OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include <string> |
| 6 |
| 7 #include "base/callback.h" |
| 8 #include "base/scoped_ptr.h" |
| 9 #include "net/base/io_buffer.h" |
| 10 #include "remoting/base/compound_buffer.h" |
| 11 #include "testing/gtest/include/gtest/gtest.h" |
| 12 |
| 13 using net::IOBuffer; |
| 14 |
| 15 namespace remoting { |
| 16 |
| 17 namespace { |
| 18 const int kDataSize = 1024; |
| 19 |
| 20 // Chunk sizes used to append and prepend data to the buffer. |
| 21 const int kChunkSizes0[] = {kDataSize, -1}; |
| 22 const int kChunkSizes1[] = {1, 10, 20, -1}; |
| 23 |
| 24 // Chunk sizes used to test CopyFrom(). |
| 25 const int kCopySizes0[] = {10, 3, -1}; |
| 26 const int kCopySizes1[] = {20, -1}; |
| 27 } // namespace |
| 28 |
| 29 class CompoundBufferTest : public testing::Test { |
| 30 public: |
| 31 |
| 32 // Following 5 methods are used with IterateOverPieces(). |
| 33 void Append(int pos, int size) { |
| 34 target_.Append(data_, data_->data() + pos, size); |
| 35 } |
| 36 |
| 37 void AppendCopyOf(int pos, int size) { |
| 38 target_.AppendCopyOf(data_->data() + pos, size); |
| 39 } |
| 40 |
| 41 void Prepend(int pos, int size) { |
| 42 target_.Prepend(data_, data_->data() + kDataSize - pos - size, size); |
| 43 } |
| 44 |
| 45 void PrependCopyOf(int pos, int size) { |
| 46 target_.PrependCopyOf(data_->data() + (kDataSize - pos - size), size); |
| 47 } |
| 48 |
| 49 void TestCopyFrom(int pos, int size) { |
| 50 CompoundBuffer copy; |
| 51 copy.CopyFrom(target_, pos, pos + size); |
| 52 EXPECT_TRUE(CompareData(copy, data_->data() + pos, size)); |
| 53 } |
| 54 |
| 55 protected: |
| 56 virtual void SetUp() { |
| 57 data_ = new IOBuffer(kDataSize); |
| 58 for (int i = 0; i < kDataSize; ++i) { |
| 59 data_->data()[i] = i; |
| 60 } |
| 61 } |
| 62 |
| 63 // Iterate over chunks of data with sizes specified in |sizes| in the |
| 64 // interval [0..kDataSize]. |function| is called for each chunk. |
| 65 void IterateOverPieces(const int sizes[], |
| 66 Callback2<int, int>::Type* function) { |
| 67 DCHECK_GT(sizes[0], 0); |
| 68 |
| 69 int pos = 0; |
| 70 int index = 0; |
| 71 while (pos < kDataSize) { |
| 72 int size = std::min(sizes[index], kDataSize - pos); |
| 73 ++index; |
| 74 if (sizes[index] <= 0) |
| 75 index = 0; |
| 76 |
| 77 function->Run(pos, size); |
| 78 |
| 79 pos += size; |
| 80 } |
| 81 delete function; |
| 82 } |
| 83 |
| 84 bool CompareData(const CompoundBuffer& buffer, char* data, int size) { |
| 85 scoped_refptr<IOBuffer> buffer_data = buffer.ToIOBufferWithSize(); |
| 86 return buffer.total_bytes() == size && |
| 87 memcmp(buffer_data->data(), data, size) == 0; |
| 88 } |
| 89 |
| 90 static size_t ReadFromInput(CompoundBufferInputStream* input, |
| 91 void* data, size_t size) { |
| 92 uint8* out = reinterpret_cast<uint8*>(data); |
| 93 int out_size = size; |
| 94 |
| 95 const void* in; |
| 96 int in_size = 0; |
| 97 |
| 98 while (true) { |
| 99 if (!input->Next(&in, &in_size)) { |
| 100 return size - out_size; |
| 101 } |
| 102 EXPECT_GT(in_size, -1); |
| 103 |
| 104 if (out_size <= in_size) { |
| 105 memcpy(out, in, out_size); |
| 106 if (in_size > out_size) { |
| 107 input->BackUp(in_size - out_size); |
| 108 } |
| 109 return size; // Copied all of it. |
| 110 } |
| 111 |
| 112 memcpy(out, in, in_size); |
| 113 out += in_size; |
| 114 out_size -= in_size; |
| 115 } |
| 116 } |
| 117 |
| 118 static void ReadString(CompoundBufferInputStream* input, |
| 119 const std::string& str) { |
| 120 SCOPED_TRACE(str); |
| 121 scoped_array<char> buffer(new char[str.size() + 1]); |
| 122 buffer[str.size()] = '\0'; |
| 123 EXPECT_EQ(ReadFromInput(input, buffer.get(), str.size()), str.size()); |
| 124 EXPECT_STREQ(str.data(), buffer.get()); |
| 125 } |
| 126 |
| 127 // Construct and prepare data in the |buffer|. |
| 128 static void PrepareData(scoped_ptr<CompoundBuffer>* buffer) { |
| 129 static const std::string kTestData = |
| 130 "Hello world!" |
| 131 "This is testing" |
| 132 "MultipleArrayInputStream" |
| 133 "for Chromoting"; |
| 134 |
| 135 // Determine how many segments to split kTestData. We split the data in |
| 136 // 1 character, 2 characters, 1 character, 2 characters ... |
| 137 int segments = (kTestData.length() / 3) * 2; |
| 138 int remaining_chars = kTestData.length() % 3; |
| 139 if (remaining_chars) { |
| 140 if (remaining_chars == 1) |
| 141 ++segments; |
| 142 else |
| 143 segments += 2; |
| 144 } |
| 145 |
| 146 CompoundBuffer* result = new CompoundBuffer(); |
| 147 const char* data = kTestData.data(); |
| 148 for (int i = 0; i < segments; ++i) { |
| 149 int size = i % 2 == 0 ? 1 : 2; |
| 150 result->Append(new net::WrappedIOBuffer(data), size); |
| 151 data += size; |
| 152 } |
| 153 result->Lock(); |
| 154 buffer->reset(result); |
| 155 } |
| 156 |
| 157 CompoundBuffer target_; |
| 158 scoped_refptr<IOBuffer> data_; |
| 159 }; |
| 160 |
| 161 TEST_F(CompoundBufferTest, Append) { |
| 162 target_.Clear(); |
| 163 IterateOverPieces(kChunkSizes0, NewCallback( |
| 164 static_cast<CompoundBufferTest*>(this), &CompoundBufferTest::Append)); |
| 165 EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize)); |
| 166 |
| 167 target_.Clear(); |
| 168 IterateOverPieces(kChunkSizes1, NewCallback( |
| 169 static_cast<CompoundBufferTest*>(this), &CompoundBufferTest::Append)); |
| 170 EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize)); |
| 171 } |
| 172 |
| 173 TEST_F(CompoundBufferTest, AppendCopyOf) { |
| 174 target_.Clear(); |
| 175 IterateOverPieces(kChunkSizes0, NewCallback( |
| 176 static_cast<CompoundBufferTest*>(this), |
| 177 &CompoundBufferTest::AppendCopyOf)); |
| 178 EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize)); |
| 179 |
| 180 target_.Clear(); |
| 181 IterateOverPieces(kChunkSizes1, NewCallback( |
| 182 static_cast<CompoundBufferTest*>(this), |
| 183 &CompoundBufferTest::AppendCopyOf)); |
| 184 EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize)); |
| 185 } |
| 186 |
| 187 TEST_F(CompoundBufferTest, Prepend) { |
| 188 target_.Clear(); |
| 189 IterateOverPieces(kChunkSizes0, NewCallback( |
| 190 static_cast<CompoundBufferTest*>(this), &CompoundBufferTest::Prepend)); |
| 191 EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize)); |
| 192 |
| 193 target_.Clear(); |
| 194 IterateOverPieces(kChunkSizes1, NewCallback( |
| 195 static_cast<CompoundBufferTest*>(this), &CompoundBufferTest::Prepend)); |
| 196 EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize)); |
| 197 } |
| 198 |
| 199 TEST_F(CompoundBufferTest, PrependCopyOf) { |
| 200 target_.Clear(); |
| 201 IterateOverPieces(kChunkSizes0, NewCallback( |
| 202 static_cast<CompoundBufferTest*>(this), |
| 203 &CompoundBufferTest::PrependCopyOf)); |
| 204 EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize)); |
| 205 |
| 206 target_.Clear(); |
| 207 IterateOverPieces(kChunkSizes1, NewCallback( |
| 208 static_cast<CompoundBufferTest*>(this), |
| 209 &CompoundBufferTest::PrependCopyOf)); |
| 210 EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize)); |
| 211 } |
| 212 |
| 213 TEST_F(CompoundBufferTest, CopyFrom) { |
| 214 target_.Clear(); |
| 215 IterateOverPieces(kChunkSizes1, NewCallback( |
| 216 static_cast<CompoundBufferTest*>(this), &CompoundBufferTest::Append)); |
| 217 { |
| 218 SCOPED_TRACE("CopyFrom.kCopySizes0"); |
| 219 IterateOverPieces(kCopySizes0, NewCallback( |
| 220 static_cast<CompoundBufferTest*>(this), |
| 221 &CompoundBufferTest::TestCopyFrom)); |
| 222 } |
| 223 { |
| 224 SCOPED_TRACE("CopyFrom.kCopySizes1"); |
| 225 IterateOverPieces(kCopySizes1, NewCallback( |
| 226 static_cast<CompoundBufferTest*>(this), |
| 227 &CompoundBufferTest::TestCopyFrom)); |
| 228 } |
| 229 } |
| 230 |
| 231 TEST_F(CompoundBufferTest, InputStream) { |
| 232 scoped_ptr<CompoundBuffer> buffer; |
| 233 PrepareData(&buffer); |
| 234 CompoundBufferInputStream stream(buffer.get()); |
| 235 |
| 236 ReadString(&stream, "Hello world!"); |
| 237 ReadString(&stream, "This "); |
| 238 ReadString(&stream, "is test"); |
| 239 EXPECT_TRUE(stream.Skip(3)); |
| 240 ReadString(&stream, "MultipleArrayInput"); |
| 241 EXPECT_TRUE(stream.Skip(6)); |
| 242 ReadString(&stream, "f"); |
| 243 ReadString(&stream, "o"); |
| 244 ReadString(&stream, "r"); |
| 245 ReadString(&stream, " "); |
| 246 ReadString(&stream, "Chromoting"); |
| 247 } |
| 248 |
| 249 } // namespace remoting |
OLD | NEW |