Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(62)

Unified Diff: content/browser/download/byte_stream_unittest.cc

Issue 10074001: Initial implementation of the ByteStream refactor. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Checkpoint and merge to LKGR. Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « content/browser/download/byte_stream.cc ('k') | content/browser/download/download_buffer.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/browser/download/byte_stream_unittest.cc
diff --git a/content/browser/download/byte_stream_unittest.cc b/content/browser/download/byte_stream_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..0498fb86b767d56de99878d62d57c194707c02de
--- /dev/null
+++ b/content/browser/download/byte_stream_unittest.cc
@@ -0,0 +1,477 @@
+// 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 "base/bind.h"
+#include "base/callback.h"
+#include "base/location.h"
+#include "base/memory/ref_counted.h"
+#include "base/task_runner.h"
+#include "content/browser/download/byte_stream.h"
+#include "net/base/io_buffer.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+using ::testing::Return;
+using ::testing::SaveArg;
+using ::testing::StrictMock;
+
+namespace tracked_objects {
+class Location;
+}
+
+namespace {
+
+class MockTaskRunner : public base::TaskRunner {
+ public:
+ MockTaskRunner();
+
+ // TaskRunner functions.
+ MOCK_METHOD3(PostDelayedTask, bool(const tracked_objects::Location&,
+ const base::Closure&, int64));
+ MOCK_METHOD3(PostDelayedTask, bool(const tracked_objects::Location&,
+ const base::Closure&, base::TimeDelta));
+ MOCK_CONST_METHOD0(RunsTasksOnCurrentThread, bool());
+
+ protected:
+ ~MockTaskRunner();
+};
+
+MockTaskRunner::MockTaskRunner() { }
+
+MockTaskRunner::~MockTaskRunner() { }
+
+int null_callback_call_count = 0;
+
+void NullCallback(int arg) {
+ null_callback_call_count++;
+}
+
+} // namespace
+
+class ByteStreamTest : public testing::Test {
+ public:
+ // Create a new IO buffer of the given |buffer_size|, with contents
+ // dependent on the |seed_key|. The |seed_key| is also used for comparing
+ // pointers between NewIOBuffer and ValidateIOBuffer; do not re-use any
+ // |seed_key| value within a single test.
+ scoped_refptr<net::IOBuffer> NewIOBuffer(size_t buffer_size, int seed_key) {
+ 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 + seed_key) % (1 << sizeof(char));
+ DCHECK(pointer_map_.find(seed_key) == pointer_map_.end());
+ DCHECK(length_map_.find(seed_key) == length_map_.end());
+ pointer_map_[seed_key] = bufferp;
+ length_map_[seed_key] = buffer_size;
+ return buffer;
+ }
+
+ // Create an IOBuffer of the appropriate size and add it to the
+ // ByteStream, returning the result of the ByteStream::AddData.
+ // Separate function to avoid duplication of buffer_size in test
+ // calls.
+ bool AddData(scoped_refptr<content::ByteStream> byte_stream,
+ int seed_key, size_t buffer_size) {
+ return byte_stream->AddData(NewIOBuffer(buffer_size, seed_key),
+ buffer_size);
+ }
+
+ // Validate that we have the IOBuffer we expect. This IOBuffer must
+ // have been created through NewIOBuffer with the given |buffer_size|
+ // and |seed_key|.
+ bool ValidateIOBuffer(scoped_refptr<net::IOBuffer> buffer, int seed_key,
+ size_t buffer_size) {
+ char *bufferp = buffer->data();
+ EXPECT_TRUE(pointer_map_.find(seed_key) != pointer_map_.end());
+ if (pointer_map_.find(seed_key) == pointer_map_.end())
+ return false;
+ EXPECT_EQ(bufferp, pointer_map_[seed_key]);
+ EXPECT_TRUE(length_map_.find(seed_key) != length_map_.end());
+ if (length_map_.find(seed_key) == length_map_.end())
+ return false;
+ EXPECT_EQ(buffer_size, length_map_[seed_key]);
+ for (size_t i = 0; i < buffer_size; i++) {
+ EXPECT_EQ(static_cast<int>((i + seed_key) % (1 << sizeof(char))),
+ bufferp[i]);
+ if (static_cast<int>((i + seed_key) % (1 << sizeof(char))) != bufferp[i])
+ return false;
+ }
+ return true;
+ }
+
+ private:
+ std::map<int, char*> pointer_map_;
+ std::map<int, size_t> length_map_;
+};
+
+// Confirm that filling and emptying the pipe works properly, and that
+// we get full triggers when we expect.
+TEST_F(ByteStreamTest, PushBack) {
+ scoped_refptr<content::ByteStream> byte_stream(new content::ByteStream());
+ byte_stream->SetBufferSize(3 * 1024);
+
+ // Push a series of IO buffers on; test pushback happening and
+ // that it's advisory.
+ EXPECT_TRUE(AddData(byte_stream, 0, 1024));
+ EXPECT_FALSE(byte_stream->IsFull());
+ EXPECT_TRUE(AddData(byte_stream, 1, 1024));
+ EXPECT_FALSE(byte_stream->IsFull());
+ EXPECT_TRUE(AddData(byte_stream, 2, 1024));
+ EXPECT_FALSE(byte_stream->IsFull());
+ EXPECT_FALSE(AddData(byte_stream, 3, 1));
+ EXPECT_TRUE(byte_stream->IsFull());
+ EXPECT_FALSE(AddData(byte_stream, 4, 1024));
+ EXPECT_TRUE(byte_stream->IsFull());
+ EXPECT_EQ(0u, byte_stream->bytes_read());
+ EXPECT_EQ(0u, byte_stream->buffers_read());
+
+ // Pull the IO buffers out; do we get the same buffers and do they
+ // have the same contents?
+ scoped_refptr<net::IOBuffer> output_io_buffer;
+ size_t output_length;
+ EXPECT_EQ(content::ByteStream::STREAM_HAS_DATA,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 0, output_length));
+ EXPECT_EQ(1024u, byte_stream->bytes_read());
+ EXPECT_EQ(1u, byte_stream->buffers_read());
+
+ EXPECT_EQ(content::ByteStream::STREAM_HAS_DATA,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 1, output_length));
+ EXPECT_EQ(2048u, byte_stream->bytes_read());
+ EXPECT_EQ(2u, byte_stream->buffers_read());
+
+ EXPECT_EQ(content::ByteStream::STREAM_HAS_DATA,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 2, output_length));
+ EXPECT_EQ(3072u, byte_stream->bytes_read());
+ EXPECT_EQ(3u, byte_stream->buffers_read());
+
+ EXPECT_EQ(content::ByteStream::STREAM_HAS_DATA,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 3, output_length));
+ EXPECT_EQ(3073u, byte_stream->bytes_read());
+ EXPECT_EQ(4u, byte_stream->buffers_read());
+
+ EXPECT_EQ(content::ByteStream::STREAM_HAS_DATA,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 4, output_length));
+ EXPECT_EQ(4097u, byte_stream->bytes_read());
+ EXPECT_EQ(5u, byte_stream->buffers_read());
+
+ EXPECT_EQ(content::ByteStream::STREAM_EMPTY,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+}
+
+// Confirm that a SourceComplete() notification transmits in-order
+// with data on the pipe.
+TEST_F(ByteStreamTest, CompleteTransmits) {
+ scoped_refptr<content::ByteStream> byte_stream;
+
+ scoped_refptr<net::IOBuffer> output_io_buffer;
+ size_t output_length;
+
+ // Empty stream, non-error case.
+ byte_stream = new content::ByteStream();
+ EXPECT_EQ(content::ByteStream::STREAM_EMPTY,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ byte_stream->SourceComplete(content::DOWNLOAD_INTERRUPT_REASON_NONE);
+ ASSERT_EQ(content::ByteStream::STREAM_COMPLETE,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ EXPECT_EQ(content::DOWNLOAD_INTERRUPT_REASON_NONE,
+ byte_stream->GetSourceResult());
+
+ // Non-empty stream, non-error case.
+ byte_stream = new content::ByteStream();
+ EXPECT_EQ(content::ByteStream::STREAM_EMPTY,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ EXPECT_TRUE(AddData(byte_stream, 0, 1024));
+ byte_stream->SourceComplete(content::DOWNLOAD_INTERRUPT_REASON_NONE);
+ EXPECT_EQ(content::ByteStream::STREAM_HAS_DATA,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 0, output_length));
+ ASSERT_EQ(content::ByteStream::STREAM_COMPLETE,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ EXPECT_EQ(content::DOWNLOAD_INTERRUPT_REASON_NONE,
+ byte_stream->GetSourceResult());
+
+ // Empty stream, non-error case.
+ byte_stream = new content::ByteStream();
+ EXPECT_EQ(content::ByteStream::STREAM_EMPTY,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ byte_stream->SourceComplete(
+ content::DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED);
+ ASSERT_EQ(content::ByteStream::STREAM_COMPLETE,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ EXPECT_EQ(content::DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED,
+ byte_stream->GetSourceResult());
+
+ // Non-empty stream, non-error case.
+ byte_stream = new content::ByteStream();
+ EXPECT_EQ(content::ByteStream::STREAM_EMPTY,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ EXPECT_TRUE(AddData(byte_stream, 1, 1024));
+ byte_stream->SourceComplete(
+ content::DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED);
+ EXPECT_EQ(content::ByteStream::STREAM_HAS_DATA,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 1, output_length));
+ ASSERT_EQ(content::ByteStream::STREAM_COMPLETE,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ EXPECT_EQ(content::DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED,
+ byte_stream->GetSourceResult());
+}
+
+// Confirm that callbacks on the sink side are triggered when they should be.
+TEST_F(ByteStreamTest, SinkCallback) {
+ scoped_refptr<MockTaskRunner> task_runner(new StrictMock<MockTaskRunner>());
+ int null_callback_call_count_start = 0;
+
+ scoped_refptr<content::ByteStream> byte_stream(new content::ByteStream());
+ byte_stream->SetBufferSize(10000);
+
+ scoped_refptr<net::IOBuffer> output_io_buffer;
+ size_t output_length;
+ base::Closure intermediate_callback;
+
+ // Callback to be called on any data.
+ byte_stream->RegisterSinkCallback(task_runner,
+ base::Bind(NullCallback, 0),
+ 0);
+ null_callback_call_count_start = null_callback_call_count;
+ EXPECT_CALL(*task_runner.get(), PostDelayedTask(_, _, 0))
+ .WillOnce(DoAll(SaveArg<1>(&intermediate_callback),
+ Return(true)));
+ EXPECT_EQ(0u, byte_stream->num_sink_callbacks());
+ EXPECT_TRUE(AddData(byte_stream, 0, 1024));
+ EXPECT_EQ(1u, byte_stream->num_sink_callbacks());
+ ::testing::Mock::VerifyAndClearExpectations(task_runner.get());
+ EXPECT_EQ(null_callback_call_count_start, null_callback_call_count);
+ intermediate_callback.Run();
+ EXPECT_EQ(null_callback_call_count_start+1, null_callback_call_count);
+ EXPECT_EQ(content::ByteStream::STREAM_HAS_DATA,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 0, output_length));
+ EXPECT_EQ(content::ByteStream::STREAM_EMPTY,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+
+ // Callback to be called on 33% full.
+ byte_stream->RegisterSinkCallback(task_runner,
+ base::Bind(NullCallback, 0),
+ 33);
+ null_callback_call_count_start = null_callback_call_count;
+ EXPECT_TRUE(AddData(byte_stream, 1, 3300));
+ EXPECT_CALL(*task_runner.get(), PostDelayedTask(_, _, 0))
+ .WillOnce(DoAll(SaveArg<1>(&intermediate_callback),
+ Return(true)));
+ EXPECT_EQ(1u, byte_stream->num_sink_callbacks());
+ EXPECT_TRUE(AddData(byte_stream, 2, 1));
+ EXPECT_EQ(2u, byte_stream->num_sink_callbacks());
+ ::testing::Mock::VerifyAndClearExpectations(task_runner.get());
+ EXPECT_EQ(null_callback_call_count_start, null_callback_call_count);
+ intermediate_callback.Run();
+ EXPECT_EQ(null_callback_call_count_start+1, null_callback_call_count);
+ EXPECT_EQ(content::ByteStream::STREAM_HAS_DATA,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 1, output_length));
+ EXPECT_EQ(content::ByteStream::STREAM_HAS_DATA,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 2, output_length));
+ EXPECT_EQ(content::ByteStream::STREAM_EMPTY,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+
+ // Callback to be called on 100% full.
+ byte_stream->RegisterSinkCallback(task_runner,
+ base::Bind(NullCallback, 0),
+ 100);
+ null_callback_call_count_start = null_callback_call_count;
+ EXPECT_TRUE(AddData(byte_stream, 3, 3300));
+ EXPECT_TRUE(AddData(byte_stream, 4, 3300));
+ EXPECT_TRUE(AddData(byte_stream, 5, 3400));
+ EXPECT_CALL(*task_runner.get(), PostDelayedTask(_, _, 0))
+ .WillOnce(DoAll(SaveArg<1>(&intermediate_callback),
+ Return(true)));
+ EXPECT_EQ(2u, byte_stream->num_sink_callbacks());
+ EXPECT_FALSE(AddData(byte_stream, 6, 1));
+ EXPECT_EQ(3u, byte_stream->num_sink_callbacks());
+ ::testing::Mock::VerifyAndClearExpectations(task_runner.get());
+ EXPECT_EQ(null_callback_call_count_start, null_callback_call_count);
+ intermediate_callback.Run();
+ EXPECT_EQ(null_callback_call_count_start+1, null_callback_call_count);
+ EXPECT_EQ(content::ByteStream::STREAM_HAS_DATA,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 3, output_length));
+ EXPECT_EQ(content::ByteStream::STREAM_HAS_DATA,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 4, output_length));
+ EXPECT_EQ(content::ByteStream::STREAM_HAS_DATA,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 5, output_length));
+ EXPECT_EQ(content::ByteStream::STREAM_HAS_DATA,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 6, output_length));
+ EXPECT_EQ(content::ByteStream::STREAM_EMPTY,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ EXPECT_EQ(3u, byte_stream->num_sink_callbacks());
+}
+
+// Confirm that callbacks on the source side are triggered when they should
+// be.
+TEST_F(ByteStreamTest, SourceCallback) {
+ scoped_refptr<MockTaskRunner> task_runner(new StrictMock<MockTaskRunner>());
+ int null_callback_call_count_start = 0;
+
+ scoped_refptr<content::ByteStream> byte_stream(new content::ByteStream());
+ byte_stream->SetBufferSize(10000);
+
+ scoped_refptr<net::IOBuffer> output_io_buffer;
+ size_t output_length;
+ base::Closure intermediate_callback;
+
+ // Confirm callback called when any space available.
+ EXPECT_TRUE(AddData(byte_stream, 0, 1));
+ EXPECT_FALSE(AddData(byte_stream, 1, 10000));
+ byte_stream->RegisterSourceCallback(task_runner,
+ base::Bind(NullCallback, 0),
+ 0);
+ null_callback_call_count_start = null_callback_call_count;
+ EXPECT_CALL(*task_runner.get(), PostDelayedTask(_, _, 0))
+ .WillOnce(DoAll(SaveArg<1>(&intermediate_callback),
+ Return(true)));
+ EXPECT_EQ(0u, byte_stream->num_source_callbacks());
+ EXPECT_EQ(content::ByteStream::STREAM_HAS_DATA,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ EXPECT_EQ(1u, byte_stream->num_source_callbacks());
+ EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 0, output_length));
+ ::testing::Mock::VerifyAndClearExpectations(task_runner.get());
+ intermediate_callback.Run();
+ EXPECT_EQ(null_callback_call_count_start+1, null_callback_call_count);
+ EXPECT_EQ(content::ByteStream::STREAM_HAS_DATA,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 1, output_length));
+ EXPECT_EQ(content::ByteStream::STREAM_EMPTY,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+
+ // Confirm callback called when 33% space available.
+ EXPECT_TRUE(AddData(byte_stream, 2, 3300));
+ EXPECT_TRUE(AddData(byte_stream, 3, 1));
+ EXPECT_FALSE(AddData(byte_stream, 4, 6700));
+ byte_stream->RegisterSourceCallback(task_runner,
+ base::Bind(NullCallback, 0),
+ 33);
+ null_callback_call_count_start = null_callback_call_count;
+ EXPECT_EQ(content::ByteStream::STREAM_HAS_DATA,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 2, output_length));
+ EXPECT_CALL(*task_runner.get(), PostDelayedTask(_, _, 0))
+ .WillOnce(DoAll(SaveArg<1>(&intermediate_callback),
+ Return(true)));
+ EXPECT_EQ(1u, byte_stream->num_source_callbacks());
+ EXPECT_EQ(content::ByteStream::STREAM_HAS_DATA,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ EXPECT_EQ(2u, byte_stream->num_source_callbacks());
+ EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 3, output_length));
+ ::testing::Mock::VerifyAndClearExpectations(task_runner.get());
+ intermediate_callback.Run();
+ EXPECT_EQ(null_callback_call_count_start+1, null_callback_call_count);
+ EXPECT_EQ(content::ByteStream::STREAM_HAS_DATA,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 4, output_length));
+ EXPECT_EQ(content::ByteStream::STREAM_EMPTY,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+
+ // Confirm callback called only when 100% space available.
+ EXPECT_TRUE(AddData(byte_stream, 5, 3300));
+ EXPECT_TRUE(AddData(byte_stream, 6, 6700));
+ EXPECT_FALSE(AddData(byte_stream, 7, 1));
+ byte_stream->RegisterSourceCallback(task_runner,
+ base::Bind(NullCallback, 0),
+ 100);
+ null_callback_call_count_start = null_callback_call_count;
+ EXPECT_EQ(2u, byte_stream->num_source_callbacks());
+ EXPECT_EQ(content::ByteStream::STREAM_HAS_DATA,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ EXPECT_EQ(3u, byte_stream->num_source_callbacks());
+ EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 5, output_length));
+ EXPECT_EQ(content::ByteStream::STREAM_HAS_DATA,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 6, output_length));
+ EXPECT_CALL(*task_runner.get(), PostDelayedTask(_, _, 0))
+ .WillOnce(DoAll(SaveArg<1>(&intermediate_callback),
+ Return(true)));
+ EXPECT_EQ(3u, byte_stream->num_source_callbacks());
+ EXPECT_EQ(content::ByteStream::STREAM_HAS_DATA,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ EXPECT_EQ(4u, byte_stream->num_source_callbacks());
+ EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 7, output_length));
+ ::testing::Mock::VerifyAndClearExpectations(task_runner.get());
+ intermediate_callback.Run();
+ EXPECT_EQ(null_callback_call_count_start+1, null_callback_call_count);
+ EXPECT_EQ(content::ByteStream::STREAM_EMPTY,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ EXPECT_EQ(4u, byte_stream->num_source_callbacks());
+}
+
+// Confirm that changing a sink callback on the same "thread" as the original
+// callback was targeted to results in the callback being dropped on the
+// floor.
+TEST_F(ByteStreamTest, SinkInterrupt) {
+ scoped_refptr<MockTaskRunner> task_runner(new StrictMock<MockTaskRunner>());
+ int null_callback_call_count_start = 0;
+
+ scoped_refptr<content::ByteStream> byte_stream(new content::ByteStream());
+ byte_stream->SetBufferSize(10000);
+
+ base::Closure intermediate_callback;
+
+ // Callback to be called on any data.
+ byte_stream->RegisterSinkCallback(task_runner,
+ base::Bind(NullCallback, 0),
+ 0);
+ null_callback_call_count_start = null_callback_call_count;
+ EXPECT_CALL(*task_runner.get(), PostDelayedTask(_, _, 0))
+ .WillOnce(DoAll(SaveArg<1>(&intermediate_callback),
+ Return(true)));
+ EXPECT_TRUE(AddData(byte_stream, 0, 1024));
+ ::testing::Mock::VerifyAndClearExpectations(task_runner.get());
+ EXPECT_EQ(null_callback_call_count_start, null_callback_call_count);
+ byte_stream->RegisterSinkCallback(scoped_refptr<base::TaskRunner>(),
+ base::Closure(), 0);
+ intermediate_callback.Run();
+ EXPECT_EQ(null_callback_call_count_start, null_callback_call_count);
+}
+
+// Confirm that changing a source callback on the same "thread" as the original
+// callback was targeted to results in the callback being dropped on the
+// floor.
+TEST_F(ByteStreamTest, SourceInterrupt) {
+ scoped_refptr<MockTaskRunner> task_runner(new StrictMock<MockTaskRunner>());
+ int null_callback_call_count_start = 0;
+
+ scoped_refptr<content::ByteStream> byte_stream(new content::ByteStream());
+ byte_stream->SetBufferSize(10000);
+
+ base::Closure intermediate_callback;
+ scoped_refptr<net::IOBuffer> output_io_buffer;
+ size_t output_length;
+
+ EXPECT_TRUE(AddData(byte_stream, 0, 1));
+ EXPECT_FALSE(AddData(byte_stream, 1, 10000));
+ byte_stream->RegisterSourceCallback(task_runner,
+ base::Bind(NullCallback, 0),
+ 0);
+ null_callback_call_count_start = null_callback_call_count;
+ EXPECT_CALL(*task_runner.get(), PostDelayedTask(_, _, 0))
+ .WillOnce(DoAll(SaveArg<1>(&intermediate_callback),
+ Return(true)));
+ EXPECT_EQ(content::ByteStream::STREAM_HAS_DATA,
+ byte_stream->GetData(&output_io_buffer, &output_length));
+ EXPECT_TRUE(ValidateIOBuffer(output_io_buffer, 0, output_length));
+ ::testing::Mock::VerifyAndClearExpectations(task_runner.get());
+ byte_stream->RegisterSourceCallback(scoped_refptr<base::TaskRunner>(),
+ base::Closure(), 0);
+ intermediate_callback.Run();
+ EXPECT_EQ(null_callback_call_count_start, null_callback_call_count);
+}
« no previous file with comments | « content/browser/download/byte_stream.cc ('k') | content/browser/download/download_buffer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698