root/remoting/base/compound_buffer_unittest.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. Append
  2. AppendCopyOf
  3. Prepend
  4. PrependCopyOf
  5. TestCopyFrom
  6. TestCropFront
  7. TestCropBack
  8. SetUp
  9. IterateOverPieces
  10. CompareData
  11. ReadFromInput
  12. ReadString
  13. PrepareData
  14. TEST_F
  15. TEST_F
  16. TEST_F
  17. TEST_F
  18. TEST_F
  19. TEST_F
  20. TEST_F
  21. TEST_F

// Copyright (c) 2011 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/bind.h"
#include "base/callback.h"
#include "base/memory/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};

const int kCropSizes[] = {1, -1};

}  // namespace

class CompoundBufferTest : public testing::Test {
 public:

  // Following 5 methods are used with IterateOverPieces().
  void Append(int pos, int size) {
    target_.Append(data_.get(), 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_.get(), 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));
  }

  void TestCropFront(int pos, int size) {
    CompoundBuffer cropped;
    cropped.CopyFrom(target_, 0, target_.total_bytes());
    cropped.CropFront(pos);
    EXPECT_TRUE(CompareData(cropped, data_->data() + pos,
                            target_.total_bytes() - pos));
  }

  void TestCropBack(int pos, int size) {
    CompoundBuffer cropped;
    cropped.CopyFrom(target_, 0, target_.total_bytes());
    cropped.CropBack(pos);
    EXPECT_TRUE(CompareData(cropped, data_->data(),
                            target_.total_bytes() - pos));
  }

 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[],
                         const base::Callback<void(int, int)>& 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;
    }
  }

  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_ptr<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, base::Bind(
      &CompoundBufferTest::Append, base::Unretained(this)));
  EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize));

  target_.Clear();
  IterateOverPieces(kChunkSizes1, base::Bind(
      &CompoundBufferTest::Append, base::Unretained(this)));
  EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize));
}

TEST_F(CompoundBufferTest, AppendCopyOf) {
  target_.Clear();
  IterateOverPieces(kChunkSizes0, base::Bind(
      &CompoundBufferTest::AppendCopyOf, base::Unretained(this)));
  EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize));

  target_.Clear();
  IterateOverPieces(kChunkSizes1, base::Bind(
      &CompoundBufferTest::AppendCopyOf, base::Unretained(this)));
  EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize));
}

TEST_F(CompoundBufferTest, Prepend) {
  target_.Clear();
  IterateOverPieces(kChunkSizes0, base::Bind(
      &CompoundBufferTest::Prepend, base::Unretained(this)));
  EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize));

  target_.Clear();
  IterateOverPieces(kChunkSizes1, base::Bind(
      &CompoundBufferTest::Prepend, base::Unretained(this)));
  EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize));
}

TEST_F(CompoundBufferTest, PrependCopyOf) {
  target_.Clear();
  IterateOverPieces(kChunkSizes0, base::Bind(
      &CompoundBufferTest::PrependCopyOf, base::Unretained(this)));
  EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize));

  target_.Clear();
  IterateOverPieces(kChunkSizes1, base::Bind(
      &CompoundBufferTest::PrependCopyOf, base::Unretained(this)));
  EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize));
}

TEST_F(CompoundBufferTest, CropFront) {
  target_.Clear();
  IterateOverPieces(kChunkSizes1, base::Bind(
      &CompoundBufferTest::Append, base::Unretained(this)));
  IterateOverPieces(kCropSizes, base::Bind(
      &CompoundBufferTest::TestCropFront, base::Unretained(this)));
}

TEST_F(CompoundBufferTest, CropBack) {
  target_.Clear();
  IterateOverPieces(kChunkSizes1, base::Bind(
      &CompoundBufferTest::Append, base::Unretained(this)));
  IterateOverPieces(kCropSizes, base::Bind(
      &CompoundBufferTest::TestCropBack, base::Unretained(this)));
}

TEST_F(CompoundBufferTest, CopyFrom) {
  target_.Clear();
  IterateOverPieces(kChunkSizes1, base::Bind(
      &CompoundBufferTest::Append, base::Unretained(this)));
  {
    SCOPED_TRACE("CopyFrom.kCopySizes0");
    IterateOverPieces(kCopySizes0, base::Bind(
        &CompoundBufferTest::TestCopyFrom, base::Unretained(this)));
  }
  {
    SCOPED_TRACE("CopyFrom.kCopySizes1");
    IterateOverPieces(kCopySizes1, base::Bind(
        &CompoundBufferTest::TestCopyFrom, base::Unretained(this)));
  }
}

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

/* [<][>][^][v][top][bottom][index][help] */