blob: b3bf224df4e662e01f06339991cf45be2eadec6d [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright 2016 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/test_tools/quic_stream_sequencer_buffer_peer.h"
6
7#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
8#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
9#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
bnca6cd6882019-11-27 08:46:01 -080010#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050011
12typedef quic::QuicStreamSequencerBuffer::BufferBlock BufferBlock;
13
14static const size_t kBlockSizeBytes =
15 quic::QuicStreamSequencerBuffer::kBlockSizeBytes;
16
17namespace quic {
18namespace test {
19
20QuicStreamSequencerBufferPeer::QuicStreamSequencerBufferPeer(
21 QuicStreamSequencerBuffer* buffer)
22 : buffer_(buffer) {}
23
24// Read from this buffer_ into the given destination buffer_ up to the
25// size of the destination. Returns the number of bytes read. Reading from
26// an empty buffer_->returns 0.
27size_t QuicStreamSequencerBufferPeer::Read(char* dest_buffer, size_t size) {
28 iovec dest;
29 dest.iov_base = dest_buffer, dest.iov_len = size;
30 size_t bytes_read;
vasilvvc48c8712019-03-11 13:38:16 -070031 std::string error_details;
bnca6cd6882019-11-27 08:46:01 -080032 EXPECT_THAT(buffer_->Readv(&dest, 1, &bytes_read, &error_details),
33 IsQuicNoError());
QUICHE teama6ef0a62019-03-07 20:34:33 -050034 return bytes_read;
35}
36
37// If buffer is empty, the blocks_ array must be empty, which means all
38// blocks are deallocated.
39bool QuicStreamSequencerBufferPeer::CheckEmptyInvariants() {
40 return !buffer_->Empty() || IsBlockArrayEmpty();
41}
42
43bool QuicStreamSequencerBufferPeer::IsBlockArrayEmpty() {
44 if (buffer_->blocks_ == nullptr) {
45 return true;
46 }
47
48 size_t count = buffer_->blocks_count_;
49 for (size_t i = 0; i < count; i++) {
50 if (buffer_->blocks_[i] != nullptr) {
51 return false;
52 }
53 }
54 return true;
55}
56
57bool QuicStreamSequencerBufferPeer::CheckInitialState() {
58 EXPECT_TRUE(buffer_->Empty() && buffer_->total_bytes_read_ == 0 &&
59 buffer_->num_bytes_buffered_ == 0);
60 return CheckBufferInvariants();
61}
62
63bool QuicStreamSequencerBufferPeer::CheckBufferInvariants() {
64 QuicStreamOffset data_span =
65 buffer_->NextExpectedByte() - buffer_->total_bytes_read_;
66 bool capacity_sane = data_span <= buffer_->max_buffer_capacity_bytes_ &&
67 data_span >= buffer_->num_bytes_buffered_;
68 if (!capacity_sane) {
69 QUIC_LOG(ERROR) << "data span is larger than capacity.";
70 QUIC_LOG(ERROR) << "total read: " << buffer_->total_bytes_read_
71 << " last byte: " << buffer_->NextExpectedByte();
72 }
73 bool total_read_sane =
74 buffer_->FirstMissingByte() >= buffer_->total_bytes_read_;
75 if (!total_read_sane) {
76 QUIC_LOG(ERROR) << "read across 1st gap.";
77 }
78 bool read_offset_sane = buffer_->ReadOffset() < kBlockSizeBytes;
79 if (!capacity_sane) {
80 QUIC_LOG(ERROR) << "read offset go beyond 1st block";
81 }
82 bool block_match_capacity = (buffer_->max_buffer_capacity_bytes_ <=
83 buffer_->blocks_count_ * kBlockSizeBytes) &&
84 (buffer_->max_buffer_capacity_bytes_ >
85 (buffer_->blocks_count_ - 1) * kBlockSizeBytes);
86 if (!capacity_sane) {
87 QUIC_LOG(ERROR) << "block number not match capcaity.";
88 }
89 bool block_retired_when_empty = CheckEmptyInvariants();
90 if (!block_retired_when_empty) {
91 QUIC_LOG(ERROR) << "block is not retired after use.";
92 }
93 return capacity_sane && total_read_sane && read_offset_sane &&
94 block_match_capacity && block_retired_when_empty;
95}
96
97size_t QuicStreamSequencerBufferPeer::GetInBlockOffset(
98 QuicStreamOffset offset) {
99 return buffer_->GetInBlockOffset(offset);
100}
101
102BufferBlock* QuicStreamSequencerBufferPeer::GetBlock(size_t index) {
103 return buffer_->blocks_[index];
104}
105
106int QuicStreamSequencerBufferPeer::IntervalSize() {
107 if (buffer_->bytes_received_.Empty()) {
108 return 1;
109 }
110 int gap_size = buffer_->bytes_received_.Size() + 1;
111 if (buffer_->bytes_received_.Empty()) {
112 return gap_size;
113 }
114 if (buffer_->bytes_received_.begin()->min() == 0) {
115 --gap_size;
116 }
117 if (buffer_->bytes_received_.rbegin()->max() ==
118 std::numeric_limits<uint64_t>::max()) {
119 --gap_size;
120 }
121 return gap_size;
122}
123
124size_t QuicStreamSequencerBufferPeer::max_buffer_capacity() {
125 return buffer_->max_buffer_capacity_bytes_;
126}
127
128size_t QuicStreamSequencerBufferPeer::ReadableBytes() {
129 return buffer_->ReadableBytes();
130}
131
132void QuicStreamSequencerBufferPeer::set_total_bytes_read(
133 QuicStreamOffset total_bytes_read) {
134 buffer_->total_bytes_read_ = total_bytes_read;
135}
136
137void QuicStreamSequencerBufferPeer::AddBytesReceived(QuicStreamOffset offset,
138 QuicByteCount length) {
139 buffer_->bytes_received_.Add(offset, offset + length);
140}
141
142bool QuicStreamSequencerBufferPeer::IsBufferAllocated() {
143 return buffer_->blocks_ != nullptr;
144}
145
146size_t QuicStreamSequencerBufferPeer::block_count() {
147 return buffer_->blocks_count_;
148}
149
150const QuicIntervalSet<QuicStreamOffset>&
151QuicStreamSequencerBufferPeer::bytes_received() {
152 return buffer_->bytes_received_;
153}
154
155} // namespace test
156} // namespace quic