 Chromium Code Reviews
 Chromium Code Reviews Issue 4779001:
  Added CompoundBuffer that will be used to store data in the encoding/decoding  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src
    
  
    Issue 4779001:
  Added CompoundBuffer that will be used to store data in the encoding/decoding  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src| 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 |