- add sources.
[platform/framework/web/crosswalk.git] / src / remoting / base / compound_buffer_unittest.cc
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.
4
5 #include <string>
6
7 #include "base/bind.h"
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"
13
14 using net::IOBuffer;
15
16 namespace remoting {
17
18 namespace {
19 const int kDataSize = 1024;
20
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};
24
25 // Chunk sizes used to test CopyFrom().
26 const int kCopySizes0[] = {10, 3, -1};
27 const int kCopySizes1[] = {20, -1};
28
29 const int kCropSizes[] = {1, -1};
30
31 }  // namespace
32
33 class CompoundBufferTest : public testing::Test {
34  public:
35
36   // Following 5 methods are used with IterateOverPieces().
37   void Append(int pos, int size) {
38     target_.Append(data_.get(), data_->data() + pos, size);
39   }
40
41   void AppendCopyOf(int pos, int size) {
42     target_.AppendCopyOf(data_->data() + pos, size);
43   }
44
45   void Prepend(int pos, int size) {
46     target_.Prepend(data_.get(), data_->data() + kDataSize - pos - size, size);
47   }
48
49   void PrependCopyOf(int pos, int size) {
50     target_.PrependCopyOf(data_->data() + (kDataSize - pos - size), size);
51   }
52
53   void TestCopyFrom(int pos, int size) {
54     CompoundBuffer copy;
55     copy.CopyFrom(target_, pos, pos + size);
56     EXPECT_TRUE(CompareData(copy, data_->data() + pos, size));
57   }
58
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));
65   }
66
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));
73   }
74
75  protected:
76   virtual void SetUp() {
77     data_ = new IOBuffer(kDataSize);
78     for (int i = 0; i < kDataSize; ++i) {
79       data_->data()[i] = i;
80     }
81   }
82
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);
88
89     int pos = 0;
90     int index = 0;
91     while (pos < kDataSize) {
92       int size = std::min(sizes[index], kDataSize - pos);
93       ++index;
94       if (sizes[index] <= 0)
95         index = 0;
96
97       function.Run(pos, size);
98
99       pos += size;
100     }
101   }
102
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;
107   }
108
109   static size_t ReadFromInput(CompoundBufferInputStream* input,
110                               void* data, size_t size) {
111     uint8* out = reinterpret_cast<uint8*>(data);
112     int out_size = size;
113
114     const void* in;
115     int in_size = 0;
116
117     while (true) {
118       if (!input->Next(&in, &in_size)) {
119         return size - out_size;
120       }
121       EXPECT_GT(in_size, -1);
122
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);
127         }
128         return size;  // Copied all of it.
129       }
130
131       memcpy(out, in, in_size);
132       out += in_size;
133       out_size -= in_size;
134     }
135   }
136
137   static void ReadString(CompoundBufferInputStream* input,
138                          const std::string& str) {
139     SCOPED_TRACE(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());
144   }
145
146   // Construct and prepare data in the |buffer|.
147   static void PrepareData(scoped_ptr<CompoundBuffer>* buffer) {
148     static const std::string kTestData =
149         "Hello world!"
150         "This is testing"
151         "MultipleArrayInputStream"
152         "for Chromoting";
153
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)
160         ++segments;
161       else
162         segments += 2;
163     }
164
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);
170       data += size;
171     }
172     result->Lock();
173     buffer->reset(result);
174   }
175
176   CompoundBuffer target_;
177   scoped_refptr<IOBuffer> data_;
178 };
179
180 TEST_F(CompoundBufferTest, Append) {
181   target_.Clear();
182   IterateOverPieces(kChunkSizes0, base::Bind(
183       &CompoundBufferTest::Append, base::Unretained(this)));
184   EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize));
185
186   target_.Clear();
187   IterateOverPieces(kChunkSizes1, base::Bind(
188       &CompoundBufferTest::Append, base::Unretained(this)));
189   EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize));
190 }
191
192 TEST_F(CompoundBufferTest, AppendCopyOf) {
193   target_.Clear();
194   IterateOverPieces(kChunkSizes0, base::Bind(
195       &CompoundBufferTest::AppendCopyOf, base::Unretained(this)));
196   EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize));
197
198   target_.Clear();
199   IterateOverPieces(kChunkSizes1, base::Bind(
200       &CompoundBufferTest::AppendCopyOf, base::Unretained(this)));
201   EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize));
202 }
203
204 TEST_F(CompoundBufferTest, Prepend) {
205   target_.Clear();
206   IterateOverPieces(kChunkSizes0, base::Bind(
207       &CompoundBufferTest::Prepend, base::Unretained(this)));
208   EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize));
209
210   target_.Clear();
211   IterateOverPieces(kChunkSizes1, base::Bind(
212       &CompoundBufferTest::Prepend, base::Unretained(this)));
213   EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize));
214 }
215
216 TEST_F(CompoundBufferTest, PrependCopyOf) {
217   target_.Clear();
218   IterateOverPieces(kChunkSizes0, base::Bind(
219       &CompoundBufferTest::PrependCopyOf, base::Unretained(this)));
220   EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize));
221
222   target_.Clear();
223   IterateOverPieces(kChunkSizes1, base::Bind(
224       &CompoundBufferTest::PrependCopyOf, base::Unretained(this)));
225   EXPECT_TRUE(CompareData(target_, data_->data(), kDataSize));
226 }
227
228 TEST_F(CompoundBufferTest, CropFront) {
229   target_.Clear();
230   IterateOverPieces(kChunkSizes1, base::Bind(
231       &CompoundBufferTest::Append, base::Unretained(this)));
232   IterateOverPieces(kCropSizes, base::Bind(
233       &CompoundBufferTest::TestCropFront, base::Unretained(this)));
234 }
235
236 TEST_F(CompoundBufferTest, CropBack) {
237   target_.Clear();
238   IterateOverPieces(kChunkSizes1, base::Bind(
239       &CompoundBufferTest::Append, base::Unretained(this)));
240   IterateOverPieces(kCropSizes, base::Bind(
241       &CompoundBufferTest::TestCropBack, base::Unretained(this)));
242 }
243
244 TEST_F(CompoundBufferTest, CopyFrom) {
245   target_.Clear();
246   IterateOverPieces(kChunkSizes1, base::Bind(
247       &CompoundBufferTest::Append, base::Unretained(this)));
248   {
249     SCOPED_TRACE("CopyFrom.kCopySizes0");
250     IterateOverPieces(kCopySizes0, base::Bind(
251         &CompoundBufferTest::TestCopyFrom, base::Unretained(this)));
252   }
253   {
254     SCOPED_TRACE("CopyFrom.kCopySizes1");
255     IterateOverPieces(kCopySizes1, base::Bind(
256         &CompoundBufferTest::TestCopyFrom, base::Unretained(this)));
257   }
258 }
259
260 TEST_F(CompoundBufferTest, InputStream) {
261   scoped_ptr<CompoundBuffer> buffer;
262   PrepareData(&buffer);
263   CompoundBufferInputStream stream(buffer.get());
264
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");
276 }
277
278 }  // namespace remoting