1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
32
33 #include <algorithm>
34 #include <cstdlib>
35 #include <memory>
36 #include "base/memory/scoped_refptr.h"
37 #include "testing/gtest/include/gtest/gtest.h"
38 #include "third_party/blink/renderer/platform/wtf/vector.h"
39
40 namespace blink {
41
TEST(SharedBufferTest,getAsBytes)42 TEST(SharedBufferTest, getAsBytes) {
43 char test_data0[] = "Hello";
44 char test_data1[] = "World";
45 char test_data2[] = "Goodbye";
46
47 scoped_refptr<SharedBuffer> shared_buffer =
48 SharedBuffer::Create(test_data0, strlen(test_data0));
49 shared_buffer->Append(test_data1, strlen(test_data1));
50 shared_buffer->Append(test_data2, strlen(test_data2));
51
52 const size_t size = shared_buffer->size();
53 auto data = std::make_unique<char[]>(size);
54 ASSERT_TRUE(shared_buffer->GetBytes(data.get(), size));
55
56 char expected_concatenation[] = "HelloWorldGoodbye";
57 ASSERT_EQ(strlen(expected_concatenation), size);
58 EXPECT_EQ(0, memcmp(expected_concatenation, data.get(),
59 strlen(expected_concatenation)));
60 }
61
TEST(SharedBufferTest,getPartAsBytes)62 TEST(SharedBufferTest, getPartAsBytes) {
63 char test_data0[] = "Hello";
64 char test_data1[] = "World";
65 char test_data2[] = "Goodbye";
66
67 scoped_refptr<SharedBuffer> shared_buffer =
68 SharedBuffer::Create(test_data0, strlen(test_data0));
69 shared_buffer->Append(test_data1, strlen(test_data1));
70 shared_buffer->Append(test_data2, strlen(test_data2));
71
72 struct TestData {
73 size_t size;
74 const char* expected;
75 } test_data[] = {
76 {17, "HelloWorldGoodbye"}, {7, "HelloWo"}, {3, "Hel"},
77 };
78 for (TestData& test : test_data) {
79 auto data = std::make_unique<char[]>(test.size);
80 ASSERT_TRUE(shared_buffer->GetBytes(data.get(), test.size));
81 EXPECT_EQ(0, memcmp(test.expected, data.get(), test.size));
82 }
83 }
84
TEST(SharedBufferTest,getAsBytesLargeSegments)85 TEST(SharedBufferTest, getAsBytesLargeSegments) {
86 Vector<char> vector0(0x4000);
87 for (size_t i = 0; i < vector0.size(); ++i)
88 vector0[i] = 'a';
89 Vector<char> vector1(0x4000);
90 for (size_t i = 0; i < vector1.size(); ++i)
91 vector1[i] = 'b';
92 Vector<char> vector2(0x4000);
93 for (size_t i = 0; i < vector2.size(); ++i)
94 vector2[i] = 'c';
95
96 scoped_refptr<SharedBuffer> shared_buffer =
97 SharedBuffer::AdoptVector(vector0);
98 shared_buffer->Append(vector1);
99 shared_buffer->Append(vector2);
100
101 const size_t size = shared_buffer->size();
102 auto data = std::make_unique<char[]>(size);
103 ASSERT_TRUE(shared_buffer->GetBytes(data.get(), size));
104
105 ASSERT_EQ(0x4000U + 0x4000U + 0x4000U, size);
106 int position = 0;
107 for (int i = 0; i < 0x4000; ++i) {
108 EXPECT_EQ('a', data[position]);
109 ++position;
110 }
111 for (int i = 0; i < 0x4000; ++i) {
112 EXPECT_EQ('b', data[position]);
113 ++position;
114 }
115 for (int i = 0; i < 0x4000; ++i) {
116 EXPECT_EQ('c', data[position]);
117 ++position;
118 }
119 }
120
TEST(SharedBufferTest,copy)121 TEST(SharedBufferTest, copy) {
122 Vector<char> test_data(10000);
123 std::generate(test_data.begin(), test_data.end(), &std::rand);
124
125 size_t length = test_data.size();
126 scoped_refptr<SharedBuffer> shared_buffer =
127 SharedBuffer::Create(test_data.data(), length);
128 shared_buffer->Append(test_data.data(), length);
129 shared_buffer->Append(test_data.data(), length);
130 shared_buffer->Append(test_data.data(), length);
131 // sharedBuffer must contain data more than segmentSize (= 0x1000) to check
132 // copy().
133 ASSERT_EQ(length * 4, shared_buffer->size());
134
135 Vector<char> clone = shared_buffer->CopyAs<Vector<char>>();
136 ASSERT_EQ(length * 4, clone.size());
137 const Vector<char> contiguous = shared_buffer->CopyAs<Vector<char>>();
138 ASSERT_EQ(contiguous.size(), shared_buffer->size());
139 ASSERT_EQ(0, memcmp(clone.data(), contiguous.data(), clone.size()));
140
141 clone.Append(test_data.data(), length);
142 ASSERT_EQ(length * 5, clone.size());
143 }
144
TEST(SharedBufferTest,constructorWithSizeOnly)145 TEST(SharedBufferTest, constructorWithSizeOnly) {
146 size_t length = 10000;
147 scoped_refptr<SharedBuffer> shared_buffer = SharedBuffer::Create(length);
148 ASSERT_EQ(length, shared_buffer->size());
149
150 // The internal flat buffer should have been resized to |length| therefore
151 // the buffer consists of one big buffer.
152 const auto it = shared_buffer->cbegin();
153 ASSERT_NE(it, shared_buffer->cend());
154 ASSERT_EQ(length, it->size());
155 }
156
TEST(SharedBufferTest,constructorWithFlatData)157 TEST(SharedBufferTest, constructorWithFlatData) {
158 Vector<char> data;
159
160 while (data.size() < 10000ul) {
161 data.Append("FooBarBaz", 9ul);
162 auto shared_buffer = SharedBuffer::Create(data.begin(), data.size());
163
164 Vector<Vector<char>> segments;
165 for (const auto& span : *shared_buffer) {
166 segments.emplace_back();
167 segments.back().Append(span.data(), span.size());
168 }
169
170 // Shared buffers constructed from flat data should stay flat.
171 ASSERT_EQ(segments.size(), 1ul);
172 ASSERT_EQ(segments.front().size(), data.size());
173 EXPECT_EQ(memcmp(segments.front().begin(), data.begin(), data.size()), 0);
174 }
175 }
176
TEST(SharedBufferTest,FlatData)177 TEST(SharedBufferTest, FlatData) {
178 auto check_flat_data = [](scoped_refptr<const SharedBuffer> shared_buffer) {
179 const SharedBuffer::DeprecatedFlatData flat_buffer(shared_buffer);
180
181 EXPECT_EQ(shared_buffer->size(), flat_buffer.size());
182 size_t offset = 0;
183 for (const auto& span : *shared_buffer) {
184 EXPECT_EQ(memcmp(span.data(), flat_buffer.Data() + offset, span.size()),
185 0);
186 offset += span.size();
187
188 // If the SharedBuffer is not segmented, FlatData doesn't copy any data.
189 EXPECT_EQ(span.size() == flat_buffer.size(),
190 span.data() == flat_buffer.Data());
191 }
192 };
193
194 scoped_refptr<SharedBuffer> shared_buffer = SharedBuffer::Create();
195
196 // Add enough data to hit a couple of segments.
197 while (shared_buffer->size() < 10000) {
198 check_flat_data(shared_buffer);
199 shared_buffer->Append("FooBarBaz", 9u);
200 }
201 }
202
TEST(SharedBufferTest,GetIteratorAt)203 TEST(SharedBufferTest, GetIteratorAt) {
204 Vector<char> data(SharedBuffer::kSegmentSize + 256);
205 std::generate(data.begin(), data.end(), &std::rand);
206 auto buffer = SharedBuffer::Create();
207 buffer->Append(data.data(), static_cast<size_t>(127));
208 buffer->Append(data.data() + 127, data.size() - 127);
209
210 const auto it0 = buffer->GetIteratorAt(static_cast<size_t>(0));
211 EXPECT_EQ(it0, buffer->cbegin());
212 ASSERT_NE(it0, buffer->cend());
213 ASSERT_EQ(it0->size(), 127u);
214 EXPECT_EQ(0, memcmp(it0->data(), data.data(), it0->size()));
215
216 const auto it1 = buffer->GetIteratorAt(static_cast<size_t>(1));
217 EXPECT_NE(it1, buffer->cbegin());
218 ASSERT_NE(it1, buffer->cend());
219 ASSERT_EQ(it1->size(), 126u);
220 EXPECT_EQ(0, memcmp(it1->data(), data.data() + 1, it1->size()));
221
222 const auto it126 = buffer->GetIteratorAt(static_cast<size_t>(126));
223 EXPECT_NE(it126, buffer->cbegin());
224 ASSERT_NE(it126, buffer->cend());
225 ASSERT_EQ(it126->size(), 1u);
226 EXPECT_EQ(0, memcmp(it126->data(), data.data() + 126, it126->size()));
227
228 const auto it127 = buffer->GetIteratorAt(static_cast<size_t>(127));
229 EXPECT_NE(it127, buffer->cbegin());
230 ASSERT_NE(it127, buffer->cend());
231 ASSERT_EQ(it127->size(), SharedBuffer::kSegmentSize);
232 EXPECT_EQ(0, memcmp(it127->data(), data.data() + 127, it127->size()));
233
234 const auto it128 = buffer->GetIteratorAt(static_cast<size_t>(128));
235 EXPECT_NE(it128, buffer->cbegin());
236 ASSERT_NE(it128, buffer->cend());
237 ASSERT_EQ(it128->size(), SharedBuffer::kSegmentSize - 1);
238 EXPECT_EQ(0, memcmp(it128->data(), data.data() + 128, it128->size()));
239
240 const auto it4222 = buffer->GetIteratorAt(static_cast<size_t>(4222));
241 EXPECT_NE(it4222, buffer->cbegin());
242 ASSERT_NE(it4222, buffer->cend());
243 ASSERT_EQ(it4222->size(), 1u);
244 EXPECT_EQ(0, memcmp(it4222->data(), data.data() + 4222, it4222->size()));
245
246 const auto it4223 = buffer->GetIteratorAt(static_cast<size_t>(4223));
247 EXPECT_NE(it4223, buffer->cbegin());
248 ASSERT_NE(it4223, buffer->cend());
249 ASSERT_EQ(it4223->size(), 129u);
250 EXPECT_EQ(0, memcmp(it4223->data(), data.data() + 4223, it4223->size()));
251
252 const auto it4224 = buffer->GetIteratorAt(static_cast<size_t>(4224));
253 EXPECT_NE(it4224, buffer->cbegin());
254 ASSERT_NE(it4224, buffer->cend());
255 ASSERT_EQ(it4224->size(), 128u);
256 EXPECT_EQ(0, memcmp(it4224->data(), data.data() + 4224, it4224->size()));
257
258 const auto it4351 = buffer->GetIteratorAt(static_cast<size_t>(4351));
259 EXPECT_NE(it4351, buffer->cbegin());
260 ASSERT_NE(it4351, buffer->cend());
261 ASSERT_EQ(it4351->size(), 1u);
262 EXPECT_EQ(0, memcmp(it4351->data(), data.data() + 4351, it4351->size()));
263
264 // All of the iterators above are different each other.
265 const SharedBuffer::Iterator iters[] = {
266 it0, it1, it126, it127, it128, it4222, it4223, it4224, it4351,
267 };
268 for (size_t i = 0; i < base::size(iters); ++i) {
269 for (size_t j = 0; j < base::size(iters); ++j) {
270 EXPECT_EQ(i == j, iters[i] == iters[j]);
271 }
272 }
273
274 auto it = it0;
275 ++it;
276 EXPECT_EQ(it, it127);
277
278 it = it1;
279 ++it;
280 EXPECT_EQ(it, it127);
281
282 it = it126;
283 ++it;
284 EXPECT_EQ(it, it127);
285
286 it = it127;
287 ++it;
288 EXPECT_EQ(it, it4223);
289
290 it = it4222;
291 ++it;
292 EXPECT_EQ(it, it4223);
293
294 it = it4223;
295 ++it;
296 EXPECT_EQ(it, buffer->cend());
297
298 it = it4224;
299 ++it;
300 EXPECT_EQ(it, buffer->cend());
301
302 const auto it4352 = buffer->GetIteratorAt(static_cast<size_t>(4352));
303 EXPECT_EQ(it4352, buffer->cend());
304
305 const auto it4353 = buffer->GetIteratorAt(static_cast<size_t>(4353));
306 EXPECT_EQ(it4353, buffer->cend());
307 }
308
TEST(SharedBufferIteratorTest,Empty)309 TEST(SharedBufferIteratorTest, Empty) {
310 auto buffer = SharedBuffer::Create();
311
312 EXPECT_EQ(buffer->begin(), buffer->end());
313 EXPECT_EQ(buffer->cbegin(), buffer->cend());
314 }
315
TEST(SharedBufferIteratorTest,ConsecutivePartOnly)316 TEST(SharedBufferIteratorTest, ConsecutivePartOnly) {
317 auto buffer = SharedBuffer::Create("hello", static_cast<size_t>(5));
318
319 EXPECT_EQ(buffer->begin(), buffer->cbegin());
320 EXPECT_EQ(buffer->end(), buffer->cend());
321
322 auto it = buffer->cbegin();
323 ASSERT_NE(it, buffer->cend());
324
325 EXPECT_EQ(String(it->data(), it->size()), "hello");
326
327 ++it;
328
329 EXPECT_EQ(it, buffer->cend());
330 }
331
TEST(SharedBufferIteratorTest,SegmentedPartOnly)332 TEST(SharedBufferIteratorTest, SegmentedPartOnly) {
333 Vector<char> data(SharedBuffer::kSegmentSize * 2 + 256);
334 std::generate(data.begin(), data.end(), &std::rand);
335 auto buffer = SharedBuffer::Create();
336 buffer->Append(data);
337
338 EXPECT_EQ(buffer->begin(), buffer->cbegin());
339 EXPECT_EQ(buffer->end(), buffer->cend());
340
341 auto it = buffer->cbegin();
342 ASSERT_NE(it, buffer->cend());
343
344 ASSERT_EQ(it->size(), SharedBuffer::kSegmentSize);
345 EXPECT_EQ(0, memcmp(data.data(), it->data(), it->size()));
346
347 ++it;
348 ASSERT_NE(it, buffer->cend());
349 ASSERT_EQ(it->size(), SharedBuffer::kSegmentSize);
350 EXPECT_EQ(0, memcmp(data.data() + SharedBuffer::kSegmentSize, it->data(),
351 it->size()));
352
353 ++it;
354 ASSERT_NE(it, buffer->cend());
355 ASSERT_EQ(it->size(), 256u);
356 EXPECT_EQ(0, memcmp(data.data() + 2 * SharedBuffer::kSegmentSize, it->data(),
357 it->size()));
358
359 ++it;
360 EXPECT_EQ(it, buffer->cend());
361 }
362
TEST(SharedBufferIteratorTest,ConsecutivePartAndSegmentedPart)363 TEST(SharedBufferIteratorTest, ConsecutivePartAndSegmentedPart) {
364 Vector<char> data(SharedBuffer::kSegmentSize * 2 + 256);
365 std::generate(data.begin(), data.end(), &std::rand);
366 auto buffer = SharedBuffer::Create();
367 buffer->Append(data.data(), static_cast<size_t>(128));
368 buffer->Append(data.data() + 128, data.size() - 128);
369
370 EXPECT_EQ(buffer->begin(), buffer->cbegin());
371 EXPECT_EQ(buffer->end(), buffer->cend());
372
373 auto it = buffer->cbegin();
374 ASSERT_NE(it, buffer->cend());
375
376 ASSERT_EQ(it->size(), 128u);
377 EXPECT_EQ(0, memcmp(data.data(), it->data(), it->size()));
378
379 ++it;
380 ASSERT_NE(it, buffer->cend());
381 ASSERT_EQ(it->size(), SharedBuffer::kSegmentSize);
382 EXPECT_EQ(0, memcmp(data.data() + 128, it->data(), it->size()));
383
384 ++it;
385 ASSERT_NE(it, buffer->cend());
386 ASSERT_EQ(it->size(), SharedBuffer::kSegmentSize);
387 EXPECT_EQ(0, memcmp(data.data() + 128 + SharedBuffer::kSegmentSize,
388 it->data(), it->size()));
389
390 ++it;
391 ASSERT_NE(it, buffer->cend());
392 ASSERT_EQ(it->size(), 128u);
393 EXPECT_EQ(0, memcmp(data.data() + 128 + 2 * SharedBuffer::kSegmentSize,
394 it->data(), it->size()));
395
396 ++it;
397 EXPECT_EQ(it, buffer->cend());
398 }
399
400 } // namespace blink
401