blob: d74bc9b037b34a735bbdc639ca7e1534f9804974 [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>
11#include <utility>
12
13#include "testing/gtest/include/gtest/gtest.h"
14#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"
17#include "net/third_party/quiche/src/quic/platform/api/quic_string.h"
18#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
19#include "net/third_party/quiche/src/quic/test_tools/quic_stream_sequencer_buffer_peer.h"
20#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
21
22namespace quic {
23
24namespace test {
25
26char GetCharFromIOVecs(size_t offset, iovec iov[], size_t count) {
27 size_t start_offset = 0;
28 for (size_t i = 0; i < count; i++) {
29 if (iov[i].iov_len == 0) {
30 continue;
31 }
32 size_t end_offset = start_offset + iov[i].iov_len - 1;
33 if (offset >= start_offset && offset <= end_offset) {
34 const char* buf = reinterpret_cast<const char*>(iov[i].iov_base);
35 return buf[offset - start_offset];
36 }
37 start_offset += iov[i].iov_len;
38 }
39 LOG(ERROR) << "Could not locate char at offset " << offset << " in " << count
40 << " iovecs";
41 for (size_t i = 0; i < count; ++i) {
42 LOG(ERROR) << " iov[" << i << "].iov_len = " << iov[i].iov_len;
43 }
44 return '\0';
45}
46
47const size_t kMaxNumGapsAllowed = 2 * kMaxPacketGap;
48
49static const size_t kBlockSizeBytes =
50 QuicStreamSequencerBuffer::kBlockSizeBytes;
51typedef QuicStreamSequencerBuffer::BufferBlock BufferBlock;
52
53namespace {
54
55class QuicStreamSequencerBufferTest : public QuicTest {
56 public:
57 void SetUp() override { Initialize(); }
58
59 void ResetMaxCapacityBytes(size_t max_capacity_bytes) {
60 max_capacity_bytes_ = max_capacity_bytes;
61 Initialize();
62 }
63
64 protected:
65 void Initialize() {
66 buffer_ = QuicMakeUnique<QuicStreamSequencerBuffer>((max_capacity_bytes_));
67 helper_ = QuicMakeUnique<QuicStreamSequencerBufferPeer>((buffer_.get()));
68 }
69
70 // Use 2.5 here to make sure the buffer has more than one block and its end
71 // doesn't align with the end of a block in order to test all the offset
72 // calculation.
73 size_t max_capacity_bytes_ = 2.5 * kBlockSizeBytes;
74
75 std::unique_ptr<QuicStreamSequencerBuffer> buffer_;
76 std::unique_ptr<QuicStreamSequencerBufferPeer> helper_;
vasilvvc48c8712019-03-11 13:38:16 -070077 std::string error_details_;
QUICHE teama6ef0a62019-03-07 20:34:33 -050078};
79
80TEST_F(QuicStreamSequencerBufferTest, InitializeWithMaxRecvWindowSize) {
81 ResetMaxCapacityBytes(16 * 1024 * 1024); // 16MB
82 EXPECT_EQ(2 * 1024u, // 16MB / 8KB = 2K
83 helper_->block_count());
84 EXPECT_EQ(max_capacity_bytes_, helper_->max_buffer_capacity());
85 EXPECT_TRUE(helper_->CheckInitialState());
86}
87
88TEST_F(QuicStreamSequencerBufferTest, InitializationWithDifferentSizes) {
89 const size_t kCapacity = 2 * QuicStreamSequencerBuffer::kBlockSizeBytes;
90 ResetMaxCapacityBytes(kCapacity);
91 EXPECT_EQ(max_capacity_bytes_, helper_->max_buffer_capacity());
92 EXPECT_TRUE(helper_->CheckInitialState());
93
94 const size_t kCapacity1 = 8 * QuicStreamSequencerBuffer::kBlockSizeBytes;
95 ResetMaxCapacityBytes(kCapacity1);
96 EXPECT_EQ(kCapacity1, helper_->max_buffer_capacity());
97 EXPECT_TRUE(helper_->CheckInitialState());
98}
99
100TEST_F(QuicStreamSequencerBufferTest, ClearOnEmpty) {
101 buffer_->Clear();
102 EXPECT_TRUE(helper_->CheckBufferInvariants());
103}
104
105TEST_F(QuicStreamSequencerBufferTest, OnStreamData0length) {
106 size_t written;
107 QuicErrorCode error =
108 buffer_->OnStreamData(800, "", &written, &error_details_);
109 EXPECT_EQ(error, QUIC_EMPTY_STREAM_FRAME_NO_FIN);
110 EXPECT_TRUE(helper_->CheckBufferInvariants());
111}
112
113TEST_F(QuicStreamSequencerBufferTest, OnStreamDataWithinBlock) {
114 EXPECT_FALSE(helper_->IsBufferAllocated());
vasilvvc48c8712019-03-11 13:38:16 -0700115 std::string source(1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500116 size_t written;
117 EXPECT_EQ(QUIC_NO_ERROR,
118 buffer_->OnStreamData(800, source, &written, &error_details_));
119 BufferBlock* block_ptr = helper_->GetBlock(0);
120 for (size_t i = 0; i < source.size(); ++i) {
121 ASSERT_EQ('a', block_ptr->buffer[helper_->GetInBlockOffset(800) + i]);
122 }
123 EXPECT_EQ(2, helper_->IntervalSize());
124 EXPECT_EQ(0u, helper_->ReadableBytes());
125 EXPECT_EQ(1u, helper_->bytes_received().Size());
126 EXPECT_EQ(800u, helper_->bytes_received().begin()->min());
127 EXPECT_EQ(1824u, helper_->bytes_received().begin()->max());
128 EXPECT_TRUE(helper_->CheckBufferInvariants());
129 EXPECT_TRUE(helper_->IsBufferAllocated());
130}
131
132TEST_F(QuicStreamSequencerBufferTest, Move) {
133 EXPECT_FALSE(helper_->IsBufferAllocated());
vasilvvc48c8712019-03-11 13:38:16 -0700134 std::string source(1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500135 size_t written;
136 EXPECT_EQ(QUIC_NO_ERROR,
137 buffer_->OnStreamData(800, source, &written, &error_details_));
138 BufferBlock* block_ptr = helper_->GetBlock(0);
139 for (size_t i = 0; i < source.size(); ++i) {
140 ASSERT_EQ('a', block_ptr->buffer[helper_->GetInBlockOffset(800) + i]);
141 }
142
143 QuicStreamSequencerBuffer buffer2(std::move(*buffer_));
144 QuicStreamSequencerBufferPeer helper2(&buffer2);
145
146 EXPECT_FALSE(helper_->IsBufferAllocated());
147
148 EXPECT_EQ(2, helper2.IntervalSize());
149 EXPECT_EQ(0u, helper2.ReadableBytes());
150 EXPECT_EQ(1u, helper2.bytes_received().Size());
151 EXPECT_EQ(800u, helper2.bytes_received().begin()->min());
152 EXPECT_EQ(1824u, helper2.bytes_received().begin()->max());
153 EXPECT_TRUE(helper2.CheckBufferInvariants());
154 EXPECT_TRUE(helper2.IsBufferAllocated());
155}
156
157TEST_F(QuicStreamSequencerBufferTest, OnStreamDataInvalidSource) {
158 // Pass in an invalid source, expects to return error.
159 QuicStringPiece source;
160 source = QuicStringPiece(nullptr, 1024);
161 size_t written;
162 EXPECT_EQ(QUIC_STREAM_SEQUENCER_INVALID_STATE,
163 buffer_->OnStreamData(800, source, &written, &error_details_));
164 EXPECT_EQ(0u, error_details_.find(QuicStrCat(
165 "QuicStreamSequencerBuffer error: OnStreamData() "
166 "dest == nullptr: ",
167 false, " source == nullptr: ", true)));
168}
169
170TEST_F(QuicStreamSequencerBufferTest, OnStreamDataWithOverlap) {
vasilvvc48c8712019-03-11 13:38:16 -0700171 std::string source(1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500172 // Write something into [800, 1824)
173 size_t written;
174 EXPECT_EQ(QUIC_NO_ERROR,
175 buffer_->OnStreamData(800, source, &written, &error_details_));
176 // Try to write to [0, 1024) and [1024, 2048).
177 EXPECT_EQ(QUIC_NO_ERROR,
178 buffer_->OnStreamData(0, source, &written, &error_details_));
179 EXPECT_EQ(QUIC_NO_ERROR,
180 buffer_->OnStreamData(1024, source, &written, &error_details_));
181}
182
183TEST_F(QuicStreamSequencerBufferTest,
184 OnStreamDataOverlapAndDuplicateCornerCases) {
vasilvvc48c8712019-03-11 13:38:16 -0700185 std::string source(1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500186 // Write something into [800, 1824)
187 size_t written;
188 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).
192 EXPECT_EQ(QUIC_NO_ERROR,
193 buffer_->OnStreamData(1, source, &written, &error_details_));
194 // Write [0, 800).
195 EXPECT_EQ(QUIC_NO_ERROR,
196 buffer_->OnStreamData(0, source, &written, &error_details_));
197 // Write [1823, 1824).
198 EXPECT_EQ(QUIC_NO_ERROR,
199 buffer_->OnStreamData(1823, one_byte, &written, &error_details_));
200 EXPECT_EQ(0u, written);
201 // write one byte to [1824, 1825)
202 EXPECT_EQ(QUIC_NO_ERROR,
203 buffer_->OnStreamData(1824, one_byte, &written, &error_details_));
204 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).
210 size_t written;
211 EXPECT_EQ(QUIC_NO_ERROR,
212 buffer_->OnStreamData(800, source, &written, &error_details_));
vasilvvc48c8712019-03-11 13:38:16 -0700213 source = std::string(100, 'b');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500214 // Write something into [kBlockSizeBytes * 2 - 20, kBlockSizeBytes * 2 + 80).
215 EXPECT_EQ(QUIC_NO_ERROR,
216 buffer_->OnStreamData(kBlockSizeBytes * 2 - 20, source, &written,
217 &error_details_));
218 EXPECT_EQ(3, helper_->IntervalSize());
219 EXPECT_EQ(1024u + 100u, buffer_->BytesBuffered());
220 EXPECT_TRUE(helper_->CheckBufferInvariants());
221}
222
223TEST_F(QuicStreamSequencerBufferTest, OnStreamDataInLongStreamWithOverlap) {
224 // Assume a stream has already buffered almost 4GB.
225 uint64_t total_bytes_read = pow(2, 32) - 1;
226 helper_->set_total_bytes_read(total_bytes_read);
227 helper_->AddBytesReceived(0, total_bytes_read);
228
229 // Three new out of order frames arrive.
230 const size_t kBytesToWrite = 100;
vasilvvc48c8712019-03-11 13:38:16 -0700231 std::string source(kBytesToWrite, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500232 size_t written;
233 // Frame [2^32 + 500, 2^32 + 600).
234 QuicStreamOffset offset = pow(2, 32) + 500;
235 EXPECT_EQ(QUIC_NO_ERROR,
236 buffer_->OnStreamData(offset, source, &written, &error_details_));
237 EXPECT_EQ(2, helper_->IntervalSize());
238
239 // Frame [2^32 + 700, 2^32 + 800).
240 offset = pow(2, 32) + 700;
241 EXPECT_EQ(QUIC_NO_ERROR,
242 buffer_->OnStreamData(offset, source, &written, &error_details_));
243 EXPECT_EQ(3, helper_->IntervalSize());
244
245 // Another frame [2^32 + 300, 2^32 + 400).
246 offset = pow(2, 32) + 300;
247 EXPECT_EQ(QUIC_NO_ERROR,
248 buffer_->OnStreamData(offset, source, &written, &error_details_));
249 EXPECT_EQ(4, helper_->IntervalSize());
250}
251
252TEST_F(QuicStreamSequencerBufferTest, OnStreamDataTillEnd) {
253 // Write 50 bytes to the end.
254 const size_t kBytesToWrite = 50;
vasilvvc48c8712019-03-11 13:38:16 -0700255 std::string source(kBytesToWrite, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500256 size_t written;
257 EXPECT_EQ(QUIC_NO_ERROR,
258 buffer_->OnStreamData(max_capacity_bytes_ - kBytesToWrite, source,
259 &written, &error_details_));
260 EXPECT_EQ(50u, buffer_->BytesBuffered());
261 EXPECT_TRUE(helper_->CheckBufferInvariants());
262}
263
264TEST_F(QuicStreamSequencerBufferTest, OnStreamDataTillEndCorner) {
265 // Write 1 byte to the end.
266 const size_t kBytesToWrite = 1;
vasilvvc48c8712019-03-11 13:38:16 -0700267 std::string source(kBytesToWrite, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500268 size_t written;
269 EXPECT_EQ(QUIC_NO_ERROR,
270 buffer_->OnStreamData(max_capacity_bytes_ - kBytesToWrite, source,
271 &written, &error_details_));
272 EXPECT_EQ(1u, buffer_->BytesBuffered());
273 EXPECT_TRUE(helper_->CheckBufferInvariants());
274}
275
276TEST_F(QuicStreamSequencerBufferTest, OnStreamDataBeyondCapacity) {
vasilvvc48c8712019-03-11 13:38:16 -0700277 std::string source(60, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500278 size_t written;
279 EXPECT_EQ(QUIC_INTERNAL_ERROR,
280 buffer_->OnStreamData(max_capacity_bytes_ - 50, source, &written,
281 &error_details_));
282 EXPECT_TRUE(helper_->CheckBufferInvariants());
283
284 source = "b";
285 EXPECT_EQ(QUIC_INTERNAL_ERROR,
286 buffer_->OnStreamData(max_capacity_bytes_, source, &written,
287 &error_details_));
288 EXPECT_TRUE(helper_->CheckBufferInvariants());
289
290 EXPECT_EQ(QUIC_INTERNAL_ERROR,
291 buffer_->OnStreamData(max_capacity_bytes_ * 1000, source, &written,
292 &error_details_));
293 EXPECT_TRUE(helper_->CheckBufferInvariants());
294
295 // Disallow current_gap != gaps_.end()
296 EXPECT_EQ(QUIC_INTERNAL_ERROR,
297 buffer_->OnStreamData(static_cast<QuicStreamOffset>(-1), source,
298 &written, &error_details_));
299 EXPECT_TRUE(helper_->CheckBufferInvariants());
300
301 // Disallow offset + size overflow
302 source = "bbb";
303 EXPECT_EQ(QUIC_INTERNAL_ERROR,
304 buffer_->OnStreamData(static_cast<QuicStreamOffset>(-2), source,
305 &written, &error_details_));
306 EXPECT_TRUE(helper_->CheckBufferInvariants());
307 EXPECT_EQ(0u, buffer_->BytesBuffered());
308}
309
310TEST_F(QuicStreamSequencerBufferTest, Readv100Bytes) {
vasilvvc48c8712019-03-11 13:38:16 -0700311 std::string source(1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500312 // Write something into [kBlockSizeBytes, kBlockSizeBytes + 1024).
313 size_t written;
314 buffer_->OnStreamData(kBlockSizeBytes, source, &written, &error_details_);
315 EXPECT_FALSE(buffer_->HasBytesToRead());
vasilvvc48c8712019-03-11 13:38:16 -0700316 source = std::string(100, 'b');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500317 // Write something into [0, 100).
318 buffer_->OnStreamData(0, source, &written, &error_details_);
319 EXPECT_TRUE(buffer_->HasBytesToRead());
320 // Read into a iovec array with total capacity of 120 bytes.
321 char dest[120];
322 iovec iovecs[3]{iovec{dest, 40}, iovec{dest + 40, 40}, iovec{dest + 80, 40}};
323 size_t read;
324 EXPECT_EQ(QUIC_NO_ERROR, buffer_->Readv(iovecs, 3, &read, &error_details_));
325 QUIC_LOG(ERROR) << error_details_;
326 EXPECT_EQ(100u, read);
327 EXPECT_EQ(100u, buffer_->BytesConsumed());
vasilvvc48c8712019-03-11 13:38:16 -0700328 EXPECT_EQ(source, std::string(dest, read));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500329 // The first block should be released as its data has been read out.
330 EXPECT_EQ(nullptr, helper_->GetBlock(0));
331 EXPECT_TRUE(helper_->CheckBufferInvariants());
332}
333
334TEST_F(QuicStreamSequencerBufferTest, ReadvAcrossBlocks) {
vasilvvc48c8712019-03-11 13:38:16 -0700335 std::string source(kBlockSizeBytes + 50, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500336 // Write 1st block to full and extand 50 bytes to next block.
337 size_t written;
338 buffer_->OnStreamData(0, source, &written, &error_details_);
339 EXPECT_EQ(source.size(), helper_->ReadableBytes());
340 // Iteratively read 512 bytes from buffer_-> Overwrite dest[] each time.
341 char dest[512];
342 while (helper_->ReadableBytes()) {
343 std::fill(dest, dest + 512, 0);
344 iovec iovecs[2]{iovec{dest, 256}, iovec{dest + 256, 256}};
345 size_t read;
346 EXPECT_EQ(QUIC_NO_ERROR, buffer_->Readv(iovecs, 2, &read, &error_details_));
347 }
348 // The last read only reads the rest 50 bytes in 2nd block.
vasilvvc48c8712019-03-11 13:38:16 -0700349 EXPECT_EQ(std::string(50, 'a'), std::string(dest, 50));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500350 EXPECT_EQ(0, dest[50]) << "Dest[50] shouln't be filled.";
351 EXPECT_EQ(source.size(), buffer_->BytesConsumed());
352 EXPECT_TRUE(buffer_->Empty());
353 EXPECT_TRUE(helper_->CheckBufferInvariants());
354}
355
356TEST_F(QuicStreamSequencerBufferTest, ClearAfterRead) {
vasilvvc48c8712019-03-11 13:38:16 -0700357 std::string source(kBlockSizeBytes + 50, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500358 // Write 1st block to full with 'a'.
359 size_t written;
360 buffer_->OnStreamData(0, source, &written, &error_details_);
361 // Read first 512 bytes from buffer to make space at the beginning.
362 char dest[512]{0};
363 const iovec iov{dest, 512};
364 size_t read;
365 EXPECT_EQ(QUIC_NO_ERROR, buffer_->Readv(&iov, 1, &read, &error_details_));
366 // Clear() should make buffer empty while preserving BytesConsumed()
367 buffer_->Clear();
368 EXPECT_TRUE(buffer_->Empty());
369 EXPECT_TRUE(helper_->CheckBufferInvariants());
370}
371
372TEST_F(QuicStreamSequencerBufferTest,
373 OnStreamDataAcrossLastBlockAndFillCapacity) {
vasilvvc48c8712019-03-11 13:38:16 -0700374 std::string source(kBlockSizeBytes + 50, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500375 // Write 1st block to full with 'a'.
376 size_t written;
377 buffer_->OnStreamData(0, source, &written, &error_details_);
378 // Read first 512 bytes from buffer to make space at the beginning.
379 char dest[512]{0};
380 const iovec iov{dest, 512};
381 size_t read;
382 EXPECT_EQ(QUIC_NO_ERROR, buffer_->Readv(&iov, 1, &read, &error_details_));
383 EXPECT_EQ(source.size(), written);
384
385 // Write more than half block size of bytes in the last block with 'b', which
386 // will wrap to the beginning and reaches the full capacity.
vasilvvc48c8712019-03-11 13:38:16 -0700387 source = std::string(0.5 * kBlockSizeBytes + 512, 'b');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500388 EXPECT_EQ(QUIC_NO_ERROR, buffer_->OnStreamData(2 * kBlockSizeBytes, source,
389 &written, &error_details_));
390 EXPECT_EQ(source.size(), written);
391 EXPECT_TRUE(helper_->CheckBufferInvariants());
392}
393
394TEST_F(QuicStreamSequencerBufferTest,
395 OnStreamDataAcrossLastBlockAndExceedCapacity) {
vasilvvc48c8712019-03-11 13:38:16 -0700396 std::string source(kBlockSizeBytes + 50, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500397 // Write 1st block to full.
398 size_t written;
399 buffer_->OnStreamData(0, source, &written, &error_details_);
400 // Read first 512 bytes from buffer to make space at the beginning.
401 char dest[512]{0};
402 const iovec iov{dest, 512};
403 size_t read;
404 EXPECT_EQ(QUIC_NO_ERROR, buffer_->Readv(&iov, 1, &read, &error_details_));
405
406 // Try to write from [max_capacity_bytes_ - 0.5 * kBlockSizeBytes,
407 // max_capacity_bytes_ + 512 + 1). But last bytes exceeds current capacity.
vasilvvc48c8712019-03-11 13:38:16 -0700408 source = std::string(0.5 * kBlockSizeBytes + 512 + 1, 'b');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500409 EXPECT_EQ(QUIC_INTERNAL_ERROR,
410 buffer_->OnStreamData(2 * kBlockSizeBytes, source, &written,
411 &error_details_));
412 EXPECT_TRUE(helper_->CheckBufferInvariants());
413}
414
415TEST_F(QuicStreamSequencerBufferTest, ReadvAcrossLastBlock) {
416 // Write to full capacity and read out 512 bytes at beginning and continue
417 // appending 256 bytes.
vasilvvc48c8712019-03-11 13:38:16 -0700418 std::string source(max_capacity_bytes_, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500419 size_t written;
420 buffer_->OnStreamData(0, source, &written, &error_details_);
421 char dest[512]{0};
422 const iovec iov{dest, 512};
423 size_t read;
424 EXPECT_EQ(QUIC_NO_ERROR, buffer_->Readv(&iov, 1, &read, &error_details_));
vasilvvc48c8712019-03-11 13:38:16 -0700425 source = std::string(256, 'b');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500426 buffer_->OnStreamData(max_capacity_bytes_, source, &written, &error_details_);
427 EXPECT_TRUE(helper_->CheckBufferInvariants());
428
429 // Read all data out.
430 std::unique_ptr<char[]> dest1{new char[max_capacity_bytes_]};
431 dest1[0] = 0;
432 const iovec iov1{dest1.get(), max_capacity_bytes_};
433 EXPECT_EQ(QUIC_NO_ERROR, buffer_->Readv(&iov1, 1, &read, &error_details_));
434 EXPECT_EQ(max_capacity_bytes_ - 512 + 256, read);
435 EXPECT_EQ(max_capacity_bytes_ + 256, buffer_->BytesConsumed());
436 EXPECT_TRUE(buffer_->Empty());
437 EXPECT_TRUE(helper_->CheckBufferInvariants());
438}
439
440TEST_F(QuicStreamSequencerBufferTest, ReadvEmpty) {
441 char dest[512]{0};
442 iovec iov{dest, 512};
443 size_t read;
444 EXPECT_EQ(QUIC_NO_ERROR, buffer_->Readv(&iov, 1, &read, &error_details_));
445 EXPECT_EQ(0u, read);
446 EXPECT_TRUE(helper_->CheckBufferInvariants());
447}
448
449TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionsEmpty) {
450 iovec iovs[2];
451 int iov_count = buffer_->GetReadableRegions(iovs, 2);
452 EXPECT_EQ(0, iov_count);
453 EXPECT_EQ(nullptr, iovs[iov_count].iov_base);
454 EXPECT_EQ(0u, iovs[iov_count].iov_len);
455}
456
457TEST_F(QuicStreamSequencerBufferTest, ReleaseWholeBuffer) {
458 // Tests that buffer is not deallocated unless ReleaseWholeBuffer() is called.
vasilvvc48c8712019-03-11 13:38:16 -0700459 std::string source(100, 'b');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500460 // Write something into [0, 100).
461 size_t written;
462 buffer_->OnStreamData(0, source, &written, &error_details_);
463 EXPECT_TRUE(buffer_->HasBytesToRead());
464 char dest[120];
465 iovec iovecs[3]{iovec{dest, 40}, iovec{dest + 40, 40}, iovec{dest + 80, 40}};
466 size_t read;
467 EXPECT_EQ(QUIC_NO_ERROR, buffer_->Readv(iovecs, 3, &read, &error_details_));
468 EXPECT_EQ(100u, read);
469 EXPECT_EQ(100u, buffer_->BytesConsumed());
470 EXPECT_TRUE(helper_->CheckBufferInvariants());
471 EXPECT_TRUE(helper_->IsBufferAllocated());
472 buffer_->ReleaseWholeBuffer();
473 EXPECT_FALSE(helper_->IsBufferAllocated());
474}
475
476TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionsBlockedByGap) {
477 // Write into [1, 1024).
vasilvvc48c8712019-03-11 13:38:16 -0700478 std::string source(1023, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500479 size_t written;
480 buffer_->OnStreamData(1, source, &written, &error_details_);
481 // Try to get readable regions, but none is there.
482 iovec iovs[2];
483 int iov_count = buffer_->GetReadableRegions(iovs, 2);
484 EXPECT_EQ(0, iov_count);
485}
486
487TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionsTillEndOfBlock) {
488 // Write first block to full with [0, 256) 'a' and the rest 'b' then read out
489 // [0, 256)
vasilvvc48c8712019-03-11 13:38:16 -0700490 std::string source(kBlockSizeBytes, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500491 size_t written;
492 buffer_->OnStreamData(0, source, &written, &error_details_);
493 char dest[256];
494 helper_->Read(dest, 256);
495 // Get readable region from [256, 1024)
496 iovec iovs[2];
497 int iov_count = buffer_->GetReadableRegions(iovs, 2);
498 EXPECT_EQ(1, iov_count);
vasilvvc48c8712019-03-11 13:38:16 -0700499 EXPECT_EQ(std::string(kBlockSizeBytes - 256, 'a'),
500 std::string(reinterpret_cast<const char*>(iovs[0].iov_base),
501 iovs[0].iov_len));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500502}
503
504TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionsWithinOneBlock) {
505 // Write into [0, 1024) and then read out [0, 256)
vasilvvc48c8712019-03-11 13:38:16 -0700506 std::string source(1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500507 size_t written;
508 buffer_->OnStreamData(0, source, &written, &error_details_);
509 char dest[256];
510 helper_->Read(dest, 256);
511 // Get readable region from [256, 1024)
512 iovec iovs[2];
513 int iov_count = buffer_->GetReadableRegions(iovs, 2);
514 EXPECT_EQ(1, iov_count);
vasilvvc48c8712019-03-11 13:38:16 -0700515 EXPECT_EQ(std::string(1024 - 256, 'a'),
516 std::string(reinterpret_cast<const char*>(iovs[0].iov_base),
517 iovs[0].iov_len));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500518}
519
520TEST_F(QuicStreamSequencerBufferTest,
521 GetReadableRegionsAcrossBlockWithLongIOV) {
522 // Write into [0, 2 * kBlockSizeBytes + 1024) and then read out [0, 1024)
vasilvvc48c8712019-03-11 13:38:16 -0700523 std::string source(2 * kBlockSizeBytes + 1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500524 size_t written;
525 buffer_->OnStreamData(0, source, &written, &error_details_);
526 char dest[1024];
527 helper_->Read(dest, 1024);
528
529 iovec iovs[4];
530 int iov_count = buffer_->GetReadableRegions(iovs, 4);
531 EXPECT_EQ(3, iov_count);
532 EXPECT_EQ(kBlockSizeBytes - 1024, iovs[0].iov_len);
533 EXPECT_EQ(kBlockSizeBytes, iovs[1].iov_len);
534 EXPECT_EQ(1024u, iovs[2].iov_len);
535}
536
537TEST_F(QuicStreamSequencerBufferTest,
538 GetReadableRegionsWithMultipleIOVsAcrossEnd) {
539 // Write into [0, 2 * kBlockSizeBytes + 1024) and then read out [0, 1024)
540 // and then append 1024 + 512 bytes.
vasilvvc48c8712019-03-11 13:38:16 -0700541 std::string source(2.5 * kBlockSizeBytes - 1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500542 size_t written;
543 buffer_->OnStreamData(0, source, &written, &error_details_);
544 char dest[1024];
545 helper_->Read(dest, 1024);
546 // Write across the end.
vasilvvc48c8712019-03-11 13:38:16 -0700547 source = std::string(1024 + 512, 'b');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500548 buffer_->OnStreamData(2.5 * kBlockSizeBytes - 1024, source, &written,
549 &error_details_);
550 // Use short iovec's.
551 iovec iovs[2];
552 int iov_count = buffer_->GetReadableRegions(iovs, 2);
553 EXPECT_EQ(2, iov_count);
554 EXPECT_EQ(kBlockSizeBytes - 1024, iovs[0].iov_len);
555 EXPECT_EQ(kBlockSizeBytes, iovs[1].iov_len);
556 // Use long iovec's and wrap the end of buffer.
557 iovec iovs1[5];
558 EXPECT_EQ(4, buffer_->GetReadableRegions(iovs1, 5));
559 EXPECT_EQ(0.5 * kBlockSizeBytes, iovs1[2].iov_len);
560 EXPECT_EQ(512u, iovs1[3].iov_len);
vasilvvc48c8712019-03-11 13:38:16 -0700561 EXPECT_EQ(std::string(512, 'b'),
562 std::string(reinterpret_cast<const char*>(iovs1[3].iov_base),
563 iovs1[3].iov_len));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500564}
565
566TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionEmpty) {
567 iovec iov;
568 EXPECT_FALSE(buffer_->GetReadableRegion(&iov));
569 EXPECT_EQ(nullptr, iov.iov_base);
570 EXPECT_EQ(0u, iov.iov_len);
571}
572
573TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionBeforeGap) {
574 // Write into [1, 1024).
vasilvvc48c8712019-03-11 13:38:16 -0700575 std::string source(1023, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500576 size_t written;
577 buffer_->OnStreamData(1, source, &written, &error_details_);
578 // GetReadableRegion should return false because range [0,1) hasn't been
579 // filled yet.
580 iovec iov;
581 EXPECT_FALSE(buffer_->GetReadableRegion(&iov));
582}
583
584TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionTillEndOfBlock) {
585 // Write into [0, kBlockSizeBytes + 1) and then read out [0, 256)
vasilvvc48c8712019-03-11 13:38:16 -0700586 std::string source(kBlockSizeBytes + 1, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500587 size_t written;
588 buffer_->OnStreamData(0, source, &written, &error_details_);
589 char dest[256];
590 helper_->Read(dest, 256);
591 // Get readable region from [256, 1024)
592 iovec iov;
593 EXPECT_TRUE(buffer_->GetReadableRegion(&iov));
594 EXPECT_EQ(
vasilvvc48c8712019-03-11 13:38:16 -0700595 std::string(kBlockSizeBytes - 256, 'a'),
596 std::string(reinterpret_cast<const char*>(iov.iov_base), iov.iov_len));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500597}
598
599TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionTillGap) {
600 // Write into [0, kBlockSizeBytes - 1) and then read out [0, 256)
vasilvvc48c8712019-03-11 13:38:16 -0700601 std::string source(kBlockSizeBytes - 1, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500602 size_t written;
603 buffer_->OnStreamData(0, source, &written, &error_details_);
604 char dest[256];
605 helper_->Read(dest, 256);
606 // Get readable region from [256, 1023)
607 iovec iov;
608 EXPECT_TRUE(buffer_->GetReadableRegion(&iov));
609 EXPECT_EQ(
vasilvvc48c8712019-03-11 13:38:16 -0700610 std::string(kBlockSizeBytes - 1 - 256, 'a'),
611 std::string(reinterpret_cast<const char*>(iov.iov_base), iov.iov_len));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500612}
613
614TEST_F(QuicStreamSequencerBufferTest, PrefetchEmptyBuffer) {
615 iovec iov;
616 EXPECT_FALSE(buffer_->PrefetchNextRegion(&iov));
617}
618
619TEST_F(QuicStreamSequencerBufferTest, PrefetchInitialBuffer) {
vasilvvc48c8712019-03-11 13:38:16 -0700620 std::string source(kBlockSizeBytes, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500621 size_t written;
622 buffer_->OnStreamData(0, source, &written, &error_details_);
623 iovec iov;
624 EXPECT_TRUE(buffer_->PrefetchNextRegion(&iov));
vasilvvc48c8712019-03-11 13:38:16 -0700625 EXPECT_EQ(source, std::string(reinterpret_cast<const char*>(iov.iov_base),
626 iov.iov_len));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500627}
628
629TEST_F(QuicStreamSequencerBufferTest, PrefetchBufferWithOffset) {
vasilvvc48c8712019-03-11 13:38:16 -0700630 std::string source(1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500631 size_t written;
632 buffer_->OnStreamData(0, source, &written, &error_details_);
633 iovec iov;
634 EXPECT_TRUE(buffer_->PrefetchNextRegion(&iov));
vasilvvc48c8712019-03-11 13:38:16 -0700635 EXPECT_EQ(source, std::string(reinterpret_cast<const char*>(iov.iov_base),
636 iov.iov_len));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500637 // The second frame goes into the same bucket.
vasilvvc48c8712019-03-11 13:38:16 -0700638 std::string source2(800, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500639 buffer_->OnStreamData(1024, source2, &written, &error_details_);
640 EXPECT_TRUE(buffer_->PrefetchNextRegion(&iov));
vasilvvc48c8712019-03-11 13:38:16 -0700641 EXPECT_EQ(source2, std::string(reinterpret_cast<const char*>(iov.iov_base),
642 iov.iov_len));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500643}
644
645TEST_F(QuicStreamSequencerBufferTest, PrefetchBufferWithMultipleBucket) {
646 const size_t data_size = 1024;
vasilvvc48c8712019-03-11 13:38:16 -0700647 std::string source(data_size, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500648 size_t written;
649 buffer_->OnStreamData(0, source, &written, &error_details_);
650 iovec iov;
651 EXPECT_TRUE(buffer_->PrefetchNextRegion(&iov));
vasilvvc48c8712019-03-11 13:38:16 -0700652 EXPECT_EQ(source, std::string(reinterpret_cast<const char*>(iov.iov_base),
653 iov.iov_len));
654 std::string source2(kBlockSizeBytes, 'b');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500655 buffer_->OnStreamData(data_size, source2, &written, &error_details_);
656 EXPECT_TRUE(buffer_->PrefetchNextRegion(&iov));
657 EXPECT_EQ(
vasilvvc48c8712019-03-11 13:38:16 -0700658 std::string(kBlockSizeBytes - data_size, 'b'),
659 std::string(reinterpret_cast<const char*>(iov.iov_base), iov.iov_len));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500660 EXPECT_TRUE(buffer_->PrefetchNextRegion(&iov));
661 EXPECT_EQ(
vasilvvc48c8712019-03-11 13:38:16 -0700662 std::string(data_size, 'b'),
663 std::string(reinterpret_cast<const char*>(iov.iov_base), iov.iov_len));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500664}
665
666TEST_F(QuicStreamSequencerBufferTest, PrefetchBufferAfterBlockRetired) {
vasilvvc48c8712019-03-11 13:38:16 -0700667 std::string source(kBlockSizeBytes, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500668 size_t written;
669 buffer_->OnStreamData(0, source, &written, &error_details_);
670 iovec iov;
671 EXPECT_TRUE(buffer_->PrefetchNextRegion(&iov));
vasilvvc48c8712019-03-11 13:38:16 -0700672 EXPECT_EQ(source, std::string(reinterpret_cast<const char*>(iov.iov_base),
673 iov.iov_len));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500674 // Read the whole block so it's retired.
675 char dest[kBlockSizeBytes];
676 helper_->Read(dest, kBlockSizeBytes);
677
vasilvvc48c8712019-03-11 13:38:16 -0700678 std::string source2(300, 'b');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500679 buffer_->OnStreamData(kBlockSizeBytes, source2, &written, &error_details_);
680
681 EXPECT_TRUE(buffer_->PrefetchNextRegion(&iov));
vasilvvc48c8712019-03-11 13:38:16 -0700682 EXPECT_EQ(source2, std::string(reinterpret_cast<const char*>(iov.iov_base),
683 iov.iov_len));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500684}
685
686TEST_F(QuicStreamSequencerBufferTest, PrefetchContinously) {
vasilvvc48c8712019-03-11 13:38:16 -0700687 std::string source(kBlockSizeBytes, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500688 size_t written;
689 buffer_->OnStreamData(0, source, &written, &error_details_);
690 iovec iov;
691 EXPECT_TRUE(buffer_->PrefetchNextRegion(&iov));
vasilvvc48c8712019-03-11 13:38:16 -0700692 EXPECT_EQ(source, std::string(reinterpret_cast<const char*>(iov.iov_base),
693 iov.iov_len));
694 std::string source2(kBlockSizeBytes, 'b');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500695 buffer_->OnStreamData(kBlockSizeBytes, source2, &written, &error_details_);
696 EXPECT_TRUE(buffer_->PrefetchNextRegion(&iov));
vasilvvc48c8712019-03-11 13:38:16 -0700697 EXPECT_EQ(source2, std::string(reinterpret_cast<const char*>(iov.iov_base),
698 iov.iov_len));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500699}
700
701TEST_F(QuicStreamSequencerBufferTest, ConsumeMoreThanPrefetch) {
vasilvvc48c8712019-03-11 13:38:16 -0700702 std::string source(100, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500703 size_t written;
704 buffer_->OnStreamData(0, source, &written, &error_details_);
705 char dest[30];
706 helper_->Read(dest, 30);
707 iovec iov;
708 EXPECT_TRUE(buffer_->PrefetchNextRegion(&iov));
709 EXPECT_EQ(
vasilvvc48c8712019-03-11 13:38:16 -0700710 std::string(70, 'a'),
711 std::string(reinterpret_cast<const char*>(iov.iov_base), iov.iov_len));
712 std::string source2(100, 'b');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500713 buffer_->OnStreamData(100, source2, &written, &error_details_);
714 buffer_->MarkConsumed(100);
715 EXPECT_TRUE(buffer_->PrefetchNextRegion(&iov));
716 EXPECT_EQ(
vasilvvc48c8712019-03-11 13:38:16 -0700717 std::string(70, 'b'),
718 std::string(reinterpret_cast<const char*>(iov.iov_base), iov.iov_len));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500719}
720
721TEST_F(QuicStreamSequencerBufferTest, PrefetchMoreThanBufferHas) {
vasilvvc48c8712019-03-11 13:38:16 -0700722 std::string source(100, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500723 size_t written;
724 buffer_->OnStreamData(0, source, &written, &error_details_);
725 iovec iov;
726 EXPECT_TRUE(buffer_->PrefetchNextRegion(&iov));
727 EXPECT_EQ(
vasilvvc48c8712019-03-11 13:38:16 -0700728 std::string(100, 'a'),
729 std::string(reinterpret_cast<const char*>(iov.iov_base), iov.iov_len));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500730 EXPECT_FALSE(buffer_->PrefetchNextRegion(&iov));
731}
732
733TEST_F(QuicStreamSequencerBufferTest, MarkConsumedInOneBlock) {
734 // Write into [0, 1024) and then read out [0, 256)
vasilvvc48c8712019-03-11 13:38:16 -0700735 std::string source(1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500736 size_t written;
737 buffer_->OnStreamData(0, source, &written, &error_details_);
738 char dest[256];
739 helper_->Read(dest, 256);
740
741 EXPECT_TRUE(buffer_->MarkConsumed(512));
742 EXPECT_EQ(256u + 512u, buffer_->BytesConsumed());
743 EXPECT_EQ(256u, helper_->ReadableBytes());
744 buffer_->MarkConsumed(256);
745 EXPECT_TRUE(buffer_->Empty());
746 EXPECT_TRUE(helper_->CheckBufferInvariants());
747}
748
749TEST_F(QuicStreamSequencerBufferTest, MarkConsumedNotEnoughBytes) {
750 // Write into [0, 1024) and then read out [0, 256)
vasilvvc48c8712019-03-11 13:38:16 -0700751 std::string source(1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500752 size_t written;
753 buffer_->OnStreamData(0, source, &written, &error_details_);
754 char dest[256];
755 helper_->Read(dest, 256);
756
757 // Consume 1st 512 bytes
758 EXPECT_TRUE(buffer_->MarkConsumed(512));
759 EXPECT_EQ(256u + 512u, buffer_->BytesConsumed());
760 EXPECT_EQ(256u, helper_->ReadableBytes());
761 // Try to consume one bytes more than available. Should return false.
762 EXPECT_FALSE(buffer_->MarkConsumed(257));
763 EXPECT_EQ(256u + 512u, buffer_->BytesConsumed());
764 iovec iov;
765 EXPECT_TRUE(buffer_->GetReadableRegion(&iov));
766 EXPECT_TRUE(helper_->CheckBufferInvariants());
767}
768
769TEST_F(QuicStreamSequencerBufferTest, MarkConsumedAcrossBlock) {
770 // Write into [0, 2 * kBlockSizeBytes + 1024) and then read out [0, 1024)
vasilvvc48c8712019-03-11 13:38:16 -0700771 std::string source(2 * kBlockSizeBytes + 1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500772 size_t written;
773 buffer_->OnStreamData(0, source, &written, &error_details_);
774 char dest[1024];
775 helper_->Read(dest, 1024);
776
777 buffer_->MarkConsumed(2 * kBlockSizeBytes);
778 EXPECT_EQ(source.size(), buffer_->BytesConsumed());
779 EXPECT_TRUE(buffer_->Empty());
780 EXPECT_TRUE(helper_->CheckBufferInvariants());
781}
782
783TEST_F(QuicStreamSequencerBufferTest, MarkConsumedAcrossEnd) {
784 // Write into [0, 2.5 * kBlockSizeBytes - 1024) and then read out [0, 1024)
785 // and then append 1024 + 512 bytes.
vasilvvc48c8712019-03-11 13:38:16 -0700786 std::string source(2.5 * kBlockSizeBytes - 1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500787 size_t written;
788 buffer_->OnStreamData(0, source, &written, &error_details_);
789 char dest[1024];
790 helper_->Read(dest, 1024);
vasilvvc48c8712019-03-11 13:38:16 -0700791 source = std::string(1024 + 512, 'b');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500792 buffer_->OnStreamData(2.5 * kBlockSizeBytes - 1024, source, &written,
793 &error_details_);
794 EXPECT_EQ(1024u, buffer_->BytesConsumed());
795
796 // Consume to the end of 2nd block.
797 buffer_->MarkConsumed(2 * kBlockSizeBytes - 1024);
798 EXPECT_EQ(2 * kBlockSizeBytes, buffer_->BytesConsumed());
799 // Consume across the physical end of buffer
800 buffer_->MarkConsumed(0.5 * kBlockSizeBytes + 500);
801 EXPECT_EQ(max_capacity_bytes_ + 500, buffer_->BytesConsumed());
802 EXPECT_EQ(12u, helper_->ReadableBytes());
803 // Consume to the logical end of buffer
804 buffer_->MarkConsumed(12);
805 EXPECT_EQ(max_capacity_bytes_ + 512, buffer_->BytesConsumed());
806 EXPECT_TRUE(buffer_->Empty());
807 EXPECT_TRUE(helper_->CheckBufferInvariants());
808}
809
810TEST_F(QuicStreamSequencerBufferTest, FlushBufferedFrames) {
811 // Write into [0, 2.5 * kBlockSizeBytes - 1024) and then read out [0, 1024).
vasilvvc48c8712019-03-11 13:38:16 -0700812 std::string source(max_capacity_bytes_ - 1024, 'a');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500813 size_t written;
814 buffer_->OnStreamData(0, source, &written, &error_details_);
815 char dest[1024];
816 helper_->Read(dest, 1024);
817 EXPECT_EQ(1024u, buffer_->BytesConsumed());
818 // Write [1024, 512) to the physical beginning.
vasilvvc48c8712019-03-11 13:38:16 -0700819 source = std::string(512, 'b');
QUICHE teama6ef0a62019-03-07 20:34:33 -0500820 buffer_->OnStreamData(max_capacity_bytes_, source, &written, &error_details_);
821 EXPECT_EQ(512u, written);
822 EXPECT_EQ(max_capacity_bytes_ - 1024 + 512, buffer_->FlushBufferedFrames());
823 EXPECT_EQ(max_capacity_bytes_ + 512, buffer_->BytesConsumed());
824 EXPECT_TRUE(buffer_->Empty());
825 EXPECT_TRUE(helper_->CheckBufferInvariants());
826 // Clear buffer at this point should still preserve BytesConsumed().
827 buffer_->Clear();
828 EXPECT_EQ(max_capacity_bytes_ + 512, buffer_->BytesConsumed());
829 EXPECT_TRUE(helper_->CheckBufferInvariants());
830}
831
832TEST_F(QuicStreamSequencerBufferTest, TooManyGaps) {
833 // Make sure max capacity is large enough that it is possible to have more
834 // than |kMaxNumGapsAllowed| number of gaps.
835 max_capacity_bytes_ = 3 * kBlockSizeBytes;
836 // Feed buffer with 1-byte discontiguous frames. e.g. [1,2), [3,4), [5,6)...
837 for (QuicStreamOffset begin = 1; begin <= max_capacity_bytes_; begin += 2) {
838 size_t written;
839 QuicErrorCode rs =
840 buffer_->OnStreamData(begin, "a", &written, &error_details_);
841
842 QuicStreamOffset last_straw = 2 * kMaxNumGapsAllowed - 1;
843 if (begin == last_straw) {
844 EXPECT_EQ(QUIC_TOO_MANY_STREAM_DATA_INTERVALS, rs);
845 EXPECT_EQ("Too many data intervals received for this stream.",
846 error_details_);
847 break;
848 }
849 }
850}
851
852class QuicStreamSequencerBufferRandomIOTest
853 : public QuicStreamSequencerBufferTest {
854 public:
855 typedef std::pair<QuicStreamOffset, size_t> OffsetSizePair;
856
857 void SetUp() override {
858 // Test against a larger capacity then above tests. Also make sure the last
859 // block is partially available to use.
860 max_capacity_bytes_ = 6.25 * kBlockSizeBytes;
861 // Stream to be buffered should be larger than the capacity to test wrap
862 // around.
863 bytes_to_buffer_ = 2 * max_capacity_bytes_;
864 Initialize();
865
866 uint64_t seed = QuicRandom::GetInstance()->RandUint64();
867 QUIC_LOG(INFO) << "**** The current seed is " << seed << " ****";
868 rng_.set_seed(seed);
869 }
870
871 // Create an out-of-order source stream with given size to populate
872 // shuffled_buf_.
873 void CreateSourceAndShuffle(size_t max_chunk_size_bytes) {
874 max_chunk_size_bytes_ = max_chunk_size_bytes;
875 std::unique_ptr<OffsetSizePair[]> chopped_stream(
876 new OffsetSizePair[bytes_to_buffer_]);
877
878 // Split stream into small chunks with random length. chopped_stream will be
879 // populated with segmented stream chunks.
880 size_t start_chopping_offset = 0;
881 size_t iterations = 0;
882 while (start_chopping_offset < bytes_to_buffer_) {
883 size_t max_chunk = std::min<size_t>(
884 max_chunk_size_bytes_, bytes_to_buffer_ - start_chopping_offset);
885 size_t chunk_size = rng_.RandUint64() % max_chunk + 1;
886 chopped_stream[iterations] =
887 OffsetSizePair(start_chopping_offset, chunk_size);
888 start_chopping_offset += chunk_size;
889 ++iterations;
890 }
891 DCHECK(start_chopping_offset == bytes_to_buffer_);
892 size_t chunk_num = iterations;
893
894 // Randomly change the sequence of in-ordered OffsetSizePairs to make a
895 // out-of-order array of OffsetSizePairs.
896 for (int i = chunk_num - 1; i >= 0; --i) {
897 size_t random_idx = rng_.RandUint64() % (i + 1);
898 QUIC_DVLOG(1) << "chunk offset " << chopped_stream[random_idx].first
899 << " size " << chopped_stream[random_idx].second;
900 shuffled_buf_.push_front(chopped_stream[random_idx]);
901 chopped_stream[random_idx] = chopped_stream[i];
902 }
903 }
904
905 // Write the currently first chunk of data in the out-of-order stream into
906 // QuicStreamSequencerBuffer. If current chuck cannot be written into buffer
907 // because it goes beyond current capacity, move it to the end of
908 // shuffled_buf_ and write it later.
909 void WriteNextChunkToBuffer() {
910 OffsetSizePair& chunk = shuffled_buf_.front();
911 QuicStreamOffset offset = chunk.first;
912 const size_t num_to_write = chunk.second;
913 std::unique_ptr<char[]> write_buf{new char[max_chunk_size_bytes_]};
914 for (size_t i = 0; i < num_to_write; ++i) {
915 write_buf[i] = (offset + i) % 256;
916 }
917 QuicStringPiece string_piece_w(write_buf.get(), num_to_write);
918 size_t written;
919 auto result = buffer_->OnStreamData(offset, string_piece_w, &written,
920 &error_details_);
921 if (result == QUIC_NO_ERROR) {
922 shuffled_buf_.pop_front();
923 total_bytes_written_ += num_to_write;
924 } else {
925 // This chunk offset exceeds window size.
926 shuffled_buf_.push_back(chunk);
927 shuffled_buf_.pop_front();
928 }
929 QUIC_DVLOG(1) << " write at offset: " << offset
930 << " len to write: " << num_to_write
931 << " write result: " << result
932 << " left over: " << shuffled_buf_.size();
933 }
934
935 protected:
936 std::list<OffsetSizePair> shuffled_buf_;
937 size_t max_chunk_size_bytes_;
938 QuicStreamOffset bytes_to_buffer_;
939 size_t total_bytes_written_ = 0;
940 size_t total_bytes_read_ = 0;
941 SimpleRandom rng_;
942};
943
944TEST_F(QuicStreamSequencerBufferRandomIOTest, RandomWriteAndReadv) {
945 // Set kMaxReadSize larger than kBlockSizeBytes to test both small and large
946 // read.
947 const size_t kMaxReadSize = kBlockSizeBytes * 2;
948 // kNumReads is larger than 1 to test how multiple read destinations work.
949 const size_t kNumReads = 2;
950 // Since write and read operation have equal possibility to be called. Bytes
951 // to be written into and read out of should roughly the same.
952 const size_t kMaxWriteSize = kNumReads * kMaxReadSize;
953 size_t iterations = 0;
954
955 CreateSourceAndShuffle(kMaxWriteSize);
956
957 while ((!shuffled_buf_.empty() || total_bytes_read_ < bytes_to_buffer_) &&
958 iterations <= 2 * bytes_to_buffer_) {
959 uint8_t next_action =
960 shuffled_buf_.empty() ? uint8_t{1} : rng_.RandUint64() % 2;
961 QUIC_DVLOG(1) << "iteration: " << iterations;
962 switch (next_action) {
963 case 0: { // write
964 WriteNextChunkToBuffer();
965 ASSERT_TRUE(helper_->CheckBufferInvariants());
966 break;
967 }
968 case 1: { // readv
969 std::unique_ptr<char[][kMaxReadSize]> read_buf{
970 new char[kNumReads][kMaxReadSize]};
971 iovec dest_iov[kNumReads];
972 size_t num_to_read = 0;
973 for (size_t i = 0; i < kNumReads; ++i) {
974 dest_iov[i].iov_base =
975 reinterpret_cast<void*>(const_cast<char*>(read_buf[i]));
976 dest_iov[i].iov_len = rng_.RandUint64() % kMaxReadSize;
977 num_to_read += dest_iov[i].iov_len;
978 }
979 size_t actually_read;
980 EXPECT_EQ(QUIC_NO_ERROR,
981 buffer_->Readv(dest_iov, kNumReads, &actually_read,
982 &error_details_));
983 ASSERT_LE(actually_read, num_to_read);
984 QUIC_DVLOG(1) << " read from offset: " << total_bytes_read_
985 << " size: " << num_to_read
986 << " actual read: " << actually_read;
987 for (size_t i = 0; i < actually_read; ++i) {
988 char ch = (i + total_bytes_read_) % 256;
989 ASSERT_EQ(ch, GetCharFromIOVecs(i, dest_iov, kNumReads))
990 << " at iteration " << iterations;
991 }
992 total_bytes_read_ += actually_read;
993 ASSERT_EQ(total_bytes_read_, buffer_->BytesConsumed());
994 ASSERT_TRUE(helper_->CheckBufferInvariants());
995 break;
996 }
997 }
998 ++iterations;
999 ASSERT_LE(total_bytes_read_, total_bytes_written_);
1000 }
1001 EXPECT_LT(iterations, bytes_to_buffer_) << "runaway test";
1002 EXPECT_LE(bytes_to_buffer_, total_bytes_read_)
1003 << "iterations: " << iterations;
1004 EXPECT_LE(bytes_to_buffer_, total_bytes_written_);
1005}
1006
1007TEST_F(QuicStreamSequencerBufferRandomIOTest, RandomWriteAndConsumeInPlace) {
1008 // The value 4 is chosen such that the max write size is no larger than the
1009 // maximum buffer capacity.
1010 const size_t kMaxNumReads = 4;
1011 // Adjust write amount be roughly equal to that GetReadableRegions() can get.
1012 const size_t kMaxWriteSize = kMaxNumReads * kBlockSizeBytes;
1013 ASSERT_LE(kMaxWriteSize, max_capacity_bytes_);
1014 size_t iterations = 0;
1015
1016 CreateSourceAndShuffle(kMaxWriteSize);
1017
1018 while ((!shuffled_buf_.empty() || total_bytes_read_ < bytes_to_buffer_) &&
1019 iterations <= 2 * bytes_to_buffer_) {
1020 uint8_t next_action =
1021 shuffled_buf_.empty() ? uint8_t{1} : rng_.RandUint64() % 2;
1022 QUIC_DVLOG(1) << "iteration: " << iterations;
1023 switch (next_action) {
1024 case 0: { // write
1025 WriteNextChunkToBuffer();
1026 ASSERT_TRUE(helper_->CheckBufferInvariants());
1027 break;
1028 }
1029 case 1: { // GetReadableRegions and then MarkConsumed
1030 size_t num_read = rng_.RandUint64() % kMaxNumReads + 1;
1031 iovec dest_iov[kMaxNumReads];
1032 ASSERT_TRUE(helper_->CheckBufferInvariants());
1033 size_t actually_num_read =
1034 buffer_->GetReadableRegions(dest_iov, num_read);
1035 ASSERT_LE(actually_num_read, num_read);
1036 size_t avail_bytes = 0;
1037 for (size_t i = 0; i < actually_num_read; ++i) {
1038 avail_bytes += dest_iov[i].iov_len;
1039 }
1040 // process random number of bytes (check the value of each byte).
1041 size_t bytes_to_process = rng_.RandUint64() % (avail_bytes + 1);
1042 size_t bytes_processed = 0;
1043 for (size_t i = 0; i < actually_num_read; ++i) {
1044 size_t bytes_in_block = std::min<size_t>(
1045 bytes_to_process - bytes_processed, dest_iov[i].iov_len);
1046 if (bytes_in_block == 0) {
1047 break;
1048 }
1049 for (size_t j = 0; j < bytes_in_block; ++j) {
1050 ASSERT_LE(bytes_processed, bytes_to_process);
1051 char char_expected =
1052 (buffer_->BytesConsumed() + bytes_processed) % 256;
1053 ASSERT_EQ(char_expected,
1054 reinterpret_cast<const char*>(dest_iov[i].iov_base)[j])
1055 << " at iteration " << iterations;
1056 ++bytes_processed;
1057 }
1058 }
1059
1060 buffer_->MarkConsumed(bytes_processed);
1061
1062 QUIC_DVLOG(1) << "iteration " << iterations << ": try to get "
1063 << num_read << " readable regions, actually get "
1064 << actually_num_read
1065 << " from offset: " << total_bytes_read_
1066 << "\nprocesse bytes: " << bytes_processed;
1067 total_bytes_read_ += bytes_processed;
1068 ASSERT_EQ(total_bytes_read_, buffer_->BytesConsumed());
1069 ASSERT_TRUE(helper_->CheckBufferInvariants());
1070 break;
1071 }
1072 }
1073 ++iterations;
1074 ASSERT_LE(total_bytes_read_, total_bytes_written_);
1075 }
1076 EXPECT_LT(iterations, bytes_to_buffer_) << "runaway test";
1077 EXPECT_LE(bytes_to_buffer_, total_bytes_read_)
1078 << "iterations: " << iterations;
1079 EXPECT_LE(bytes_to_buffer_, total_bytes_written_);
1080}
1081
1082} // anonymous namespace
1083
1084} // namespace test
1085
1086} // namespace quic