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