summaryrefslogtreecommitdiffstats
path: root/net/quic/quic_stream_sequencer_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'net/quic/quic_stream_sequencer_test.cc')
-rw-r--r--net/quic/quic_stream_sequencer_test.cc187
1 files changed, 187 insertions, 0 deletions
diff --git a/net/quic/quic_stream_sequencer_test.cc b/net/quic/quic_stream_sequencer_test.cc
index 787d8f5..3b0104e 100644
--- a/net/quic/quic_stream_sequencer_test.cc
+++ b/net/quic/quic_stream_sequencer_test.cc
@@ -80,6 +80,44 @@ class QuicStreamSequencerTest : public ::testing::Test {
sequencer_(new QuicStreamSequencerPeer(&stream_)) {
}
+ bool VerifyReadableRegions(const char** expected, size_t num_expected) {
+ iovec iovecs[5];
+ size_t num_iovecs = sequencer_->GetReadableRegions(iovecs,
+ arraysize(iovecs));
+ return VerifyIovecs(iovecs, num_iovecs, expected, num_expected);
+ }
+
+ bool VerifyIovecs(iovec* iovecs,
+ size_t num_iovecs,
+ const char** expected,
+ size_t num_expected) {
+ if (num_expected != num_iovecs) {
+ LOG(ERROR) << "Incorrect number of iovecs. Expected: "
+ << num_expected << " Actual: " << num_iovecs;
+ return false;
+ }
+ for (size_t i = 0; i < num_expected; ++i) {
+ if (!VerifyIovec(iovecs[i], expected[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ bool VerifyIovec(const iovec& iovec, StringPiece expected) {
+ if (iovec.iov_len != expected.length()) {
+ LOG(ERROR) << "Invalid length: " << iovec.iov_len
+ << " vs " << expected.length();
+ return false;
+ }
+ if (memcmp(iovec.iov_base, expected.data(), expected.length()) != 0) {
+ LOG(ERROR) << "Invalid data: " << static_cast<char*>(iovec.iov_base)
+ << " vs " << expected.data();
+ return false;
+ }
+ return true;
+ }
+
QuicSession* session_;
testing::StrictMock<MockStream> stream_;
scoped_ptr<QuicStreamSequencerPeer> sequencer_;
@@ -211,6 +249,119 @@ TEST_F(QuicStreamSequencerTest, OutOfOrderFramesProcessedWithBuffering) {
EXPECT_EQ(0u, sequencer_->frames()->size());
}
+TEST_F(QuicStreamSequencerTest, OutOfOrderFramesBlockignWithReadv) {
+ sequencer_->SetMemoryLimit(9);
+ char buffer[20];
+ iovec iov[2];
+ iov[0].iov_base = &buffer[0];
+ iov[0].iov_len = 1;
+ iov[1].iov_base = &buffer[1];
+ iov[1].iov_len = 2;
+
+ // Push abc - process.
+ // Push jkl - buffer (not next data)
+ // Push def - don't process.
+ // Push mno - drop (too far out)
+ // Push ghi - buffer (def not processed)
+ // Read 2.
+ // Push mno - buffer (not all read)
+ // Read all
+ // Push pqr - process
+
+ InSequence s;
+ EXPECT_CALL(stream_, ProcessData(StrEq("abc"), 3)).WillOnce(Return(3));
+ EXPECT_CALL(stream_, ProcessData(StrEq("def"), 3)).WillOnce(Return(0));
+ EXPECT_CALL(stream_, ProcessData(StrEq("pqr"), 3)).WillOnce(Return(3));
+
+ EXPECT_TRUE(sequencer_->OnFrame(0, "abc", 3));
+ EXPECT_TRUE(sequencer_->OnFrame(3, "def", 3));
+ EXPECT_TRUE(sequencer_->OnFrame(9, "jkl", 3));
+ EXPECT_FALSE(sequencer_->OnFrame(12, "mno", 3));
+ EXPECT_TRUE(sequencer_->OnFrame(6, "ghi", 3));
+
+ // Read 3 bytes.
+ EXPECT_EQ(3, sequencer_->Readv(iov, 2));
+ EXPECT_EQ(0, strncmp(buffer, "def", 3));
+
+ // Now we have space to bufer this.
+ EXPECT_TRUE(sequencer_->OnFrame(12, "mno", 3));
+
+ // Read the remaining 9 bytes.
+ iov[1].iov_len = 19;
+ EXPECT_EQ(9, sequencer_->Readv(iov, 2));
+ EXPECT_EQ(0, strncmp(buffer, "ghijklmno", 9));
+
+ EXPECT_TRUE(sequencer_->OnFrame(15, "pqr", 3));
+}
+
+// Same as above, just using a different method for reading.
+TEST_F(QuicStreamSequencerTest, OutOfOrderFramesBlockignWithGetReadableRegion) {
+ sequencer_->SetMemoryLimit(9);
+
+ InSequence s;
+ EXPECT_CALL(stream_, ProcessData(StrEq("abc"), 3)).WillOnce(Return(3));
+ EXPECT_CALL(stream_, ProcessData(StrEq("def"), 3)).WillOnce(Return(0));
+ EXPECT_CALL(stream_, ProcessData(StrEq("pqr"), 3)).WillOnce(Return(3));
+
+ EXPECT_TRUE(sequencer_->OnFrame(0, "abc", 3));
+ EXPECT_TRUE(sequencer_->OnFrame(3, "def", 3));
+ EXPECT_TRUE(sequencer_->OnFrame(9, "jkl", 3));
+ EXPECT_FALSE(sequencer_->OnFrame(12, "mno", 3));
+ EXPECT_TRUE(sequencer_->OnFrame(6, "ghi", 3));
+
+ // Read 3 bytes.
+ const char* expected[] = {"def", "ghi", "jkl"};
+ ASSERT_TRUE(VerifyReadableRegions(expected, arraysize(expected)));
+ char buffer[9];
+ iovec read_iov = { &buffer[0], 3 };
+ ASSERT_EQ(3, sequencer_->Readv(&read_iov, 1));
+
+ // Now we have space to bufer this.
+ EXPECT_TRUE(sequencer_->OnFrame(12, "mno", 3));
+
+ // Read the remaining 9 bytes.
+ const char* expected2[] = {"ghi", "jkl", "mno"};
+ ASSERT_TRUE(VerifyReadableRegions(expected2, arraysize(expected2)));
+ read_iov.iov_len = 9;
+ ASSERT_EQ(9, sequencer_->Readv(&read_iov, 1));
+
+ EXPECT_TRUE(sequencer_->OnFrame(15, "pqr", 3));
+}
+
+// Same as above, just using a different method for reading.
+TEST_F(QuicStreamSequencerTest, MarkConsumed) {
+ sequencer_->SetMemoryLimit(9);
+
+ InSequence s;
+ EXPECT_CALL(stream_, ProcessData(StrEq("abc"), 3)).WillOnce(Return(0));
+
+ EXPECT_TRUE(sequencer_->OnFrame(0, "abc", 3));
+ EXPECT_TRUE(sequencer_->OnFrame(3, "def", 3));
+ EXPECT_TRUE(sequencer_->OnFrame(6, "ghi", 3));
+
+ // Peek into the data.
+ const char* expected[] = {"abc", "def", "ghi"};
+ ASSERT_TRUE(VerifyReadableRegions(expected, arraysize(expected)));
+
+ // Consume 1 byte.
+ sequencer_->MarkConsumed(1);
+ // Verify data.
+ const char* expected2[] = {"bc", "def", "ghi"};
+ ASSERT_TRUE(VerifyReadableRegions(expected2, arraysize(expected2)));
+
+ // Consume 2 bytes.
+ sequencer_->MarkConsumed(2);
+ // Verify data.
+ const char* expected3[] = {"def", "ghi"};
+ ASSERT_TRUE(VerifyReadableRegions(expected3, arraysize(expected3)));
+
+ // Consume 5 bytes.
+ sequencer_->MarkConsumed(5);
+ // Verify data.
+ const char* expected4[] = {"i"};
+ ASSERT_TRUE(VerifyReadableRegions(expected4, arraysize(expected4)));
+}
+
TEST_F(QuicStreamSequencerTest, BasicCloseOrdered) {
InSequence s;
EXPECT_CALL(stream_, ProcessData(StrEq("abc"), 3)).WillOnce(Return(3));
@@ -304,6 +455,42 @@ TEST_F(QuicStreamSequencerTest, CloseBeforeTermianteEqual) {
EXPECT_TRUE(sequencer_->OnFrame(0, "abc", 3));
}
+TEST_F(QuicStreamSequencerTest, TerminateWithReadv) {
+ char buffer[3];
+
+ sequencer_->CloseStreamAtOffset(3, true);
+ EXPECT_EQ(3u, sequencer_->close_offset());
+
+ EXPECT_FALSE(sequencer_->IsHalfClosed());
+
+ EXPECT_CALL(stream_, ProcessData(StrEq("abc"), 3)).WillOnce(Return(0));
+ EXPECT_TRUE(sequencer_->OnFrame(0, "abc", 3));
+
+ iovec iov = { &buffer[0], 3 };
+ int bytes_read = sequencer_->Readv(&iov, 1);
+ EXPECT_EQ(3, bytes_read);
+ EXPECT_TRUE(sequencer_->IsHalfClosed());
+ EXPECT_FALSE(sequencer_->IsClosed());
+}
+
+TEST_F(QuicStreamSequencerTest, CloseWithReadv) {
+ char buffer[3];
+
+ sequencer_->CloseStreamAtOffset(3, false);
+ EXPECT_EQ(3u, sequencer_->close_offset());
+
+ EXPECT_FALSE(sequencer_->IsClosed());
+
+ EXPECT_CALL(stream_, ProcessData(StrEq("abc"), 3)).WillOnce(Return(0));
+ EXPECT_TRUE(sequencer_->OnFrame(0, "abc", 3));
+
+ iovec iov = { &buffer[0], 3 };
+ int bytes_read = sequencer_->Readv(&iov, 1);
+ EXPECT_EQ(3, bytes_read);
+ EXPECT_TRUE(sequencer_->IsHalfClosed());
+ EXPECT_TRUE(sequencer_->IsClosed());
+}
+
TEST_F(QuicStreamSequencerTest, MutipleOffsets) {
sequencer_->CloseStreamAtOffset(3, false);
EXPECT_EQ(3u, sequencer_->close_offset());