| Index: net/spdy/spdy_write_queue_unittest.cc
|
| diff --git a/net/spdy/spdy_write_queue_unittest.cc b/net/spdy/spdy_write_queue_unittest.cc
|
| index 6d6cb3cd3b57fe0d1ac253f6b5ca570477517260..2ab415acde57a1a4042e2519adafa753cbcff547 100644
|
| --- a/net/spdy/spdy_write_queue_unittest.cc
|
| +++ b/net/spdy/spdy_write_queue_unittest.cc
|
| @@ -23,6 +23,11 @@ namespace net {
|
|
|
| namespace {
|
|
|
| +using std::string;
|
| +
|
| +const char kOriginal[] = "original";
|
| +const char kRequeued[] = "requeued";
|
| +
|
| class SpdyWriteQueueTest : public ::testing::Test {};
|
|
|
| // Makes a SpdyFrameProducer producing a frame with the data in the
|
| @@ -44,6 +49,35 @@ scoped_ptr<SpdyBufferProducer> IntToProducer(int i) {
|
| return StringToProducer(base::IntToString(i));
|
| }
|
|
|
| +// Producer whose produced buffer will enqueue yet another buffer into the
|
| +// SpdyWriteQueue upon destruction.
|
| +class RequeingBufferProducer : public SpdyBufferProducer {
|
| + public:
|
| + RequeingBufferProducer(SpdyWriteQueue* queue) {
|
| + buffer_.reset(new SpdyBuffer(kOriginal, arraysize(kOriginal)));
|
| + buffer_->AddConsumeCallback(
|
| + base::Bind(RequeingBufferProducer::ConsumeCallback, queue));
|
| + }
|
| +
|
| + virtual scoped_ptr<SpdyBuffer> ProduceBuffer() OVERRIDE {
|
| + return buffer_.Pass();
|
| + }
|
| +
|
| + static void ConsumeCallback(SpdyWriteQueue* queue,
|
| + size_t size,
|
| + SpdyBuffer::ConsumeSource source) {
|
| + scoped_ptr<SpdyBufferProducer> producer(
|
| + new SimpleBufferProducer(scoped_ptr<SpdyBuffer>(
|
| + new SpdyBuffer(kRequeued, arraysize(kRequeued)))));
|
| +
|
| + queue->Enqueue(
|
| + MEDIUM, RST_STREAM, producer.Pass(), base::WeakPtr<SpdyStream>());
|
| + }
|
| +
|
| + private:
|
| + scoped_ptr<SpdyBuffer> buffer_;
|
| +};
|
| +
|
| // Produces a frame with the given producer and returns a copy of its
|
| // data as a string.
|
| std::string ProducerToString(scoped_ptr<SpdyBufferProducer> producer) {
|
| @@ -247,6 +281,96 @@ TEST_F(SpdyWriteQueueTest, Clear) {
|
| EXPECT_FALSE(write_queue.Dequeue(&frame_type, &frame_producer, &stream));
|
| }
|
|
|
| +TEST_F(SpdyWriteQueueTest, RequeingProducerWithoutReentrance) {
|
| + SpdyWriteQueue queue;
|
| + queue.Enqueue(
|
| + DEFAULT_PRIORITY,
|
| + SYN_STREAM,
|
| + scoped_ptr<SpdyBufferProducer>(new RequeingBufferProducer(&queue)),
|
| + base::WeakPtr<SpdyStream>());
|
| + {
|
| + SpdyFrameType frame_type;
|
| + scoped_ptr<SpdyBufferProducer> producer;
|
| + base::WeakPtr<SpdyStream> stream;
|
| +
|
| + EXPECT_TRUE(queue.Dequeue(&frame_type, &producer, &stream));
|
| + EXPECT_TRUE(queue.IsEmpty());
|
| + EXPECT_EQ(string(kOriginal), producer->ProduceBuffer()->GetRemainingData());
|
| + }
|
| + // |producer| was destroyed, and a buffer is re-queued.
|
| + EXPECT_FALSE(queue.IsEmpty());
|
| +
|
| + SpdyFrameType frame_type;
|
| + scoped_ptr<SpdyBufferProducer> producer;
|
| + base::WeakPtr<SpdyStream> stream;
|
| +
|
| + EXPECT_TRUE(queue.Dequeue(&frame_type, &producer, &stream));
|
| + EXPECT_EQ(string(kRequeued), producer->ProduceBuffer()->GetRemainingData());
|
| +}
|
| +
|
| +TEST_F(SpdyWriteQueueTest, ReentranceOnClear) {
|
| + SpdyWriteQueue queue;
|
| + queue.Enqueue(
|
| + DEFAULT_PRIORITY,
|
| + SYN_STREAM,
|
| + scoped_ptr<SpdyBufferProducer>(new RequeingBufferProducer(&queue)),
|
| + base::WeakPtr<SpdyStream>());
|
| +
|
| + queue.Clear();
|
| + EXPECT_FALSE(queue.IsEmpty());
|
| +
|
| + SpdyFrameType frame_type;
|
| + scoped_ptr<SpdyBufferProducer> producer;
|
| + base::WeakPtr<SpdyStream> stream;
|
| +
|
| + EXPECT_TRUE(queue.Dequeue(&frame_type, &producer, &stream));
|
| + EXPECT_EQ(string(kRequeued), producer->ProduceBuffer()->GetRemainingData());
|
| +}
|
| +
|
| +TEST_F(SpdyWriteQueueTest, ReentranceOnRemovePendingWritesAfter) {
|
| + scoped_ptr<SpdyStream> stream(MakeTestStream(DEFAULT_PRIORITY));
|
| + stream->set_stream_id(2);
|
| +
|
| + SpdyWriteQueue queue;
|
| + queue.Enqueue(
|
| + DEFAULT_PRIORITY,
|
| + SYN_STREAM,
|
| + scoped_ptr<SpdyBufferProducer>(new RequeingBufferProducer(&queue)),
|
| + stream->GetWeakPtr());
|
| +
|
| + queue.RemovePendingWritesForStreamsAfter(1);
|
| + EXPECT_FALSE(queue.IsEmpty());
|
| +
|
| + SpdyFrameType frame_type;
|
| + scoped_ptr<SpdyBufferProducer> producer;
|
| + base::WeakPtr<SpdyStream> weak_stream;
|
| +
|
| + EXPECT_TRUE(queue.Dequeue(&frame_type, &producer, &weak_stream));
|
| + EXPECT_EQ(string(kRequeued), producer->ProduceBuffer()->GetRemainingData());
|
| +}
|
| +
|
| +TEST_F(SpdyWriteQueueTest, ReentranceOnRemovePendingWritesForStream) {
|
| + scoped_ptr<SpdyStream> stream(MakeTestStream(DEFAULT_PRIORITY));
|
| + stream->set_stream_id(2);
|
| +
|
| + SpdyWriteQueue queue;
|
| + queue.Enqueue(
|
| + DEFAULT_PRIORITY,
|
| + SYN_STREAM,
|
| + scoped_ptr<SpdyBufferProducer>(new RequeingBufferProducer(&queue)),
|
| + stream->GetWeakPtr());
|
| +
|
| + queue.RemovePendingWritesForStream(stream->GetWeakPtr());
|
| + EXPECT_FALSE(queue.IsEmpty());
|
| +
|
| + SpdyFrameType frame_type;
|
| + scoped_ptr<SpdyBufferProducer> producer;
|
| + base::WeakPtr<SpdyStream> weak_stream;
|
| +
|
| + EXPECT_TRUE(queue.Dequeue(&frame_type, &producer, &weak_stream));
|
| + EXPECT_EQ(string(kRequeued), producer->ProduceBuffer()->GetRemainingData());
|
| +}
|
| +
|
| } // namespace
|
|
|
| } // namespace net
|
|
|