OLD | NEW |
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. | 1 // 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 #include "net/quic/core/quic_stream_sequencer_buffer.h" | 4 #include "net/quic/core/quic_stream_sequencer_buffer.h" |
5 | 5 |
6 #include <algorithm> | 6 #include <algorithm> |
7 #include <limits> | 7 #include <limits> |
8 #include <map> | 8 #include <map> |
9 #include <string> | 9 #include <string> |
10 #include <utility> | 10 #include <utility> |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
53 QuicStreamSequencerBuffer::kBlockSizeBytes; | 53 QuicStreamSequencerBuffer::kBlockSizeBytes; |
54 typedef QuicStreamSequencerBuffer::BufferBlock BufferBlock; | 54 typedef QuicStreamSequencerBuffer::BufferBlock BufferBlock; |
55 typedef QuicStreamSequencerBuffer::Gap Gap; | 55 typedef QuicStreamSequencerBuffer::Gap Gap; |
56 typedef QuicStreamSequencerBuffer::FrameInfo FrameInfo; | 56 typedef QuicStreamSequencerBuffer::FrameInfo FrameInfo; |
57 | 57 |
58 class QuicStreamSequencerBufferPeer { | 58 class QuicStreamSequencerBufferPeer { |
59 public: | 59 public: |
60 explicit QuicStreamSequencerBufferPeer(QuicStreamSequencerBuffer* buffer) | 60 explicit QuicStreamSequencerBufferPeer(QuicStreamSequencerBuffer* buffer) |
61 : buffer_(buffer) {} | 61 : buffer_(buffer) {} |
62 | 62 |
63 // Read from this buffer_->into the given destination buffer_-> up to the | 63 // Read from this buffer_ into the given destination buffer_ up to the |
64 // size of the destination. Returns the number of bytes read. Reading from | 64 // size of the destination. Returns the number of bytes read. Reading from |
65 // an empty buffer_->returns 0. | 65 // an empty buffer_->returns 0. |
66 size_t Read(char* dest_buffer, size_t size) { | 66 size_t Read(char* dest_buffer, size_t size) { |
67 iovec dest; | 67 iovec dest; |
68 dest.iov_base = dest_buffer, dest.iov_len = size; | 68 dest.iov_base = dest_buffer, dest.iov_len = size; |
69 return buffer_->Readv(&dest, 1); | 69 return buffer_->Readv(&dest, 1); |
70 } | 70 } |
71 | 71 |
72 // If buffer is empty, the blocks_ array must be empty, which means all | 72 // If buffer is empty, the blocks_ array must be empty, which means all |
73 // blocks are deallocated. | 73 // blocks are deallocated. |
74 bool CheckEmptyInvariants() { | 74 bool CheckEmptyInvariants() { |
75 return !buffer_->Empty() || IsBlockArrayEmpty(); | 75 return !buffer_->Empty() || IsBlockArrayEmpty(); |
76 } | 76 } |
77 | 77 |
78 bool IsBlockArrayEmpty() { | 78 bool IsBlockArrayEmpty() { |
| 79 if (FLAGS_quic_reduce_sequencer_buffer_memory_life_time && // NOLINT |
| 80 buffer_->blocks_ == nullptr) { |
| 81 return true; |
| 82 } |
| 83 |
79 size_t count = buffer_->blocks_count_; | 84 size_t count = buffer_->blocks_count_; |
80 for (size_t i = 0; i < count; i++) { | 85 for (size_t i = 0; i < count; i++) { |
81 if (buffer_->blocks_[i] != nullptr) { | 86 if (buffer_->blocks_[i] != nullptr) { |
82 return false; | 87 return false; |
83 } | 88 } |
84 } | 89 } |
85 return true; | 90 return true; |
86 } | 91 } |
87 | 92 |
88 bool CheckInitialState() { | 93 bool CheckInitialState() { |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
143 std::map<QuicStreamOffset, FrameInfo>* frame_arrival_time_map() { | 148 std::map<QuicStreamOffset, FrameInfo>* frame_arrival_time_map() { |
144 return &(buffer_->frame_arrival_time_map_); | 149 return &(buffer_->frame_arrival_time_map_); |
145 } | 150 } |
146 | 151 |
147 void set_total_bytes_read(QuicStreamOffset total_bytes_read) { | 152 void set_total_bytes_read(QuicStreamOffset total_bytes_read) { |
148 buffer_->total_bytes_read_ = total_bytes_read; | 153 buffer_->total_bytes_read_ = total_bytes_read; |
149 } | 154 } |
150 | 155 |
151 void set_gaps(const std::list<Gap>& gaps) { buffer_->gaps_ = gaps; } | 156 void set_gaps(const std::list<Gap>& gaps) { buffer_->gaps_ = gaps; } |
152 | 157 |
| 158 bool IsBufferAllocated() { return buffer_->blocks_ != nullptr; } |
| 159 |
153 private: | 160 private: |
154 QuicStreamSequencerBuffer* buffer_; | 161 QuicStreamSequencerBuffer* buffer_; |
155 }; | 162 }; |
156 | 163 |
157 namespace { | 164 namespace { |
158 | 165 |
159 class QuicStreamSequencerBufferTest : public testing::Test { | 166 class QuicStreamSequencerBufferTest : public testing::Test { |
160 public: | 167 public: |
161 void SetUp() override { Initialize(); } | 168 void SetUp() override { Initialize(); } |
162 | 169 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 | 208 |
202 TEST_F(QuicStreamSequencerBufferTest, OnStreamData0length) { | 209 TEST_F(QuicStreamSequencerBufferTest, OnStreamData0length) { |
203 size_t written; | 210 size_t written; |
204 QuicErrorCode error = buffer_->OnStreamData(800, "", clock_.ApproximateNow(), | 211 QuicErrorCode error = buffer_->OnStreamData(800, "", clock_.ApproximateNow(), |
205 &written, &error_details_); | 212 &written, &error_details_); |
206 EXPECT_EQ(error, QUIC_EMPTY_STREAM_FRAME_NO_FIN); | 213 EXPECT_EQ(error, QUIC_EMPTY_STREAM_FRAME_NO_FIN); |
207 EXPECT_TRUE(helper_->CheckBufferInvariants()); | 214 EXPECT_TRUE(helper_->CheckBufferInvariants()); |
208 } | 215 } |
209 | 216 |
210 TEST_F(QuicStreamSequencerBufferTest, OnStreamDataWithinBlock) { | 217 TEST_F(QuicStreamSequencerBufferTest, OnStreamDataWithinBlock) { |
| 218 if (FLAGS_quic_reduce_sequencer_buffer_memory_life_time) { // NOLINT |
| 219 EXPECT_FALSE(helper_->IsBufferAllocated()); |
| 220 } |
211 string source(1024, 'a'); | 221 string source(1024, 'a'); |
212 size_t written; | 222 size_t written; |
213 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); | 223 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); |
214 QuicTime t = clock_.ApproximateNow(); | 224 QuicTime t = clock_.ApproximateNow(); |
215 EXPECT_EQ(QUIC_NO_ERROR, | 225 EXPECT_EQ(QUIC_NO_ERROR, |
216 buffer_->OnStreamData(800, source, t, &written, &error_details_)); | 226 buffer_->OnStreamData(800, source, t, &written, &error_details_)); |
217 BufferBlock* block_ptr = helper_->GetBlock(0); | 227 BufferBlock* block_ptr = helper_->GetBlock(0); |
218 for (size_t i = 0; i < source.size(); ++i) { | 228 for (size_t i = 0; i < source.size(); ++i) { |
219 ASSERT_EQ('a', block_ptr->buffer[helper_->GetInBlockOffset(800) + i]); | 229 ASSERT_EQ('a', block_ptr->buffer[helper_->GetInBlockOffset(800) + i]); |
220 } | 230 } |
221 EXPECT_EQ(2, helper_->GapSize()); | 231 EXPECT_EQ(2, helper_->GapSize()); |
222 std::list<Gap> gaps = helper_->GetGaps(); | 232 std::list<Gap> gaps = helper_->GetGaps(); |
223 EXPECT_EQ(800u, gaps.front().end_offset); | 233 EXPECT_EQ(800u, gaps.front().end_offset); |
224 EXPECT_EQ(1824u, gaps.back().begin_offset); | 234 EXPECT_EQ(1824u, gaps.back().begin_offset); |
225 auto* frame_map = helper_->frame_arrival_time_map(); | 235 auto* frame_map = helper_->frame_arrival_time_map(); |
226 EXPECT_EQ(1u, frame_map->size()); | 236 EXPECT_EQ(1u, frame_map->size()); |
227 EXPECT_EQ(800u, frame_map->begin()->first); | 237 EXPECT_EQ(800u, frame_map->begin()->first); |
228 EXPECT_EQ(t, (*frame_map)[800].timestamp); | 238 EXPECT_EQ(t, (*frame_map)[800].timestamp); |
229 EXPECT_TRUE(helper_->CheckBufferInvariants()); | 239 EXPECT_TRUE(helper_->CheckBufferInvariants()); |
| 240 EXPECT_TRUE(helper_->IsBufferAllocated()); |
230 } | 241 } |
231 | 242 |
232 TEST_F(QuicStreamSequencerBufferTest, OnStreamDataWithOverlap) { | 243 TEST_F(QuicStreamSequencerBufferTest, OnStreamDataWithOverlap) { |
233 string source(1024, 'a'); | 244 string source(1024, 'a'); |
234 // Write something into [800, 1824) | 245 // Write something into [800, 1824) |
235 size_t written; | 246 size_t written; |
236 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); | 247 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); |
237 QuicTime t1 = clock_.ApproximateNow(); | 248 QuicTime t1 = clock_.ApproximateNow(); |
238 EXPECT_EQ(QUIC_NO_ERROR, | 249 EXPECT_EQ(QUIC_NO_ERROR, |
239 buffer_->OnStreamData(800, source, t1, &written, &error_details_)); | 250 buffer_->OnStreamData(800, source, t1, &written, &error_details_)); |
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
534 } | 545 } |
535 | 546 |
536 TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionsEmpty) { | 547 TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionsEmpty) { |
537 iovec iovs[2]; | 548 iovec iovs[2]; |
538 int iov_count = buffer_->GetReadableRegions(iovs, 2); | 549 int iov_count = buffer_->GetReadableRegions(iovs, 2); |
539 EXPECT_EQ(0, iov_count); | 550 EXPECT_EQ(0, iov_count); |
540 EXPECT_EQ(nullptr, iovs[iov_count].iov_base); | 551 EXPECT_EQ(nullptr, iovs[iov_count].iov_base); |
541 EXPECT_EQ(0u, iovs[iov_count].iov_len); | 552 EXPECT_EQ(0u, iovs[iov_count].iov_len); |
542 } | 553 } |
543 | 554 |
| 555 TEST_F(QuicStreamSequencerBufferTest, ReleaseWholeBuffer) { |
| 556 // Tests that buffer is not deallocated unless ReleaseWholeBuffer() is called. |
| 557 if (!FLAGS_quic_reduce_sequencer_buffer_memory_life_time) { // NOLINT |
| 558 // Won't release buffer when flag is off. |
| 559 return; |
| 560 } |
| 561 |
| 562 string source(100, 'b'); |
| 563 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); |
| 564 QuicTime t1 = clock_.ApproximateNow(); |
| 565 // Write something into [0, 100). |
| 566 size_t written; |
| 567 buffer_->OnStreamData(0, source, t1, &written, &error_details_); |
| 568 EXPECT_TRUE(buffer_->HasBytesToRead()); |
| 569 char dest[120]; |
| 570 iovec iovecs[3]{iovec{dest, 40}, iovec{dest + 40, 40}, iovec{dest + 80, 40}}; |
| 571 size_t read = buffer_->Readv(iovecs, 3); |
| 572 EXPECT_EQ(100u, read); |
| 573 EXPECT_EQ(100u, buffer_->BytesConsumed()); |
| 574 EXPECT_TRUE(helper_->CheckBufferInvariants()); |
| 575 EXPECT_TRUE(helper_->IsBufferAllocated()); |
| 576 buffer_->ReleaseWholeBuffer(); |
| 577 EXPECT_FALSE(helper_->IsBufferAllocated()); |
| 578 } |
| 579 |
544 TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionsBlockedByGap) { | 580 TEST_F(QuicStreamSequencerBufferTest, GetReadableRegionsBlockedByGap) { |
545 // Write into [1, 1024). | 581 // Write into [1, 1024). |
546 string source(1023, 'a'); | 582 string source(1023, 'a'); |
547 size_t written; | 583 size_t written; |
548 buffer_->OnStreamData(1, source, clock_.ApproximateNow(), &written, | 584 buffer_->OnStreamData(1, source, clock_.ApproximateNow(), &written, |
549 &error_details_); | 585 &error_details_); |
550 // Try to get readable regions, but none is there. | 586 // Try to get readable regions, but none is there. |
551 iovec iovs[2]; | 587 iovec iovs[2]; |
552 int iov_count = buffer_->GetReadableRegions(iovs, 2); | 588 int iov_count = buffer_->GetReadableRegions(iovs, 2); |
553 EXPECT_EQ(0, iov_count); | 589 EXPECT_EQ(0, iov_count); |
(...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1078 EXPECT_LE(bytes_to_buffer_, total_bytes_read_) << "iterations: " | 1114 EXPECT_LE(bytes_to_buffer_, total_bytes_read_) << "iterations: " |
1079 << iterations; | 1115 << iterations; |
1080 EXPECT_LE(bytes_to_buffer_, total_bytes_written_); | 1116 EXPECT_LE(bytes_to_buffer_, total_bytes_written_); |
1081 } | 1117 } |
1082 | 1118 |
1083 } // anonymous namespace | 1119 } // anonymous namespace |
1084 | 1120 |
1085 } // namespace test | 1121 } // namespace test |
1086 | 1122 |
1087 } // namespace net | 1123 } // namespace net |
OLD | NEW |