| Index: net/quic/quic_stream_sequencer_test.cc
|
| ===================================================================
|
| --- net/quic/quic_stream_sequencer_test.cc (revision 165858)
|
| +++ net/quic/quic_stream_sequencer_test.cc (working copy)
|
| @@ -1,413 +0,0 @@
|
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "net/quic/quic_stream_sequencer.h"
|
| -
|
| -#include <utility>
|
| -#include <vector>
|
| -
|
| -#include "base/rand_util.h"
|
| -#include "net/quic/reliable_quic_stream.h"
|
| -#include "testing/gmock/include/gmock/gmock.h"
|
| -#include "testing/gtest/include/gtest/gtest.h"
|
| -
|
| -using base::StringPiece;
|
| -using std::min;
|
| -using std::pair;
|
| -using std::vector;
|
| -using testing::_;
|
| -using testing::AnyNumber;
|
| -using testing::InSequence;
|
| -using testing::Return;
|
| -using testing::StrEq;
|
| -
|
| -namespace net {
|
| -
|
| -class QuicStreamSequencerPeer : public QuicStreamSequencer {
|
| - public:
|
| - explicit QuicStreamSequencerPeer(ReliableQuicStream* stream)
|
| - : QuicStreamSequencer(stream) {
|
| - }
|
| -
|
| - QuicStreamSequencerPeer(int32 max_mem, ReliableQuicStream* stream)
|
| - : QuicStreamSequencer(max_mem, stream) {}
|
| -
|
| - virtual bool OnFrame(QuicStreamOffset byte_offset,
|
| - const char* data,
|
| - uint32 data_len) {
|
| - QuicStreamFrame frame;
|
| - frame.stream_id = 1;
|
| - frame.offset = byte_offset;
|
| - frame.data = StringPiece(data, data_len);
|
| - return OnStreamFrame(frame);
|
| - }
|
| -
|
| - void SetMemoryLimit(size_t limit) {
|
| - max_frame_memory_ = limit;
|
| - }
|
| -
|
| - ReliableQuicStream* stream() { return stream_; }
|
| - uint64 num_bytes_consumed() { return num_bytes_consumed_; }
|
| - FrameMap* frames() { return &frames_; }
|
| - int32 max_frame_memory() { return max_frame_memory_; }
|
| - QuicStreamOffset close_offset() { return close_offset_; }
|
| -};
|
| -
|
| -class MockStream : public ReliableQuicStream {
|
| - public:
|
| - MockStream(QuicSession* session, QuicStreamId id)
|
| - : ReliableQuicStream(id, session) {
|
| - }
|
| -
|
| - MOCK_METHOD1(TerminateFromPeer, void(bool half_close));
|
| - MOCK_METHOD2(ProcessData, uint32(const char* data, uint32 data_len));
|
| - MOCK_METHOD1(Close, void(QuicErrorCode error));
|
| -};
|
| -
|
| -namespace {
|
| -
|
| -static const char kPayload[] =
|
| - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
| -
|
| -class QuicStreamSequencerTest : public ::testing::Test {
|
| - protected:
|
| - QuicStreamSequencerTest()
|
| - : session_(NULL),
|
| - stream_(session_, 1),
|
| - sequencer_(new QuicStreamSequencerPeer(&stream_)) {
|
| - }
|
| -
|
| - QuicSession* session_;
|
| - testing::StrictMock<MockStream> stream_;
|
| - scoped_ptr<QuicStreamSequencerPeer> sequencer_;
|
| -};
|
| -
|
| -TEST_F(QuicStreamSequencerTest, RejectOldFrame) {
|
| - EXPECT_CALL(stream_, ProcessData("abc", 3))
|
| - .WillOnce(Return(3));
|
| -
|
| - EXPECT_TRUE(sequencer_->OnFrame(0, "abc", 3));
|
| - EXPECT_EQ(0u, sequencer_->frames()->size());
|
| - EXPECT_EQ(3u, sequencer_->num_bytes_consumed());
|
| - // Nack this - it matches a past sequence number and we should not see it
|
| - // again.
|
| - EXPECT_FALSE(sequencer_->OnFrame(0, "def", 3));
|
| - EXPECT_EQ(0u, sequencer_->frames()->size());
|
| -}
|
| -
|
| -TEST_F(QuicStreamSequencerTest, RejectOverlyLargeFrame) {
|
| - /*
|
| - EXPECT_DFATAL(sequencer_.reset(new QuicStreamSequencerPeer(2, &stream_)),
|
| - "Setting max frame memory to 2. "
|
| - "Some frames will be impossible to handle.");
|
| -
|
| - EXPECT_DEBUG_DEATH(sequencer_->OnFrame(0, "abc", 3), "");
|
| - */
|
| -}
|
| -
|
| -TEST_F(QuicStreamSequencerTest, DropFramePastBuffering) {
|
| - sequencer_->SetMemoryLimit(3);
|
| -
|
| - EXPECT_FALSE(sequencer_->OnFrame(3, "abc", 3));
|
| -}
|
| -
|
| -TEST_F(QuicStreamSequencerTest, RejectBufferedFrame) {
|
| - EXPECT_CALL(stream_, ProcessData("abc", 3));
|
| -
|
| - EXPECT_TRUE(sequencer_->OnFrame(0, "abc", 3));
|
| - EXPECT_EQ(1u, sequencer_->frames()->size());
|
| - EXPECT_EQ(0u, sequencer_->num_bytes_consumed());
|
| - // Ignore this - it matches a buffered frame.
|
| - // Right now there's no checking that the payload is consistent.
|
| - EXPECT_FALSE(sequencer_->OnFrame(0, "def", 3));
|
| - EXPECT_EQ(1u, sequencer_->frames()->size());
|
| -}
|
| -
|
| -TEST_F(QuicStreamSequencerTest, FullFrameConsumed) {
|
| - EXPECT_CALL(stream_, ProcessData("abc", 3))
|
| - .WillOnce(Return(3));
|
| -
|
| - EXPECT_TRUE(sequencer_->OnFrame(0, "abc", 3));
|
| - EXPECT_EQ(0u, sequencer_->frames()->size());
|
| - EXPECT_EQ(3u, sequencer_->num_bytes_consumed());
|
| -}
|
| -
|
| -TEST_F(QuicStreamSequencerTest, PartialFrameConsumed) {
|
| - EXPECT_CALL(stream_, ProcessData("abc", 3))
|
| - .WillOnce(Return(2));
|
| -
|
| - EXPECT_TRUE(sequencer_->OnFrame(0, "abc", 3));
|
| - EXPECT_EQ(1u, sequencer_->frames()->size());
|
| - EXPECT_EQ(2u, sequencer_->num_bytes_consumed());
|
| - EXPECT_EQ("c", sequencer_->frames()->find(2)->second);
|
| -}
|
| -
|
| -TEST_F(QuicStreamSequencerTest, NextxFrameNotConsumed) {
|
| - EXPECT_CALL(stream_, ProcessData("abc", 3))
|
| - .WillOnce(Return(0));
|
| -
|
| - EXPECT_TRUE(sequencer_->OnFrame(0, "abc", 3));
|
| - EXPECT_EQ(1u, sequencer_->frames()->size());
|
| - EXPECT_EQ(0u, sequencer_->num_bytes_consumed());
|
| - EXPECT_EQ("abc", sequencer_->frames()->find(0)->second);
|
| -}
|
| -
|
| -TEST_F(QuicStreamSequencerTest, FutureFrameNotProcessed) {
|
| - EXPECT_TRUE(sequencer_->OnFrame(3, "abc", 3));
|
| - EXPECT_EQ(1u, sequencer_->frames()->size());
|
| - EXPECT_EQ(0u, sequencer_->num_bytes_consumed());
|
| - EXPECT_EQ("abc", sequencer_->frames()->find(3)->second);
|
| -}
|
| -
|
| -TEST_F(QuicStreamSequencerTest, OutOfOrderFrameProcessed) {
|
| - // Buffer the first
|
| - EXPECT_TRUE(sequencer_->OnFrame(6, "ghi", 3));
|
| - EXPECT_EQ(1u, sequencer_->frames()->size());
|
| - EXPECT_EQ(0u, sequencer_->num_bytes_consumed());
|
| - // Buffer the second
|
| - EXPECT_TRUE(sequencer_->OnFrame(3, "def", 3));
|
| - EXPECT_EQ(2u, sequencer_->frames()->size());
|
| - EXPECT_EQ(0u, sequencer_->num_bytes_consumed());
|
| -
|
| - InSequence s;
|
| - EXPECT_CALL(stream_, ProcessData("abc", 3)).WillOnce(Return(3));
|
| - EXPECT_CALL(stream_, ProcessData(StrEq("def"), 3)).WillOnce(Return(3));
|
| - EXPECT_CALL(stream_, ProcessData(StrEq("ghi"), 3)).WillOnce(Return(3));
|
| -
|
| - // Ack right away
|
| - EXPECT_TRUE(sequencer_->OnFrame(0, "abc", 3));
|
| - EXPECT_EQ(9u, sequencer_->num_bytes_consumed());
|
| -
|
| - EXPECT_EQ(0u, sequencer_->frames()->size());
|
| -}
|
| -
|
| -TEST_F(QuicStreamSequencerTest, OutOfOrderFramesProcessedWithBuffering) {
|
| - sequencer_->SetMemoryLimit(9);
|
| -
|
| - // Too far to buffer.
|
| - EXPECT_FALSE(sequencer_->OnFrame(9, "jkl", 3));
|
| -
|
| - // We can afford to buffer this.
|
| - EXPECT_TRUE(sequencer_->OnFrame(6, "ghi", 3));
|
| - EXPECT_EQ(0u, sequencer_->num_bytes_consumed());
|
| -
|
| - InSequence s;
|
| - EXPECT_CALL(stream_, ProcessData("abc", 3)).WillOnce(Return(3));
|
| -
|
| - // Ack right away
|
| - EXPECT_TRUE(sequencer_->OnFrame(0, "abc", 3));
|
| - EXPECT_EQ(3u, sequencer_->num_bytes_consumed());
|
| -
|
| - // We should be willing to buffer this now.
|
| - EXPECT_TRUE(sequencer_->OnFrame(9, "jkl", 3));
|
| - EXPECT_EQ(3u, sequencer_->num_bytes_consumed());
|
| -
|
| - EXPECT_CALL(stream_, ProcessData(StrEq("def"), 3)).WillOnce(Return(3));
|
| - EXPECT_CALL(stream_, ProcessData(StrEq("ghi"), 3)).WillOnce(Return(3));
|
| - EXPECT_CALL(stream_, ProcessData(StrEq("jkl"), 3)).WillOnce(Return(3));
|
| -
|
| - EXPECT_TRUE(sequencer_->OnFrame(3, "def", 3));
|
| - EXPECT_EQ(12u, sequencer_->num_bytes_consumed());
|
| - EXPECT_EQ(0u, sequencer_->frames()->size());
|
| -}
|
| -
|
| -TEST_F(QuicStreamSequencerTest, BasicCloseOrdered) {
|
| - InSequence s;
|
| - EXPECT_CALL(stream_, ProcessData(StrEq("abc"), 3)).WillOnce(Return(3));
|
| - EXPECT_TRUE(sequencer_->OnFrame(0, "abc", 3));
|
| -
|
| - EXPECT_CALL(stream_, TerminateFromPeer(false));
|
| - sequencer_->CloseStreamAtOffset(3, false);
|
| - EXPECT_EQ(3u, sequencer_->close_offset());
|
| -}
|
| -
|
| -TEST_F(QuicStreamSequencerTest, BasicHalfOrdered) {
|
| - InSequence s;
|
| -
|
| - EXPECT_CALL(stream_, ProcessData(StrEq("abc"), 3)).WillOnce(Return(3));
|
| - EXPECT_TRUE(sequencer_->OnFrame(0, "abc", 3));
|
| -
|
| - EXPECT_CALL(stream_, TerminateFromPeer(true));
|
| - sequencer_->CloseStreamAtOffset(3, true);
|
| - EXPECT_EQ(3u, sequencer_->close_offset());
|
| -}
|
| -
|
| -TEST_F(QuicStreamSequencerTest, BasicCloseUnordered) {
|
| - sequencer_->CloseStreamAtOffset(3, false);
|
| - EXPECT_EQ(3u, sequencer_->close_offset());
|
| -
|
| - InSequence s;
|
| - EXPECT_CALL(stream_, ProcessData(StrEq("abc"), 3)).WillOnce(Return(3));
|
| - EXPECT_CALL(stream_, TerminateFromPeer(false));
|
| -
|
| - EXPECT_TRUE(sequencer_->OnFrame(0, "abc", 3));
|
| -}
|
| -
|
| -TEST_F(QuicStreamSequencerTest, BasicHalfUnorderedWithFlush) {
|
| - sequencer_->CloseStreamAtOffset(6, true);
|
| - EXPECT_EQ(6u, sequencer_->close_offset());
|
| - InSequence s;
|
| - EXPECT_CALL(stream_, ProcessData(StrEq("abc"), 3)).WillOnce(Return(3));
|
| - EXPECT_CALL(stream_, ProcessData(StrEq("def"), 3)).WillOnce(Return(3));
|
| - EXPECT_CALL(stream_, TerminateFromPeer(true));
|
| -
|
| - EXPECT_TRUE(sequencer_->OnFrame(3, "def", 3));
|
| - EXPECT_TRUE(sequencer_->OnFrame(0, "abc", 3));
|
| -}
|
| -
|
| -TEST_F(QuicStreamSequencerTest, BasicCloseUnorderedWithFlush) {
|
| - sequencer_->CloseStreamAtOffset(6, false);
|
| - EXPECT_EQ(6u, sequencer_->close_offset());
|
| -
|
| - InSequence s;
|
| - EXPECT_CALL(stream_, ProcessData(StrEq("abc"), 3)).WillOnce(Return(3));
|
| - EXPECT_CALL(stream_, ProcessData(StrEq("def"), 3)).WillOnce(Return(3));
|
| - EXPECT_CALL(stream_, TerminateFromPeer(false));
|
| -
|
| - EXPECT_TRUE(sequencer_->OnFrame(3, "def", 3));
|
| - EXPECT_TRUE(sequencer_->OnFrame(0, "abc", 3));
|
| -}
|
| -
|
| -TEST_F(QuicStreamSequencerTest, BasicHalfUnordered) {
|
| - sequencer_->CloseStreamAtOffset(3, true);
|
| - EXPECT_EQ(3u, sequencer_->close_offset());
|
| - InSequence s;
|
| - EXPECT_CALL(stream_, ProcessData(StrEq("abc"), 3)).WillOnce(Return(3));
|
| - EXPECT_CALL(stream_, TerminateFromPeer(true));
|
| -
|
| - EXPECT_TRUE(sequencer_->OnFrame(0, "abc", 3));
|
| -}
|
| -
|
| -TEST_F(QuicStreamSequencerTest, CloseStreamBeforeCloseEqual) {
|
| - sequencer_->CloseStreamAtOffset(3, true);
|
| - EXPECT_EQ(3u, sequencer_->close_offset());
|
| -
|
| - sequencer_->CloseStreamAtOffset(3, false);
|
| - EXPECT_EQ(3u, sequencer_->close_offset());
|
| -
|
| - InSequence s;
|
| - EXPECT_CALL(stream_, ProcessData(StrEq("abc"), 3)).WillOnce(Return(3));
|
| - EXPECT_CALL(stream_, TerminateFromPeer(false));
|
| - EXPECT_TRUE(sequencer_->OnFrame(0, "abc", 3));
|
| -}
|
| -
|
| -TEST_F(QuicStreamSequencerTest, CloseBeforeTermianteEqual) {
|
| - sequencer_->CloseStreamAtOffset(3, false);
|
| - EXPECT_EQ(3u, sequencer_->close_offset());
|
| -
|
| - sequencer_->CloseStreamAtOffset(3, true);
|
| - EXPECT_EQ(3u, sequencer_->close_offset());
|
| -
|
| - InSequence s;
|
| - EXPECT_CALL(stream_, ProcessData(StrEq("abc"), 3)).WillOnce(Return(3));
|
| - EXPECT_CALL(stream_, TerminateFromPeer(false));
|
| - EXPECT_TRUE(sequencer_->OnFrame(0, "abc", 3));
|
| -}
|
| -
|
| -TEST_F(QuicStreamSequencerTest, MutipleOffsets) {
|
| - sequencer_->CloseStreamAtOffset(3, false);
|
| - EXPECT_EQ(3u, sequencer_->close_offset());
|
| -
|
| - EXPECT_CALL(stream_, Close(QUIC_MULTIPLE_TERMINATION_OFFSETS));
|
| - sequencer_->CloseStreamAtOffset(5, false);
|
| - EXPECT_EQ(3u, sequencer_->close_offset());
|
| -
|
| - EXPECT_CALL(stream_, Close(QUIC_MULTIPLE_TERMINATION_OFFSETS));
|
| - sequencer_->CloseStreamAtOffset(1, false);
|
| - EXPECT_EQ(3u, sequencer_->close_offset());
|
| -
|
| - sequencer_->CloseStreamAtOffset(3, false);
|
| - EXPECT_EQ(3u, sequencer_->close_offset());
|
| -}
|
| -
|
| -class QuicSequencerRandomTest : public QuicStreamSequencerTest {
|
| - public:
|
| - typedef pair<int, string> Frame;
|
| - typedef vector<Frame> FrameList;
|
| -
|
| - void CreateFrames() {
|
| - int payload_size = arraysize(kPayload) - 1;
|
| - int remaining_payload = payload_size;
|
| - while (remaining_payload != 0) {
|
| - int size = min(OneToN(6), remaining_payload);
|
| - int idx = payload_size - remaining_payload;
|
| - list_.push_back(make_pair(idx, string(kPayload + idx, size)));
|
| - remaining_payload -= size;
|
| - }
|
| - }
|
| -
|
| - QuicSequencerRandomTest() {
|
| - //int32 seed = ACMRandom::HostnamePidTimeSeed();
|
| - //LOG(INFO) << "**** The current seed is " << seed << " ****";
|
| - //random_.reset(new ACMRandom(seed));
|
| -
|
| - CreateFrames();
|
| - }
|
| -
|
| - int OneToN(int n) {
|
| - return base::RandInt(1, n);
|
| - }
|
| -
|
| - int MaybeProcessMaybeBuffer(const char* data, uint32 len) {
|
| - int to_process = len;
|
| - if (base::RandUint64() % 2 != 0) {
|
| - to_process = base::RandInt(0, len);
|
| - }
|
| - output_.append(data, to_process);
|
| - LOG(ERROR) << output_;
|
| - return to_process;
|
| - }
|
| -
|
| - string output_;
|
| - //scoped_ptr<ACMRandom> random_;
|
| - FrameList list_;
|
| -};
|
| -
|
| -// All frames are processed as soon as we have sequential data.
|
| -// Infinite buffering, so all frames are acked right away.
|
| -TEST_F(QuicSequencerRandomTest, RandomFramesNoDroppingNoBackup) {
|
| - InSequence s;
|
| - for (size_t i = 0; i < list_.size(); ++i) {
|
| - string* data = &list_[i].second;
|
| - EXPECT_CALL(stream_, ProcessData(StrEq(*data), data->size()))
|
| - .WillOnce(Return(data->size()));
|
| - }
|
| -
|
| - while (list_.size() != 0) {
|
| - int idx = OneToN(list_.size()) - 1;
|
| - LOG(ERROR) << "Sending index " << idx << " " << list_[idx].second.c_str();
|
| - EXPECT_TRUE(sequencer_->OnFrame(
|
| - list_[idx].first, list_[idx].second.c_str(),
|
| - list_[idx].second.size()));
|
| - list_.erase(list_.begin() + idx);
|
| - }
|
| -}
|
| -
|
| -// All frames are processed as soon as we have sequential data.
|
| -// Buffering, so some frames are rejected.
|
| -TEST_F(QuicSequencerRandomTest, RandomFramesDroppingNoBackup) {
|
| - sequencer_->SetMemoryLimit(26);
|
| -
|
| - InSequence s;
|
| - for (size_t i = 0; i < list_.size(); ++i) {
|
| - string* data = &list_[i].second;
|
| - EXPECT_CALL(stream_, ProcessData(StrEq(*data), data->size()))
|
| - .WillOnce(Return(data->size()));
|
| - }
|
| -
|
| - while (list_.size() != 0) {
|
| - int idx = OneToN(list_.size()) - 1;
|
| - LOG(ERROR) << "Sending index " << idx << " " << list_[idx].second.c_str();
|
| - bool acked = sequencer_->OnFrame(
|
| - list_[idx].first, list_[idx].second.c_str(),
|
| - list_[idx].second.size());
|
| - if (acked) {
|
| - list_.erase(list_.begin() + idx);
|
| - }
|
| - }
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -} // namespace net
|
|
|