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