diff options
Diffstat (limited to 'chromium/content/browser/streams/stream_unittest.cc')
| -rw-r--r-- | chromium/content/browser/streams/stream_unittest.cc | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/chromium/content/browser/streams/stream_unittest.cc b/chromium/content/browser/streams/stream_unittest.cc new file mode 100644 index 00000000000..c0077b7375b --- /dev/null +++ b/chromium/content/browser/streams/stream_unittest.cc @@ -0,0 +1,253 @@ +// Copyright (c) 2013 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 "base/message_loop/message_loop.h" +#include "base/test/test_simple_task_runner.h" +#include "content/browser/streams/stream.h" +#include "content/browser/streams/stream_read_observer.h" +#include "content/browser/streams/stream_registry.h" +#include "content/browser/streams/stream_write_observer.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace content { + +class StreamTest : public testing::Test { + public: + StreamTest() : producing_seed_key_(0) {} + + virtual void SetUp() OVERRIDE { + registry_.reset(new StreamRegistry()); + } + + // Create a new IO buffer of the given |buffer_size| and fill it with random + // data. + scoped_refptr<net::IOBuffer> NewIOBuffer(size_t buffer_size) { + scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(buffer_size)); + char *bufferp = buffer->data(); + for (size_t i = 0; i < buffer_size; i++) + bufferp[i] = (i + producing_seed_key_) % (1 << sizeof(char)); + ++producing_seed_key_; + return buffer; + } + + protected: + base::MessageLoop message_loop_; + scoped_ptr<StreamRegistry> registry_; + + private: + int producing_seed_key_; +}; + +class TestStreamReader : public StreamReadObserver { + public: + TestStreamReader() : buffer_(new net::GrowableIOBuffer()), completed_(false) { + } + virtual ~TestStreamReader() {} + + void Read(Stream* stream) { + const size_t kBufferSize = 32768; + scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize)); + + int bytes_read = 0; + while (true) { + Stream::StreamState state = + stream->ReadRawData(buffer.get(), kBufferSize, &bytes_read); + switch (state) { + case Stream::STREAM_HAS_DATA: + // TODO(tyoshino): Move these expectations to the beginning of Read() + // method once Stream::Finalize() is fixed. + EXPECT_FALSE(completed_); + break; + case Stream::STREAM_COMPLETE: + completed_ = true; + return; + case Stream::STREAM_EMPTY: + EXPECT_FALSE(completed_); + return; + } + size_t old_capacity = buffer_->capacity(); + buffer_->SetCapacity(old_capacity + bytes_read); + memcpy(buffer_->StartOfBuffer() + old_capacity, + buffer->data(), bytes_read); + } + } + + virtual void OnDataAvailable(Stream* stream) OVERRIDE { + Read(stream); + } + + scoped_refptr<net::GrowableIOBuffer> buffer() { return buffer_; } + + bool completed() const { + return completed_; + } + + private: + scoped_refptr<net::GrowableIOBuffer> buffer_; + bool completed_; +}; + +class TestStreamWriter : public StreamWriteObserver { + public: + TestStreamWriter() {} + virtual ~TestStreamWriter() {} + + void Write(Stream* stream, + scoped_refptr<net::IOBuffer> buffer, + size_t buffer_size) { + stream->AddData(buffer, buffer_size); + } + + virtual void OnSpaceAvailable(Stream* stream) OVERRIDE { + } + + virtual void OnClose(Stream* stream) OVERRIDE { + } +}; + +TEST_F(StreamTest, SetReadObserver) { + TestStreamReader reader; + TestStreamWriter writer; + + GURL url("blob://stream"); + scoped_refptr<Stream> stream( + new Stream(registry_.get(), &writer, url)); + EXPECT_TRUE(stream->SetReadObserver(&reader)); +} + +TEST_F(StreamTest, SetReadObserver_SecondFails) { + TestStreamReader reader1; + TestStreamReader reader2; + TestStreamWriter writer; + + GURL url("blob://stream"); + scoped_refptr<Stream> stream( + new Stream(registry_.get(), &writer, url)); + EXPECT_TRUE(stream->SetReadObserver(&reader1)); + EXPECT_FALSE(stream->SetReadObserver(&reader2)); +} + +TEST_F(StreamTest, SetReadObserver_TwoReaders) { + TestStreamReader reader1; + TestStreamReader reader2; + TestStreamWriter writer; + + GURL url("blob://stream"); + scoped_refptr<Stream> stream( + new Stream(registry_.get(), &writer, url)); + EXPECT_TRUE(stream->SetReadObserver(&reader1)); + + // Once the first read observer is removed, a new one can be added. + stream->RemoveReadObserver(&reader1); + EXPECT_TRUE(stream->SetReadObserver(&reader2)); +} + +TEST_F(StreamTest, Stream) { + TestStreamReader reader; + TestStreamWriter writer; + + GURL url("blob://stream"); + scoped_refptr<Stream> stream( + new Stream(registry_.get(), &writer, url)); + EXPECT_TRUE(stream->SetReadObserver(&reader)); + + const int kBufferSize = 1000000; + scoped_refptr<net::IOBuffer> buffer(NewIOBuffer(kBufferSize)); + writer.Write(stream.get(), buffer, kBufferSize); + stream->Finalize(); + base::MessageLoop::current()->RunUntilIdle(); + EXPECT_TRUE(reader.completed()); + + ASSERT_EQ(reader.buffer()->capacity(), kBufferSize); + for (int i = 0; i < kBufferSize; i++) + EXPECT_EQ(buffer->data()[i], reader.buffer()->data()[i]); +} + +// Test that even if a reader receives an empty buffer, once TransferData() +// method is called on it with |source_complete| = true, following Read() calls +// on it never returns STREAM_EMPTY. Together with StreamTest.Stream above, this +// guarantees that Reader::Read() call returns only STREAM_HAS_DATA +// or STREAM_COMPLETE in |data_available_callback_| call corresponding to +// Writer::Close(). +TEST_F(StreamTest, ClosedReaderDoesNotReturnStreamEmpty) { + TestStreamReader reader; + TestStreamWriter writer; + + GURL url("blob://stream"); + scoped_refptr<Stream> stream( + new Stream(registry_.get(), &writer, url)); + EXPECT_TRUE(stream->SetReadObserver(&reader)); + + const int kBufferSize = 0; + scoped_refptr<net::IOBuffer> buffer(NewIOBuffer(kBufferSize)); + stream->AddData(buffer, kBufferSize); + stream->Finalize(); + base::MessageLoop::current()->RunUntilIdle(); + EXPECT_TRUE(reader.completed()); + EXPECT_EQ(0, reader.buffer()->capacity()); +} + +TEST_F(StreamTest, GetStream) { + TestStreamWriter writer; + + GURL url("blob://stream"); + scoped_refptr<Stream> stream1( + new Stream(registry_.get(), &writer, url)); + + scoped_refptr<Stream> stream2 = registry_->GetStream(url); + ASSERT_EQ(stream1, stream2); +} + +TEST_F(StreamTest, GetStream_Missing) { + TestStreamWriter writer; + + GURL url1("blob://stream"); + scoped_refptr<Stream> stream1( + new Stream(registry_.get(), &writer, url1)); + + GURL url2("blob://stream2"); + scoped_refptr<Stream> stream2 = registry_->GetStream(url2); + ASSERT_FALSE(stream2.get()); +} + +TEST_F(StreamTest, CloneStream) { + TestStreamWriter writer; + + GURL url1("blob://stream"); + scoped_refptr<Stream> stream1( + new Stream(registry_.get(), &writer, url1)); + + GURL url2("blob://stream2"); + ASSERT_TRUE(registry_->CloneStream(url2, url1)); + scoped_refptr<Stream> stream2 = registry_->GetStream(url2); + ASSERT_EQ(stream1, stream2); +} + +TEST_F(StreamTest, CloneStream_Missing) { + TestStreamWriter writer; + + GURL url1("blob://stream"); + scoped_refptr<Stream> stream1( + new Stream(registry_.get(), &writer, url1)); + + GURL url2("blob://stream2"); + GURL url3("blob://stream3"); + ASSERT_FALSE(registry_->CloneStream(url2, url3)); + scoped_refptr<Stream> stream2 = registry_->GetStream(url2); + ASSERT_FALSE(stream2.get()); +} + +TEST_F(StreamTest, UnregisterStream) { + TestStreamWriter writer; + + GURL url("blob://stream"); + scoped_refptr<Stream> stream1( + new Stream(registry_.get(), &writer, url)); + + registry_->UnregisterStream(url); + scoped_refptr<Stream> stream2 = registry_->GetStream(url); + ASSERT_FALSE(stream2.get()); +} + +} // namespace content |
