OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 | 4 |
5 #include "net/quic/quic_stream_sequencer.h" | 5 #include "net/quic/quic_stream_sequencer.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/rand_util.h" | 11 #include "base/rand_util.h" |
12 #include "net/base/ip_endpoint.h" | 12 #include "net/base/ip_endpoint.h" |
13 #include "net/quic/quic_utils.h" | 13 #include "net/quic/quic_utils.h" |
14 #include "net/quic/reliable_quic_stream.h" | 14 #include "net/quic/reliable_quic_stream.h" |
| 15 #include "net/quic/test_tools/mock_clock.h" |
15 #include "net/quic/test_tools/quic_stream_sequencer_peer.h" | 16 #include "net/quic/test_tools/quic_stream_sequencer_peer.h" |
16 #include "net/quic/test_tools/quic_test_utils.h" | 17 #include "net/quic/test_tools/quic_test_utils.h" |
17 #include "net/test/gtest_util.h" | 18 #include "net/test/gtest_util.h" |
18 #include "testing/gmock/include/gmock/gmock.h" | 19 #include "testing/gmock/include/gmock/gmock.h" |
19 #include "testing/gmock_mutant.h" | 20 #include "testing/gmock_mutant.h" |
20 #include "testing/gtest/include/gtest/gtest.h" | 21 #include "testing/gtest/include/gtest/gtest.h" |
21 | 22 |
22 using base::StringPiece; | 23 using base::StringPiece; |
23 using std::map; | 24 using std::map; |
24 using std::min; | 25 using std::min; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
69 iov.iov_base = buffer; | 70 iov.iov_base = buffer; |
70 iov.iov_len = num_bytes; | 71 iov.iov_len = num_bytes; |
71 ASSERT_EQ(static_cast<int>(num_bytes), sequencer_->Readv(&iov, 1)); | 72 ASSERT_EQ(static_cast<int>(num_bytes), sequencer_->Readv(&iov, 1)); |
72 } | 73 } |
73 | 74 |
74 protected: | 75 protected: |
75 QuicStreamSequencerTest() | 76 QuicStreamSequencerTest() |
76 : connection_(new MockConnection(Perspective::IS_CLIENT)), | 77 : connection_(new MockConnection(Perspective::IS_CLIENT)), |
77 session_(connection_), | 78 session_(connection_), |
78 stream_(&session_, 1), | 79 stream_(&session_, 1), |
79 sequencer_(new QuicStreamSequencer(&stream_)) {} | 80 sequencer_(new QuicStreamSequencer(&stream_, &clock_)) {} |
| 81 |
| 82 bool VerifyReadableRegion(const char** expected) { |
| 83 iovec iovecs[1]; |
| 84 if (sequencer_->GetReadableRegion(iovecs, nullptr)) { |
| 85 return (VerifyIovecs(iovecs, 1, expected, 1)); |
| 86 } |
| 87 return false; |
| 88 } |
80 | 89 |
81 bool VerifyReadableRegions(const char** expected, size_t num_expected) { | 90 bool VerifyReadableRegions(const char** expected, size_t num_expected) { |
82 iovec iovecs[5]; | 91 iovec iovecs[5]; |
83 size_t num_iovecs = | 92 size_t num_iovecs = |
84 sequencer_->GetReadableRegions(iovecs, arraysize(iovecs)); | 93 sequencer_->GetReadableRegions(iovecs, arraysize(iovecs)); |
85 return VerifyIovecs(iovecs, num_iovecs, expected, num_expected); | 94 return VerifyReadableRegion(expected) && |
| 95 VerifyIovecs(iovecs, num_iovecs, expected, num_expected); |
86 } | 96 } |
87 | 97 |
88 bool VerifyIovecs(iovec* iovecs, | 98 bool VerifyIovecs(iovec* iovecs, |
89 size_t num_iovecs, | 99 size_t num_iovecs, |
90 const char** expected, | 100 const char** expected, |
91 size_t num_expected) { | 101 size_t num_expected) { |
92 if (num_expected != num_iovecs) { | 102 if (num_expected != num_iovecs) { |
93 LOG(ERROR) << "Incorrect number of iovecs. Expected: " << num_expected | 103 LOG(ERROR) << "Incorrect number of iovecs. Expected: " << num_expected |
94 << " Actual: " << num_iovecs; | 104 << " Actual: " << num_iovecs; |
95 return false; | 105 return false; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
137 size_t NumBufferedFrames() { | 147 size_t NumBufferedFrames() { |
138 return QuicStreamSequencerPeer::GetNumBufferedFrames(sequencer_.get()); | 148 return QuicStreamSequencerPeer::GetNumBufferedFrames(sequencer_.get()); |
139 } | 149 } |
140 | 150 |
141 bool FrameOverlapsBufferedData(const QuicStreamFrame& frame) { | 151 bool FrameOverlapsBufferedData(const QuicStreamFrame& frame) { |
142 return QuicStreamSequencerPeer::FrameOverlapsBufferedData(sequencer_.get(), | 152 return QuicStreamSequencerPeer::FrameOverlapsBufferedData(sequencer_.get(), |
143 frame); | 153 frame); |
144 } | 154 } |
145 | 155 |
146 MockConnection* connection_; | 156 MockConnection* connection_; |
| 157 MockClock clock_; |
147 MockQuicSpdySession session_; | 158 MockQuicSpdySession session_; |
148 testing::StrictMock<MockStream> stream_; | 159 testing::StrictMock<MockStream> stream_; |
149 scoped_ptr<QuicStreamSequencer> sequencer_; | 160 scoped_ptr<QuicStreamSequencer> sequencer_; |
150 }; | 161 }; |
151 | 162 |
152 // TODO(rch): reorder these tests so they build on each other. | 163 // TODO(rch): reorder these tests so they build on each other. |
153 | 164 |
154 TEST_F(QuicStreamSequencerTest, RejectOldFrame) { | 165 TEST_F(QuicStreamSequencerTest, RejectOldFrame) { |
155 EXPECT_CALL(stream_, OnDataAvailable()) | 166 EXPECT_CALL(stream_, OnDataAvailable()) |
156 .WillOnce(testing::Invoke( | 167 .WillOnce(testing::Invoke( |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
439 if (!list_.empty() && (base::RandUint64() % 2 == 0)) { // Send data | 450 if (!list_.empty() && (base::RandUint64() % 2 == 0)) { // Send data |
440 int index = OneToN(list_.size()) - 1; | 451 int index = OneToN(list_.size()) - 1; |
441 OnFrame(list_[index].first, list_[index].second.data()); | 452 OnFrame(list_[index].first, list_[index].second.data()); |
442 list_.erase(list_.begin() + index); | 453 list_.erase(list_.begin() + index); |
443 } else { // Read data | 454 } else { // Read data |
444 bool has_bytes = sequencer_->HasBytesToRead(); | 455 bool has_bytes = sequencer_->HasBytesToRead(); |
445 iovec peek_iov[20]; | 456 iovec peek_iov[20]; |
446 int iovs_peeked = sequencer_->GetReadableRegions(peek_iov, 20); | 457 int iovs_peeked = sequencer_->GetReadableRegions(peek_iov, 20); |
447 if (has_bytes) { | 458 if (has_bytes) { |
448 ASSERT_LT(0, iovs_peeked); | 459 ASSERT_LT(0, iovs_peeked); |
| 460 ASSERT_TRUE(sequencer_->GetReadableRegion(peek_iov, nullptr)); |
449 } else { | 461 } else { |
450 ASSERT_EQ(0, iovs_peeked); | 462 ASSERT_EQ(0, iovs_peeked); |
| 463 ASSERT_FALSE(sequencer_->GetReadableRegion(peek_iov, nullptr)); |
451 } | 464 } |
452 int total_bytes_to_peek = arraysize(buffer); | 465 int total_bytes_to_peek = arraysize(buffer); |
453 for (int i = 0; i < iovs_peeked; ++i) { | 466 for (int i = 0; i < iovs_peeked; ++i) { |
454 int bytes_to_peek = min<int>(peek_iov[i].iov_len, total_bytes_to_peek); | 467 int bytes_to_peek = min<int>(peek_iov[i].iov_len, total_bytes_to_peek); |
455 peeked_.append(static_cast<char*>(peek_iov[i].iov_base), bytes_to_peek); | 468 peeked_.append(static_cast<char*>(peek_iov[i].iov_base), bytes_to_peek); |
456 total_bytes_to_peek -= bytes_to_peek; | 469 total_bytes_to_peek -= bytes_to_peek; |
457 if (total_bytes_to_peek == 0) { | 470 if (total_bytes_to_peek == 0) { |
458 break; | 471 break; |
459 } | 472 } |
460 } | 473 } |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
588 QuicStreamFrame frame1(kClientDataStreamId1, false, 1, StringPiece("hello")); | 601 QuicStreamFrame frame1(kClientDataStreamId1, false, 1, StringPiece("hello")); |
589 sequencer_->OnStreamFrame(frame1); | 602 sequencer_->OnStreamFrame(frame1); |
590 | 603 |
591 QuicStreamFrame frame2(kClientDataStreamId1, false, 2, StringPiece("hello")); | 604 QuicStreamFrame frame2(kClientDataStreamId1, false, 2, StringPiece("hello")); |
592 EXPECT_TRUE(FrameOverlapsBufferedData(frame2)); | 605 EXPECT_TRUE(FrameOverlapsBufferedData(frame2)); |
593 EXPECT_CALL(stream_, CloseConnectionWithDetails(QUIC_INVALID_STREAM_FRAME, _)) | 606 EXPECT_CALL(stream_, CloseConnectionWithDetails(QUIC_INVALID_STREAM_FRAME, _)) |
594 .Times(1); | 607 .Times(1); |
595 sequencer_->OnStreamFrame(frame2); | 608 sequencer_->OnStreamFrame(frame2); |
596 } | 609 } |
597 | 610 |
| 611 TEST_F(QuicStreamSequencerTest, InOrderTimestamps) { |
| 612 // This test verifies that timestamps returned by |
| 613 // GetReadableRegion() are in the correct sequence when frames |
| 614 // arrive at the sequencer in order. |
| 615 EXPECT_CALL(stream_, OnDataAvailable()); |
| 616 |
| 617 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); |
| 618 |
| 619 // Buffer the first frame. |
| 620 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); |
| 621 QuicTime t1 = clock_.ApproximateNow(); |
| 622 OnFrame(0, "abc"); |
| 623 EXPECT_EQ(1u, NumBufferedFrames()); |
| 624 EXPECT_EQ(0u, sequencer_->num_bytes_consumed()); |
| 625 EXPECT_EQ(3u, sequencer_->num_bytes_buffered()); |
| 626 // Buffer the second frame. |
| 627 QuicTime t2 = clock_.ApproximateNow(); |
| 628 OnFrame(3, "def"); |
| 629 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); |
| 630 EXPECT_EQ(2u, NumBufferedFrames()); |
| 631 EXPECT_EQ(0u, sequencer_->num_bytes_consumed()); |
| 632 EXPECT_EQ(6u, sequencer_->num_bytes_buffered()); |
| 633 |
| 634 iovec iovecs[1]; |
| 635 QuicTime timestamp(QuicTime::Zero()); |
| 636 |
| 637 EXPECT_TRUE(sequencer_->GetReadableRegion(iovecs, ×tamp)); |
| 638 EXPECT_EQ(timestamp, t1); |
| 639 QuicStreamSequencerTest::ConsumeData(3); |
| 640 EXPECT_EQ(1u, NumBufferedFrames()); |
| 641 EXPECT_EQ(3u, sequencer_->num_bytes_consumed()); |
| 642 EXPECT_EQ(3u, sequencer_->num_bytes_buffered()); |
| 643 |
| 644 EXPECT_TRUE(sequencer_->GetReadableRegion(iovecs, ×tamp)); |
| 645 EXPECT_EQ(timestamp, t2); |
| 646 QuicStreamSequencerTest::ConsumeData(3); |
| 647 EXPECT_EQ(0u, NumBufferedFrames()); |
| 648 EXPECT_EQ(6u, sequencer_->num_bytes_consumed()); |
| 649 EXPECT_EQ(0u, sequencer_->num_bytes_buffered()); |
| 650 } |
| 651 |
| 652 TEST_F(QuicStreamSequencerTest, OutOfOrderTimestamps) { |
| 653 // This test verifies that timestamps returned by |
| 654 // GetReadableRegion() are in the correct sequence when frames |
| 655 // arrive at the sequencer out of order. |
| 656 EXPECT_CALL(stream_, OnDataAvailable()); |
| 657 |
| 658 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); |
| 659 |
| 660 // Buffer the first frame |
| 661 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); |
| 662 QuicTime t1 = clock_.ApproximateNow(); |
| 663 OnFrame(3, "def"); |
| 664 EXPECT_EQ(1u, NumBufferedFrames()); |
| 665 EXPECT_EQ(0u, sequencer_->num_bytes_consumed()); |
| 666 EXPECT_EQ(3u, sequencer_->num_bytes_buffered()); |
| 667 // Buffer the second frame |
| 668 QuicTime t2 = clock_.ApproximateNow(); |
| 669 OnFrame(0, "abc"); |
| 670 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); |
| 671 EXPECT_EQ(2u, NumBufferedFrames()); |
| 672 EXPECT_EQ(0u, sequencer_->num_bytes_consumed()); |
| 673 EXPECT_EQ(6u, sequencer_->num_bytes_buffered()); |
| 674 |
| 675 iovec iovecs[1]; |
| 676 QuicTime timestamp(QuicTime::Zero()); |
| 677 |
| 678 EXPECT_TRUE(sequencer_->GetReadableRegion(iovecs, ×tamp)); |
| 679 EXPECT_EQ(timestamp, t2); |
| 680 QuicStreamSequencerTest::ConsumeData(3); |
| 681 EXPECT_EQ(1u, NumBufferedFrames()); |
| 682 EXPECT_EQ(3u, sequencer_->num_bytes_consumed()); |
| 683 EXPECT_EQ(3u, sequencer_->num_bytes_buffered()); |
| 684 |
| 685 EXPECT_TRUE(sequencer_->GetReadableRegion(iovecs, ×tamp)); |
| 686 EXPECT_EQ(timestamp, t1); |
| 687 QuicStreamSequencerTest::ConsumeData(3); |
| 688 EXPECT_EQ(0u, NumBufferedFrames()); |
| 689 EXPECT_EQ(6u, sequencer_->num_bytes_consumed()); |
| 690 EXPECT_EQ(0u, sequencer_->num_bytes_buffered()); |
| 691 } |
| 692 |
598 } // namespace | 693 } // namespace |
599 } // namespace test | 694 } // namespace test |
600 } // namespace net | 695 } // namespace net |
OLD | NEW |