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