| Index: net/quic/quartc/quartc_stream_test.cc
|
| diff --git a/net/quic/quartc/quartc_stream_test.cc b/net/quic/quartc/quartc_stream_test.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..3302df6cff2876f0d08948492b79d220a556d2e6
|
| --- /dev/null
|
| +++ b/net/quic/quartc/quartc_stream_test.cc
|
| @@ -0,0 +1,276 @@
|
| +// Copyright (c) 2017 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/quartc/quartc_stream.h"
|
| +
|
| +#include "net/quic/core/crypto/quic_random.h"
|
| +#include "net/quic/core/quic_session.h"
|
| +#include "net/quic/core/quic_simple_buffer_allocator.h"
|
| +#include "net/quic/quartc/quartc_clock_interface.h"
|
| +#include "net/quic/quartc/quartc_factory.h"
|
| +#include "net/quic/test_tools/mock_clock.h"
|
| +#include "net/spdy/core/spdy_protocol.h"
|
| +#include "testing/gmock/include/gmock/gmock.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +namespace net {
|
| +
|
| +namespace {
|
| +
|
| +static const SpdyPriority kDefaultPriority = 3;
|
| +static const QuicStreamId kStreamId = 5;
|
| +static const QuartcStreamInterface::WriteParameters kDefaultParam;
|
| +
|
| +// MockQuicSession that does not create streams and writes data from
|
| +// QuicStream to a string.
|
| +class MockQuicSession : public QuicSession {
|
| + public:
|
| + MockQuicSession(QuicConnection* connection,
|
| + const QuicConfig& config,
|
| + std::string* write_buffer)
|
| + : QuicSession(connection, nullptr /*visitor*/, config),
|
| + write_buffer_(write_buffer) {}
|
| +
|
| + ~MockQuicSession() override {}
|
| +
|
| + // Writes outgoing data from QuicStream to a string.
|
| + QuicConsumedData WritevData(
|
| + QuicStream* stream,
|
| + QuicStreamId id,
|
| + QuicIOVector iovector,
|
| + QuicStreamOffset offset,
|
| + StreamSendingState state,
|
| + QuicReferenceCountedPointer<
|
| + QuicAckListenerInterface> /*ack_notifier_delegate*/) override {
|
| + if (!writable_) {
|
| + return QuicConsumedData(0, false);
|
| + }
|
| +
|
| + const char* data = reinterpret_cast<const char*>(iovector.iov->iov_base);
|
| + size_t len = iovector.total_length;
|
| + write_buffer_->append(data, len);
|
| + return QuicConsumedData(len, state != StreamSendingState::NO_FIN);
|
| + }
|
| +
|
| + QuartcStream* CreateIncomingDynamicStream(QuicStreamId id) override {
|
| + return nullptr;
|
| + }
|
| +
|
| + QuartcStream* CreateOutgoingDynamicStream(SpdyPriority priority) override {
|
| + return nullptr;
|
| + }
|
| +
|
| + const QuicCryptoStream* GetCryptoStream() const override { return nullptr; }
|
| + QuicCryptoStream* GetMutableCryptoStream() override { return nullptr; }
|
| +
|
| + // Called by QuicStream when they want to close stream.
|
| + void SendRstStream(QuicStreamId id,
|
| + QuicRstStreamErrorCode error,
|
| + QuicStreamOffset bytes_written) override {}
|
| +
|
| + // Sets whether data is written to buffer, or else if this is write blocked.
|
| + void set_writable(bool writable) { writable_ = writable; }
|
| +
|
| + // Tracks whether the stream is write blocked and its priority.
|
| + void RegisterReliableStream(QuicStreamId stream_id, SpdyPriority priority) {
|
| + write_blocked_streams()->RegisterStream(stream_id, priority);
|
| + }
|
| +
|
| + // The session take ownership of the stream.
|
| + void ActivateReliableStream(std::unique_ptr<QuicStream> stream) {
|
| + ActivateStream(std::move(stream));
|
| + }
|
| +
|
| + protected:
|
| + std::unique_ptr<QuicStream> CreateStream(QuicStreamId id) override {
|
| + return nullptr;
|
| + }
|
| +
|
| + private:
|
| + // Stores written data from ReliableQuicStreamAdapter.
|
| + std::string* write_buffer_;
|
| + // Whether data is written to write_buffer_.
|
| + bool writable_ = true;
|
| +};
|
| +
|
| +// Packet writer that does nothing. This is required for QuicConnection but
|
| +// isn't used for writing data.
|
| +class DummyPacketWriter : public QuicPacketWriter {
|
| + public:
|
| + DummyPacketWriter() {}
|
| +
|
| + // QuicPacketWriter overrides.
|
| + WriteResult WritePacket(const char* buffer,
|
| + size_t buf_len,
|
| + const QuicIpAddress& self_address,
|
| + const QuicSocketAddress& peer_address,
|
| + PerPacketOptions* options) override {
|
| + return WriteResult(WRITE_STATUS_ERROR, 0);
|
| + }
|
| +
|
| + bool IsWriteBlockedDataBuffered() const override { return false; }
|
| +
|
| + bool IsWriteBlocked() const override { return false; };
|
| +
|
| + void SetWritable() override {}
|
| +
|
| + QuicByteCount GetMaxPacketSize(
|
| + const QuicSocketAddress& peer_address) const override {
|
| + return 0;
|
| + }
|
| +};
|
| +
|
| +class MockQuartcStreamDelegate : public QuartcStreamInterface::Delegate {
|
| + public:
|
| + MockQuartcStreamDelegate(int id, std::string* read_buffer)
|
| + : id_(id), read_buffer_(read_buffer) {}
|
| +
|
| + void OnBufferedAmountDecrease(QuartcStreamInterface* stream) override {
|
| + queued_bytes_amount_ = stream->buffered_amount();
|
| + }
|
| +
|
| + void OnReceived(QuartcStreamInterface* stream,
|
| + const char* data,
|
| + size_t size) override {
|
| + EXPECT_EQ(id_, stream->stream_id());
|
| + read_buffer_->append(data, size);
|
| + }
|
| +
|
| + void OnClose(QuartcStreamInterface* stream) override { closed_ = true; }
|
| +
|
| + bool closed() { return closed_; }
|
| +
|
| + int queued_bytes_amount() { return queued_bytes_amount_; }
|
| +
|
| + protected:
|
| + uint32_t id_;
|
| + // Data read by the QuicStream.
|
| + std::string* read_buffer_;
|
| + // Whether the QuicStream is closed.
|
| + bool closed_ = false;
|
| + int queued_bytes_amount_ = -1;
|
| +};
|
| +
|
| +class QuartcStreamTest : public ::testing::Test,
|
| + public QuicConnectionHelperInterface {
|
| + public:
|
| + void CreateReliableQuicStream() {
|
| + // Arbitrary values for QuicConnection.
|
| + Perspective perspective = Perspective::IS_SERVER;
|
| + QuicIpAddress ip;
|
| + ip.FromString("0.0.0.0");
|
| + bool owns_writer = true;
|
| +
|
| + // We only use QuartcFactory for its role as an alarm factory.
|
| + QuartcFactoryConfig config;
|
| + alarm_factory_.reset(new QuartcFactory(config));
|
| +
|
| + connection_.reset(new QuicConnection(
|
| + 0, QuicSocketAddress(ip, 0), this /*QuicConnectionHelperInterface*/,
|
| + alarm_factory_.get(), new DummyPacketWriter(), owns_writer, perspective,
|
| + AllSupportedVersions()));
|
| +
|
| + session_.reset(
|
| + new MockQuicSession(connection_.get(), QuicConfig(), &write_buffer_));
|
| + mock_stream_delegate_.reset(
|
| + new MockQuartcStreamDelegate(kStreamId, &read_buffer_));
|
| + stream_ = new QuartcStream(kStreamId, session_.get());
|
| + stream_->SetDelegate(mock_stream_delegate_.get());
|
| + session_->RegisterReliableStream(stream_->stream_id(), kDefaultPriority);
|
| + session_->ActivateReliableStream(std::unique_ptr<QuartcStream>(stream_));
|
| + }
|
| +
|
| + ~QuartcStreamTest() override {}
|
| +
|
| + const QuicClock* GetClock() const override { return &clock_; }
|
| +
|
| + QuicRandom* GetRandomGenerator() override {
|
| + return QuicRandom::GetInstance();
|
| + }
|
| +
|
| + QuicBufferAllocator* GetBufferAllocator() override {
|
| + return &buffer_allocator_;
|
| + }
|
| +
|
| + protected:
|
| + // The QuicSession will take the ownership.
|
| + QuartcStream* stream_;
|
| + std::unique_ptr<MockQuartcStreamDelegate> mock_stream_delegate_;
|
| + std::unique_ptr<MockQuicSession> session_;
|
| + // Data written by the ReliableQuicStreamAdapterTest.
|
| + std::string write_buffer_;
|
| + // Data read by the ReliableQuicStreamAdapterTest.
|
| + std::string read_buffer_;
|
| + std::unique_ptr<QuicAlarmFactory> alarm_factory_;
|
| + std::unique_ptr<QuicConnection> connection_;
|
| + // Used to implement the QuicConnectionHelperInterface.
|
| + SimpleBufferAllocator buffer_allocator_;
|
| + MockClock clock_;
|
| +};
|
| +
|
| +// Write an entire string.
|
| +TEST_F(QuartcStreamTest, WriteDataWhole) {
|
| + CreateReliableQuicStream();
|
| + stream_->Write("Foo bar", 7, kDefaultParam);
|
| + EXPECT_EQ("Foo bar", write_buffer_);
|
| +}
|
| +
|
| +// Write part of a string.
|
| +TEST_F(QuartcStreamTest, WriteDataPartial) {
|
| + CreateReliableQuicStream();
|
| + stream_->Write("Foo bar", 5, kDefaultParam);
|
| + EXPECT_EQ("Foo b", write_buffer_);
|
| +}
|
| +
|
| +// Test that strings are buffered correctly.
|
| +TEST_F(QuartcStreamTest, BufferData) {
|
| + CreateReliableQuicStream();
|
| +
|
| + session_->set_writable(false);
|
| + stream_->Write("Foo bar", 7, kDefaultParam);
|
| + // The data will be buffered.
|
| + EXPECT_EQ(0ul, write_buffer_.size());
|
| + EXPECT_TRUE(stream_->HasBufferedData());
|
| + EXPECT_EQ(-1, mock_stream_delegate_->queued_bytes_amount());
|
| + // The session is writable and the buffered data amount will change.
|
| + session_->set_writable(true);
|
| + stream_->OnCanWrite();
|
| + EXPECT_EQ(0, mock_stream_delegate_->queued_bytes_amount());
|
| + EXPECT_FALSE(stream_->HasBufferedData());
|
| + EXPECT_EQ("Foo bar", write_buffer_);
|
| +
|
| + stream_->Write("xyzzy", 5, kDefaultParam);
|
| + EXPECT_EQ("Foo barxyzzy", write_buffer_);
|
| +}
|
| +
|
| +// Read an entire string.
|
| +TEST_F(QuartcStreamTest, ReadDataWhole) {
|
| + CreateReliableQuicStream();
|
| + QuicStreamFrame frame(kStreamId, false, 0, "Hello, World!");
|
| + stream_->OnStreamFrame(frame);
|
| +
|
| + EXPECT_EQ("Hello, World!", read_buffer_);
|
| +}
|
| +
|
| +// Read part of a string.
|
| +TEST_F(QuartcStreamTest, ReadDataPartial) {
|
| + CreateReliableQuicStream();
|
| + QuicStreamFrame frame(kStreamId, false, 0, "Hello, World!");
|
| + frame.data_length = 5;
|
| + stream_->OnStreamFrame(frame);
|
| +
|
| + EXPECT_EQ("Hello", read_buffer_);
|
| +}
|
| +
|
| +// Test that closing the stream results in a callback.
|
| +TEST_F(QuartcStreamTest, CloseStream) {
|
| + CreateReliableQuicStream();
|
| + EXPECT_FALSE(mock_stream_delegate_->closed());
|
| + stream_->OnClose();
|
| + EXPECT_TRUE(mock_stream_delegate_->closed());
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +} // namespace net
|
|
|