| 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 |