summaryrefslogtreecommitdiffstats
path: root/media/base/seekable_buffer_unittest.cc
diff options
context:
space:
mode:
authorhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-19 00:26:39 +0000
committerhclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-19 00:26:39 +0000
commitc029795f77cf332b95a2966af82dd2fe256649bb (patch)
tree93839cb805b9630ecfe10e73b813f677337936bc /media/base/seekable_buffer_unittest.cc
parent2248044b2b21b8e9803aa56cad2a48b1bfb66924 (diff)
downloadchromium_src-c029795f77cf332b95a2966af82dd2fe256649bb.zip
chromium_src-c029795f77cf332b95a2966af82dd2fe256649bb.tar.gz
chromium_src-c029795f77cf332b95a2966af82dd2fe256649bb.tar.bz2
SeekableBuffer to implement a window of buffer which has short seeking ability.
Defined the base interface SeekableBuffer and a thread safe implemntation of ThreadSafeSeekableBuffer. This class is to be used for media resource loading that does the meat of buffer queueing and handles short seeking for short distance out-of-order read patterns. Review URL: http://codereview.chromium.org/113213 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16348 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/base/seekable_buffer_unittest.cc')
-rw-r--r--media/base/seekable_buffer_unittest.cc283
1 files changed, 283 insertions, 0 deletions
diff --git a/media/base/seekable_buffer_unittest.cc b/media/base/seekable_buffer_unittest.cc
new file mode 100644
index 0000000..65df7e1
--- /dev/null
+++ b/media/base/seekable_buffer_unittest.cc
@@ -0,0 +1,283 @@
+// Copyright (c) 2009 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/logging.h"
+#include "base/scoped_ptr.h"
+#include "base/time.h"
+#include "media/base/seekable_buffer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+class SeekableBufferTest : public testing::Test {
+ protected:
+ virtual void SetUp() {
+ // Setup seed.
+ size_t seed = static_cast<int32>(base::Time::Now().ToInternalValue());
+ srand(seed);
+ LOG(INFO) << "Random seed: " << seed;
+
+ // Creates a test data.
+ data_.reset(new uint8[kDataSize]);
+ for (size_t i = 0; i < kDataSize; i++)
+ data_.get()[i] = static_cast<char>(rand());
+
+ // Creates a temp buffer.
+ write_buffer_.reset(new uint8[kDataSize]);
+
+ // Setup |buffer_|.
+ buffer_.reset(new media::SeekableBuffer(kBufferSize, kBufferSize));
+ }
+
+ size_t GetRandomInt(size_t maximum) {
+ return rand() % maximum + 1;
+ }
+
+ static const size_t kDataSize = 409600;
+ static const size_t kBufferSize = 4096;
+ scoped_ptr<media::SeekableBuffer> buffer_;
+ scoped_array<uint8> data_;
+ scoped_array<uint8> write_buffer_;
+};
+
+TEST_F(SeekableBufferTest, RandomReadWrite) {
+ size_t write_position = 0;
+ size_t read_position = 0;
+ while (read_position < kDataSize) {
+ // Write a random amount of data.
+ size_t write_size = GetRandomInt(kBufferSize);
+ write_size = std::min(write_size, kDataSize - write_position);
+ bool should_append =
+ buffer_->Append(write_size, data_.get() + write_position);
+ write_position += write_size;
+ EXPECT_GE(write_position, read_position);
+ EXPECT_EQ(write_position - read_position, buffer_->forward_bytes());
+ EXPECT_EQ(should_append, buffer_->forward_bytes() < kBufferSize)
+ << "Incorrect buffer full reported";
+
+ // Read a random amount of data.
+ size_t read_size = GetRandomInt(kBufferSize);
+ size_t bytes_read = buffer_->Read(read_size, write_buffer_.get());
+ EXPECT_GE(read_size, bytes_read);
+ EXPECT_EQ(0, memcmp(write_buffer_.get(),
+ data_.get() + read_position,
+ bytes_read));
+ read_position += bytes_read;
+ EXPECT_GE(write_position, read_position);
+ EXPECT_EQ(write_position - read_position, buffer_->forward_bytes());
+ }
+}
+
+TEST_F(SeekableBufferTest, ReadWriteSeek) {
+ const size_t kWriteSize = 512;
+ const size_t kReadSize = kWriteSize / 4;
+
+ size_t write_position = 0;
+ size_t read_position = 0;
+ size_t forward_bytes = 0;
+ for (int i = 0; i < 10; ++i) {
+ // Write until buffer is full.
+ for (int j = kBufferSize / kWriteSize; j > 0; --j) {
+ bool should_append =
+ buffer_->Append(kWriteSize, data_.get() + write_position);
+ EXPECT_EQ(j > 1, should_append) << "Incorrect buffer full reported";
+ write_position += kWriteSize;
+ forward_bytes += kWriteSize;
+ EXPECT_EQ(forward_bytes, buffer_->forward_bytes());
+ }
+
+ // Simulate a read and seek pattern. Each loop reads 4 times, each time
+ // reading a quarter of |kWriteSize|.
+ for (size_t j = 0; j < kBufferSize / kWriteSize; ++j) {
+ // Read.
+ EXPECT_EQ(kReadSize, buffer_->Read(kReadSize, write_buffer_.get()));
+ forward_bytes -= kReadSize;
+ EXPECT_EQ(forward_bytes, buffer_->forward_bytes());
+ EXPECT_EQ(0, memcmp(write_buffer_.get(),
+ data_.get() + read_position,
+ kReadSize));
+ read_position += kReadSize;
+
+ // Seek forward.
+ EXPECT_TRUE(buffer_->Seek(2 * kReadSize));
+ forward_bytes -= 2 * kReadSize;
+ read_position += 2 * kReadSize;
+ EXPECT_EQ(forward_bytes, buffer_->forward_bytes());
+
+ // Read.
+ EXPECT_EQ(kReadSize, buffer_->Read(kReadSize, write_buffer_.get()));
+ forward_bytes -= kReadSize;
+ EXPECT_EQ(forward_bytes, buffer_->forward_bytes());
+ EXPECT_EQ(0, memcmp(write_buffer_.get(),
+ data_.get() + read_position,
+ kReadSize));
+ read_position += kReadSize;
+
+ // Seek backward.
+ EXPECT_TRUE(buffer_->Seek(-3 * static_cast<int32>(kReadSize)));
+ forward_bytes += 3 * kReadSize;
+ read_position -= 3 * kReadSize;
+ EXPECT_EQ(forward_bytes, buffer_->forward_bytes());
+
+ // Read.
+ EXPECT_EQ(kReadSize, buffer_->Read(kReadSize, write_buffer_.get()));
+ forward_bytes -= kReadSize;
+ EXPECT_EQ(forward_bytes, buffer_->forward_bytes());
+ EXPECT_EQ(0, memcmp(write_buffer_.get(),
+ data_.get() + read_position,
+ kReadSize));
+ read_position += kReadSize;
+
+ // Read.
+ EXPECT_EQ(kReadSize, buffer_->Read(kReadSize, write_buffer_.get()));
+ forward_bytes -= kReadSize;
+ EXPECT_EQ(forward_bytes, buffer_->forward_bytes());
+ EXPECT_EQ(0, memcmp(write_buffer_.get(),
+ data_.get() + read_position,
+ kReadSize));
+ read_position += kReadSize;
+
+ // Seek forward.
+ EXPECT_TRUE(buffer_->Seek(kReadSize));
+ forward_bytes -= kReadSize;
+ read_position += kReadSize;
+ EXPECT_EQ(forward_bytes, buffer_->forward_bytes());
+ }
+ }
+}
+
+TEST_F(SeekableBufferTest, BufferFull) {
+ const size_t kWriteSize = 512;
+
+ // Write and expect the buffer to be not full.
+ size_t write_position = 0;
+ for (size_t i = 0; i < kBufferSize / kWriteSize - 1; ++i) {
+ EXPECT_TRUE(buffer_->Append(kWriteSize, data_.get() + write_position));
+ write_position += kWriteSize;
+ EXPECT_EQ(write_position, buffer_->forward_bytes());
+ }
+
+ // Write 10 more times, the buffer is full.
+ for (int i = 0; i < 10; ++i) {
+ EXPECT_FALSE(buffer_->Append(kWriteSize, data_.get() + write_position));
+ write_position += kWriteSize;
+ EXPECT_EQ(write_position, buffer_->forward_bytes());
+ }
+
+ // Read until the buffer is empty.
+ size_t read_position = 0;
+ while (buffer_->forward_bytes()) {
+ // Read a random amount of data.
+ size_t read_size = GetRandomInt(kBufferSize);
+ size_t forward_bytes = buffer_->forward_bytes();
+ size_t bytes_read = buffer_->Read(read_size, write_buffer_.get());
+ EXPECT_EQ(0, memcmp(write_buffer_.get(),
+ data_.get() + read_position,
+ bytes_read));
+ if (read_size > forward_bytes)
+ EXPECT_EQ(forward_bytes, bytes_read);
+ else
+ EXPECT_EQ(read_size, bytes_read);
+ read_position += bytes_read;
+ EXPECT_GE(write_position, read_position);
+ EXPECT_EQ(write_position - read_position, buffer_->forward_bytes());
+ }
+
+ // Expect we have no bytes left.
+ EXPECT_EQ(0u, buffer_->forward_bytes());
+ EXPECT_EQ(0u, buffer_->Read(1, write_buffer_.get()));
+}
+
+TEST_F(SeekableBufferTest, SeekBackward) {
+ EXPECT_EQ(0u, buffer_->forward_bytes());
+ EXPECT_EQ(0u, buffer_->backward_bytes());
+ EXPECT_FALSE(buffer_->Seek(1));
+ EXPECT_FALSE(buffer_->Seek(-1));
+
+ const size_t kWriteSize = 512;
+ const size_t kReadSize = 256;
+
+ // Write into buffer until it's full.
+ size_t write_position = 0;
+ for (size_t i = 0; i < kBufferSize / kWriteSize; ++i) {
+ // Write a random amount of data.
+ buffer_->Append(kWriteSize, data_.get() + write_position);
+ write_position += kWriteSize;
+ }
+
+ // Read until buffer is empty.
+ size_t read_position = 0;
+ for (size_t i = 0; i < kBufferSize / kReadSize; ++i) {
+ EXPECT_EQ(kReadSize, buffer_->Read(kReadSize, write_buffer_.get()));
+ EXPECT_EQ(0, memcmp(write_buffer_.get(),
+ data_.get() + read_position,
+ kReadSize));
+ read_position += kReadSize;
+ }
+
+ // Seek backward.
+ EXPECT_TRUE(buffer_->Seek(-static_cast<int32>(kBufferSize)));
+ EXPECT_FALSE(buffer_->Seek(-1));
+
+ // Read again.
+ read_position = 0;
+ for (size_t i = 0; i < kBufferSize / kReadSize; ++i) {
+ EXPECT_EQ(kReadSize, buffer_->Read(kReadSize, write_buffer_.get()));
+ EXPECT_EQ(0, memcmp(write_buffer_.get(),
+ data_.get() + read_position,
+ kReadSize));
+ read_position += kReadSize;
+ }
+}
+
+TEST_F(SeekableBufferTest, SeekForward) {
+ size_t write_position = 0;
+ size_t read_position = 0;
+ while (read_position < kDataSize) {
+ for (int i = 0; i < 10; ++i) {
+ // Write a random amount of data.
+ size_t write_size = GetRandomInt(kBufferSize);
+ write_size = std::min(write_size, kDataSize - write_position);
+ if (!write_size)
+ break;
+ bool should_append =
+ buffer_->Append(write_size, data_.get() + write_position);
+ write_position += write_size;
+ EXPECT_GE(write_position, read_position);
+ EXPECT_EQ(write_position - read_position, buffer_->forward_bytes());
+ EXPECT_EQ(should_append, buffer_->forward_bytes() < kBufferSize)
+ << "Incorrect buffer full status reported";
+ }
+
+ // Read a random amount of data.
+ size_t seek_size = GetRandomInt(kBufferSize);
+ if (buffer_->Seek(seek_size))
+ read_position += seek_size;
+ EXPECT_GE(write_position, read_position);
+ EXPECT_EQ(write_position - read_position, buffer_->forward_bytes());
+
+ // Read a random amount of data.
+ size_t read_size = GetRandomInt(kBufferSize);
+ size_t bytes_read = buffer_->Read(read_size, write_buffer_.get());
+ EXPECT_GE(read_size, bytes_read);
+ EXPECT_EQ(0, memcmp(write_buffer_.get(),
+ data_.get() + read_position,
+ bytes_read));
+ read_position += bytes_read;
+ EXPECT_GE(write_position, read_position);
+ EXPECT_EQ(write_position - read_position, buffer_->forward_bytes());
+ }
+}
+
+TEST_F(SeekableBufferTest, AllMethods) {
+ EXPECT_EQ(0u, buffer_->Read(0, write_buffer_.get()));
+ EXPECT_EQ(0u, buffer_->Read(1, write_buffer_.get()));
+ EXPECT_TRUE(buffer_->Seek(0));
+ EXPECT_FALSE(buffer_->Seek(-1));
+ EXPECT_FALSE(buffer_->Seek(1));
+ EXPECT_EQ(0u, buffer_->forward_bytes());
+ EXPECT_EQ(0u, buffer_->backward_bytes());
+}
+
+}