1 // Copyright (c) 2011 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.
8 #include "base/callback.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "net/base/io_buffer.h"
11 #include "remoting/base/compound_buffer.h"
12 #include "testing/gtest/include/gtest/gtest.h"
19 const int kDataSize
= 1024;
21 // Chunk sizes used to append and prepend data to the buffer.
22 const int kChunkSizes0
[] = {kDataSize
, -1};
23 const int kChunkSizes1
[] = {1, 10, 20, -1};
25 // Chunk sizes used to test CopyFrom().
26 const int kCopySizes0
[] = {10, 3, -1};
27 const int kCopySizes1
[] = {20, -1};
29 const int kCropSizes
[] = {1, -1};
33 class CompoundBufferTest
: public testing::Test
{
36 // Following 5 methods are used with IterateOverPieces().
37 void Append(int pos
, int size
) {
38 target_
.Append(data_
.get(), data_
->data() + pos
, size
);
41 void AppendCopyOf(int pos
, int size
) {
42 target_
.AppendCopyOf(data_
->data() + pos
, size
);
45 void Prepend(int pos
, int size
) {
46 target_
.Prepend(data_
.get(), data_
->data() + kDataSize
- pos
- size
, size
);
49 void PrependCopyOf(int pos
, int size
) {
50 target_
.PrependCopyOf(data_
->data() + (kDataSize
- pos
- size
), size
);
53 void TestCopyFrom(int pos
, int size
) {
55 copy
.CopyFrom(target_
, pos
, pos
+ size
);
56 EXPECT_TRUE(CompareData(copy
, data_
->data() + pos
, size
));
59 void TestCropFront(int pos
, int size
) {
60 CompoundBuffer cropped
;
61 cropped
.CopyFrom(target_
, 0, target_
.total_bytes());
62 cropped
.CropFront(pos
);
63 EXPECT_TRUE(CompareData(cropped
, data_
->data() + pos
,
64 target_
.total_bytes() - pos
));
67 void TestCropBack(int pos
, int size
) {
68 CompoundBuffer cropped
;
69 cropped
.CopyFrom(target_
, 0, target_
.total_bytes());
70 cropped
.CropBack(pos
);
71 EXPECT_TRUE(CompareData(cropped
, data_
->data(),
72 target_
.total_bytes() - pos
));
76 virtual void SetUp() {
77 data_
= new IOBuffer(kDataSize
);
78 for (int i
= 0; i
< kDataSize
; ++i
) {
83 // Iterate over chunks of data with sizes specified in |sizes| in the
84 // interval [0..kDataSize]. |function| is called for each chunk.
85 void IterateOverPieces(const int sizes
[],
86 const base::Callback
<void(int, int)>& function
) {
87 DCHECK_GT(sizes
[0], 0);
91 while (pos
< kDataSize
) {
92 int size
= std::min(sizes
[index
], kDataSize
- pos
);
94 if (sizes
[index
] <= 0)
97 function
.Run(pos
, size
);
103 bool CompareData(const CompoundBuffer
& buffer
, char* data
, int size
) {
104 scoped_refptr
<IOBuffer
> buffer_data
= buffer
.ToIOBufferWithSize();
105 return buffer
.total_bytes() == size
&&
106 memcmp(buffer_data
->data(), data
, size
) == 0;
109 static size_t ReadFromInput(CompoundBufferInputStream
* input
,
110 void* data
, size_t size
) {
111 uint8
* out
= reinterpret_cast<uint8
*>(data
);
118 if (!input
->Next(&in
, &in_size
)) {
119 return size
- out_size
;
121 EXPECT_GT(in_size
, -1);
123 if (out_size
<= in_size
) {
124 memcpy(out
, in
, out_size
);
125 if (in_size
> out_size
) {
126 input
->BackUp(in_size
- out_size
);
128 return size
; // Copied all of it.
131 memcpy(out
, in
, in_size
);
137 static void ReadString(CompoundBufferInputStream
* input
,
138 const std::string
& str
) {
140 scoped_ptr
<char[]> buffer(new char[str
.size() + 1]);
141 buffer
[str
.size()] = '\0';
142 EXPECT_EQ(ReadFromInput(input
, buffer
.get(), str
.size()), str
.size());
143 EXPECT_STREQ(str
.data(), buffer
.get());
146 // Construct and prepare data in the |buffer|.
147 static void PrepareData(scoped_ptr
<CompoundBuffer
>* buffer
) {
148 static const std::string kTestData
=
151 "MultipleArrayInputStream"
154 // Determine how many segments to split kTestData. We split the data in
155 // 1 character, 2 characters, 1 character, 2 characters ...
156 int segments
= (kTestData
.length() / 3) * 2;
157 int remaining_chars
= kTestData
.length() % 3;
158 if (remaining_chars
) {
159 if (remaining_chars
== 1)
165 CompoundBuffer
* result
= new CompoundBuffer();
166 const char* data
= kTestData
.data();
167 for (int i
= 0; i
< segments
; ++i
) {
168 int size
= i
% 2 == 0 ? 1 : 2;
169 result
->Append(new net::WrappedIOBuffer(data
), size
);
173 buffer
->reset(result
);
176 CompoundBuffer target_
;
177 scoped_refptr
<IOBuffer
> data_
;
180 TEST_F(CompoundBufferTest
, Append
) {
182 IterateOverPieces(kChunkSizes0
, base::Bind(
183 &CompoundBufferTest::Append
, base::Unretained(this)));
184 EXPECT_TRUE(CompareData(target_
, data_
->data(), kDataSize
));
187 IterateOverPieces(kChunkSizes1
, base::Bind(
188 &CompoundBufferTest::Append
, base::Unretained(this)));
189 EXPECT_TRUE(CompareData(target_
, data_
->data(), kDataSize
));
192 TEST_F(CompoundBufferTest
, AppendCopyOf
) {
194 IterateOverPieces(kChunkSizes0
, base::Bind(
195 &CompoundBufferTest::AppendCopyOf
, base::Unretained(this)));
196 EXPECT_TRUE(CompareData(target_
, data_
->data(), kDataSize
));
199 IterateOverPieces(kChunkSizes1
, base::Bind(
200 &CompoundBufferTest::AppendCopyOf
, base::Unretained(this)));
201 EXPECT_TRUE(CompareData(target_
, data_
->data(), kDataSize
));
204 TEST_F(CompoundBufferTest
, Prepend
) {
206 IterateOverPieces(kChunkSizes0
, base::Bind(
207 &CompoundBufferTest::Prepend
, base::Unretained(this)));
208 EXPECT_TRUE(CompareData(target_
, data_
->data(), kDataSize
));
211 IterateOverPieces(kChunkSizes1
, base::Bind(
212 &CompoundBufferTest::Prepend
, base::Unretained(this)));
213 EXPECT_TRUE(CompareData(target_
, data_
->data(), kDataSize
));
216 TEST_F(CompoundBufferTest
, PrependCopyOf
) {
218 IterateOverPieces(kChunkSizes0
, base::Bind(
219 &CompoundBufferTest::PrependCopyOf
, base::Unretained(this)));
220 EXPECT_TRUE(CompareData(target_
, data_
->data(), kDataSize
));
223 IterateOverPieces(kChunkSizes1
, base::Bind(
224 &CompoundBufferTest::PrependCopyOf
, base::Unretained(this)));
225 EXPECT_TRUE(CompareData(target_
, data_
->data(), kDataSize
));
228 TEST_F(CompoundBufferTest
, CropFront
) {
230 IterateOverPieces(kChunkSizes1
, base::Bind(
231 &CompoundBufferTest::Append
, base::Unretained(this)));
232 IterateOverPieces(kCropSizes
, base::Bind(
233 &CompoundBufferTest::TestCropFront
, base::Unretained(this)));
236 TEST_F(CompoundBufferTest
, CropBack
) {
238 IterateOverPieces(kChunkSizes1
, base::Bind(
239 &CompoundBufferTest::Append
, base::Unretained(this)));
240 IterateOverPieces(kCropSizes
, base::Bind(
241 &CompoundBufferTest::TestCropBack
, base::Unretained(this)));
244 TEST_F(CompoundBufferTest
, CopyFrom
) {
246 IterateOverPieces(kChunkSizes1
, base::Bind(
247 &CompoundBufferTest::Append
, base::Unretained(this)));
249 SCOPED_TRACE("CopyFrom.kCopySizes0");
250 IterateOverPieces(kCopySizes0
, base::Bind(
251 &CompoundBufferTest::TestCopyFrom
, base::Unretained(this)));
254 SCOPED_TRACE("CopyFrom.kCopySizes1");
255 IterateOverPieces(kCopySizes1
, base::Bind(
256 &CompoundBufferTest::TestCopyFrom
, base::Unretained(this)));
260 TEST_F(CompoundBufferTest
, InputStream
) {
261 scoped_ptr
<CompoundBuffer
> buffer
;
262 PrepareData(&buffer
);
263 CompoundBufferInputStream
stream(buffer
.get());
265 ReadString(&stream
, "Hello world!");
266 ReadString(&stream
, "This ");
267 ReadString(&stream
, "is test");
268 EXPECT_TRUE(stream
.Skip(3));
269 ReadString(&stream
, "MultipleArrayInput");
270 EXPECT_TRUE(stream
.Skip(6));
271 ReadString(&stream
, "f");
272 ReadString(&stream
, "o");
273 ReadString(&stream
, "r");
274 ReadString(&stream
, " ");
275 ReadString(&stream
, "Chromoting");
278 } // namespace remoting