| Index: remoting/base/compound_buffer_unittest.cc
|
| diff --git a/remoting/base/compound_buffer_unittest.cc b/remoting/base/compound_buffer_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..63ede5a02e033ac96f0af543e79b84c04e2e2f05
|
| --- /dev/null
|
| +++ b/remoting/base/compound_buffer_unittest.cc
|
| @@ -0,0 +1,249 @@
|
| +// Copyright (c) 2010 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 <string>
|
| +
|
| +#include "base/callback.h"
|
| +#include "base/scoped_ptr.h"
|
| +#include "net/base/io_buffer.h"
|
| +#include "remoting/base/compound_buffer.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +using net::IOBuffer;
|
| +
|
| +namespace remoting {
|
| +
|
| +namespace {
|
| +const int kDataSize = 1024;
|
| +
|
| +// Chunk sizes used to append and prepend data to the buffer.
|
| +const int kChunkSizes0[] = {kDataSize, -1};
|
| +const int kChunkSizes1[] = {1, 10, 20, -1};
|
| +
|
| +// Chunk sizes used to test CopyFrom().
|
| +const int kCopySizes0[] = {10, 3, -1};
|
| +const int kCopySizes1[] = {20, -1};
|
| +} // namespace
|
| +
|
| +class CompoundBufferTest : public testing::Test {
|
| + public:
|
| +
|
| + // Following 5 methods are used with IterateOverPieces().
|
| + void Append(int pos, int size) {
|
| + target_.Append(data_, data_->data() + pos, size);
|
| + }
|
| +
|
| + void AppendCopyOf(int pos, int size) {
|
| + target_.AppendCopyOf(data_->data() + pos, size);
|
| + }
|
| +
|
| + void Prepend(int pos, int size) {
|
| + target_.Prepend(data_, data_->data() + kDataSize - pos - size, size);
|
| + }
|
| +
|
| + void PrependCopyOf(int pos, int size) {
|
| + target_.PrependCopyOf(data_->data() + (kDataSize - pos - size), size);
|
| + }
|
| +
|
| + void TestCopyFrom(int pos, int size) {
|
| + CompoundBuffer copy;
|
| + copy.CopyFrom(target_, pos, pos + size);
|
| + EXPECT_TRUE(CompareData(copy, data_->data() + pos, size));
|
| + }
|
| +
|
| + protected:
|
| + virtual void SetUp() {
|
| + data_ = new IOBuffer(kDataSize);
|
| + for (int i = 0; i < kDataSize; ++i) {
|
| + data_->data()[i] = i;
|
| + }
|
| + }
|
| +
|
| + // Iterate over chunks of data with sizes specified in |sizes| in the
|
| + // interval [0..kDataSize]. |function| is called for each chunk.
|
| + void IterateOverPieces(const int sizes[],
|
| + Callback2<int, int>::Type* function) {
|
| + DCHECK_GT(sizes[0], 0);
|
| +
|
| + int pos = 0;
|
| + int index = 0;
|
| + while (pos < kDataSize) {
|
| + int size = std::min(sizes[index], kDataSize - pos);
|
| + ++index;
|
| + if (sizes[index] <= 0)
|
| + index = 0;
|
| +
|
| + function->Run(pos, size);
|
| +
|
| + pos += size;
|
| + }
|
| + delete function;
|
| + }
|
| +
|
| + bool CompareData(const CompoundBuffer& buffer, char* data, int size) {
|
| + scoped_refptr<IOBuffer> buffer_data = buffer.ToIOBufferWithSize();
|
| + return buffer.total_bytes() == size &&
|
| + memcmp(buffer_data->data(), data, size) == 0;
|
| + }
|
| +
|
| + static size_t ReadFromInput(CompoundBufferInputStream* input,
|
| + void* data, size_t size) {
|
| + uint8* out = reinterpret_cast<uint8*>(data);
|
| + int out_size = size;
|
| +
|
| + const void* in;
|
| + int in_size = 0;
|
| +
|
| + while (true) {
|
| + if (!input->Next(&in, &in_size)) {
|
| + return size - out_size;
|
| + }
|
| + EXPECT_GT(in_size, -1);
|
| +
|
| + if (out_size <= in_size) {
|
| + memcpy(out, in, out_size);
|
| + if (in_size > out_size) {
|
| + input->BackUp(in_size - out_size);
|
| + }
|
| + return size; // Copied all of it.
|
| + }
|
| +
|
| + memcpy(out, in, in_size);
|
| + out += in_size;
|
| + out_size -= in_size;
|
| + }
|
| + }
|
| +
|
| + static void ReadString(CompoundBufferInputStream* input,
|
| + const std::string& str) {
|
| + SCOPED_TRACE(str);
|
| + scoped_array<char> buffer(new char[str.size() + 1]);
|
| + buffer[str.size()] = '\0';
|
| + EXPECT_EQ(ReadFromInput(input, buffer.get(), str.size()), str.size());
|
| + EXPECT_STREQ(str.data(), buffer.get());
|
| + }
|
| +
|
| + // Construct and prepare data in the |buffer|.
|
| + static void PrepareData(scoped_ptr<CompoundBuffer>* buffer) {
|
| + static const std::string kTestData =
|
| + "Hello world!"
|
| + "This is testing"
|
| + "MultipleArrayInputStream"
|
| + "for Chromoting";
|
| +
|
| + // Determine how many segments to split kTestData. We split the data in
|
| + // 1 character, 2 characters, 1 character, 2 characters ...
|
| + int segments = (kTestData.length() / 3) * 2;
|
| + int remaining_chars = kTestData.length() % 3;
|
| + if (remaining_chars) {
|
| + if (remaining_chars == 1)
|
| + ++segments;
|
| + else
|
| + segments += 2;
|
| + }
|
| +
|
| + CompoundBuffer* result = new CompoundBuffer();
|
| + const char* data = kTestData.data();
|
| + for (int i = 0; i < segments; ++i) {
|
| + int size = i % 2 == 0 ? 1 : 2;
|
| + result->Append(new net::WrappedIOBuffer(data), size);
|
| + data += size;
|
| + }
|
| + result->Lock();
|
| + buffer->reset(result);
|
| + }
|
| +
|
| + CompoundBuffer target_;
|
| + scoped_refptr<IOBuffer> data_;
|
| +};
|
| +
|
| +TEST_F(CompoundBufferTest, Append) {
|
| + target_.Clear();
|
| + IterateOverPieces(kChunkSizes0, NewCallback(
|
| + static_cast<CompoundBufferTest*>(this), &CompoundBufferTest::Append));
|
| + EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize));
|
| +
|
| + target_.Clear();
|
| + IterateOverPieces(kChunkSizes1, NewCallback(
|
| + static_cast<CompoundBufferTest*>(this), &CompoundBufferTest::Append));
|
| + EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize));
|
| +}
|
| +
|
| +TEST_F(CompoundBufferTest, AppendCopyOf) {
|
| + target_.Clear();
|
| + IterateOverPieces(kChunkSizes0, NewCallback(
|
| + static_cast<CompoundBufferTest*>(this),
|
| + &CompoundBufferTest::AppendCopyOf));
|
| + EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize));
|
| +
|
| + target_.Clear();
|
| + IterateOverPieces(kChunkSizes1, NewCallback(
|
| + static_cast<CompoundBufferTest*>(this),
|
| + &CompoundBufferTest::AppendCopyOf));
|
| + EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize));
|
| +}
|
| +
|
| +TEST_F(CompoundBufferTest, Prepend) {
|
| + target_.Clear();
|
| + IterateOverPieces(kChunkSizes0, NewCallback(
|
| + static_cast<CompoundBufferTest*>(this), &CompoundBufferTest::Prepend));
|
| + EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize));
|
| +
|
| + target_.Clear();
|
| + IterateOverPieces(kChunkSizes1, NewCallback(
|
| + static_cast<CompoundBufferTest*>(this), &CompoundBufferTest::Prepend));
|
| + EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize));
|
| +}
|
| +
|
| +TEST_F(CompoundBufferTest, PrependCopyOf) {
|
| + target_.Clear();
|
| + IterateOverPieces(kChunkSizes0, NewCallback(
|
| + static_cast<CompoundBufferTest*>(this),
|
| + &CompoundBufferTest::PrependCopyOf));
|
| + EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize));
|
| +
|
| + target_.Clear();
|
| + IterateOverPieces(kChunkSizes1, NewCallback(
|
| + static_cast<CompoundBufferTest*>(this),
|
| + &CompoundBufferTest::PrependCopyOf));
|
| + EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize));
|
| +}
|
| +
|
| +TEST_F(CompoundBufferTest, CopyFrom) {
|
| + target_.Clear();
|
| + IterateOverPieces(kChunkSizes1, NewCallback(
|
| + static_cast<CompoundBufferTest*>(this), &CompoundBufferTest::Append));
|
| + {
|
| + SCOPED_TRACE("CopyFrom.kCopySizes0");
|
| + IterateOverPieces(kCopySizes0, NewCallback(
|
| + static_cast<CompoundBufferTest*>(this),
|
| + &CompoundBufferTest::TestCopyFrom));
|
| + }
|
| + {
|
| + SCOPED_TRACE("CopyFrom.kCopySizes1");
|
| + IterateOverPieces(kCopySizes1, NewCallback(
|
| + static_cast<CompoundBufferTest*>(this),
|
| + &CompoundBufferTest::TestCopyFrom));
|
| + }
|
| +}
|
| +
|
| +TEST_F(CompoundBufferTest, InputStream) {
|
| + scoped_ptr<CompoundBuffer> buffer;
|
| + PrepareData(&buffer);
|
| + CompoundBufferInputStream stream(buffer.get());
|
| +
|
| + ReadString(&stream, "Hello world!");
|
| + ReadString(&stream, "This ");
|
| + ReadString(&stream, "is test");
|
| + EXPECT_TRUE(stream.Skip(3));
|
| + ReadString(&stream, "MultipleArrayInput");
|
| + EXPECT_TRUE(stream.Skip(6));
|
| + ReadString(&stream, "f");
|
| + ReadString(&stream, "o");
|
| + ReadString(&stream, "r");
|
| + ReadString(&stream, " ");
|
| + ReadString(&stream, "Chromoting");
|
| +}
|
| +
|
| +} // namespace remoting
|
|
|