Chromium Code Reviews| 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..a92cd919341287f2d6e6aae19885da480439ed54 |
| --- /dev/null |
| +++ b/remoting/base/compound_buffer_unittest.cc |
| @@ -0,0 +1,247 @@ |
| +// 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 CopyAndAppend(int pos, int size) { |
| + target_.CopyAndAppend(data_->data() + pos, size); |
| + } |
| + |
| + void Prepend(int pos, int size) { |
| + target_.Prepend(data_, data_->data() + (kDataSize - pos - size), size); |
| + } |
| + |
| + void CopyAndPrepend(int pos, int size) { |
| + target_.CopyAndPrepend(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.Assemble(); |
| + return buffer.total_bytes() == size && |
| + memcmp(buffer_data->data(), data, size) == 0; |
| + } |
| + |
| + static size_t ReadFromInput(CompoundBuffer* 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(CompoundBuffer* 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 |output_stream|. |
| + static void PrepareData(scoped_ptr<CompoundBuffer>* stream) { |
| + 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* mstream = new CompoundBuffer(); |
| + const char* data = kTestData.data(); |
| + for (int i = 0; i < segments; ++i) { |
| + int size = i % 2 == 0 ? 1 : 2; |
| + mstream->Append(new net::WrappedIOBuffer(data), size); |
| + data += size; |
| + } |
| + stream->reset(mstream); |
| + } |
| + |
| + 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, CopyAndAppend) { |
| + target_.Clear(); |
| + IterateOverPieces(kChunkSizes0, NewCallback( |
| + static_cast<CompoundBufferTest*>(this), |
| + &CompoundBufferTest::CopyAndAppend)); |
| + EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize)); |
| + |
| + target_.Clear(); |
| + IterateOverPieces(kChunkSizes1, NewCallback( |
| + static_cast<CompoundBufferTest*>(this), |
| + &CompoundBufferTest::CopyAndAppend)); |
| + 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, CopyAndPrepend) { |
| + target_.Clear(); |
| + IterateOverPieces(kChunkSizes0, NewCallback( |
| + static_cast<CompoundBufferTest*>(this), |
| + &CompoundBufferTest::CopyAndPrepend)); |
| + EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize)); |
| + |
| + target_.Clear(); |
| + IterateOverPieces(kChunkSizes1, NewCallback( |
| + static_cast<CompoundBufferTest*>(this), |
| + &CompoundBufferTest::CopyAndPrepend)); |
| + 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)); |
| + } |
| +} |
|
awong
2010/11/12 02:40:06
We should also test the interactions between the Z
Sergey Ulanov
2010/11/13 04:43:39
Not needed anymore, as I separated CompoundBuffer
|
| + |
| +TEST_F(CompoundBufferTest, InputStream) { |
| + scoped_ptr<CompoundBuffer> stream; |
| + PrepareData(&stream); |
| + |
| + ReadString(stream.get(), "Hello world!"); |
| + ReadString(stream.get(), "This "); |
| + ReadString(stream.get(), "is test"); |
| + EXPECT_TRUE(stream->Skip(3)); |
| + ReadString(stream.get(), "MultipleArrayInput"); |
| + EXPECT_TRUE(stream->Skip(6)); |
| + ReadString(stream.get(), "f"); |
| + ReadString(stream.get(), "o"); |
| + ReadString(stream.get(), "r"); |
| + ReadString(stream.get(), " "); |
| + ReadString(stream.get(), "Chromoting"); |
| +} |
| + |
| +} // namespace remoting |