blob: ad2c4e0fba3efab2da43531b64bd747e0ebe7bf3 [file] [log] [blame]
jbauch13041cf2016-02-25 06:16:52 -08001/*
2 * Copyright 2016 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Steve Anton10542f22019-01-11 09:11:00 -080011#include "rtc_base/copy_on_write_buffer.h"
Yves Gerey3e707812018-11-28 16:47:49 +010012
13#include <cstdint>
14
15#include "test/gtest.h"
jbauch13041cf2016-02-25 06:16:52 -080016
17namespace rtc {
18
19namespace {
20
21// clang-format off
22const uint8_t kTestData[] = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
23 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
24// clang-format on
25
26} // namespace
27
28void EnsureBuffersShareData(const CopyOnWriteBuffer& buf1,
29 const CopyOnWriteBuffer& buf2) {
30 // Data is shared between buffers.
31 EXPECT_EQ(buf1.size(), buf2.size());
32 EXPECT_EQ(buf1.capacity(), buf2.capacity());
33 const uint8_t* data1 = buf1.data();
34 const uint8_t* data2 = buf2.data();
35 EXPECT_EQ(data1, data2);
36 EXPECT_EQ(buf1, buf2);
37}
38
39void EnsureBuffersDontShareData(const CopyOnWriteBuffer& buf1,
40 const CopyOnWriteBuffer& buf2) {
41 // Data is not shared between buffers.
42 const uint8_t* data1 = buf1.cdata();
43 const uint8_t* data2 = buf2.cdata();
44 EXPECT_NE(data1, data2);
45}
46
jbaucheec21bd2016-03-20 06:15:43 -070047TEST(CopyOnWriteBufferTest, TestCreateEmptyData) {
48 CopyOnWriteBuffer buf(static_cast<const uint8_t*>(nullptr), 0);
49 EXPECT_EQ(buf.size(), 0u);
50 EXPECT_EQ(buf.capacity(), 0u);
51 EXPECT_EQ(buf.data(), nullptr);
52}
53
jbauch13041cf2016-02-25 06:16:52 -080054TEST(CopyOnWriteBufferTest, TestMoveConstruct) {
55 CopyOnWriteBuffer buf1(kTestData, 3, 10);
56 size_t buf1_size = buf1.size();
57 size_t buf1_capacity = buf1.capacity();
58 const uint8_t* buf1_data = buf1.cdata();
59
60 CopyOnWriteBuffer buf2(std::move(buf1));
61 EXPECT_EQ(buf1.size(), 0u);
62 EXPECT_EQ(buf1.capacity(), 0u);
63 EXPECT_EQ(buf1.data(), nullptr);
64 EXPECT_EQ(buf2.size(), buf1_size);
65 EXPECT_EQ(buf2.capacity(), buf1_capacity);
66 EXPECT_EQ(buf2.data(), buf1_data);
67}
68
69TEST(CopyOnWriteBufferTest, TestMoveAssign) {
70 CopyOnWriteBuffer buf1(kTestData, 3, 10);
71 size_t buf1_size = buf1.size();
72 size_t buf1_capacity = buf1.capacity();
73 const uint8_t* buf1_data = buf1.cdata();
74
75 CopyOnWriteBuffer buf2;
76 buf2 = std::move(buf1);
77 EXPECT_EQ(buf1.size(), 0u);
78 EXPECT_EQ(buf1.capacity(), 0u);
79 EXPECT_EQ(buf1.data(), nullptr);
80 EXPECT_EQ(buf2.size(), buf1_size);
81 EXPECT_EQ(buf2.capacity(), buf1_capacity);
82 EXPECT_EQ(buf2.data(), buf1_data);
83}
84
85TEST(CopyOnWriteBufferTest, TestSwap) {
86 CopyOnWriteBuffer buf1(kTestData, 3, 10);
87 size_t buf1_size = buf1.size();
88 size_t buf1_capacity = buf1.capacity();
89 const uint8_t* buf1_data = buf1.cdata();
90
91 CopyOnWriteBuffer buf2(kTestData, 6, 20);
92 size_t buf2_size = buf2.size();
93 size_t buf2_capacity = buf2.capacity();
94 const uint8_t* buf2_data = buf2.cdata();
95
96 std::swap(buf1, buf2);
97 EXPECT_EQ(buf1.size(), buf2_size);
98 EXPECT_EQ(buf1.capacity(), buf2_capacity);
99 EXPECT_EQ(buf1.data(), buf2_data);
100 EXPECT_EQ(buf2.size(), buf1_size);
101 EXPECT_EQ(buf2.capacity(), buf1_capacity);
102 EXPECT_EQ(buf2.data(), buf1_data);
103}
104
105TEST(CopyOnWriteBufferTest, TestAppendData) {
106 CopyOnWriteBuffer buf1(kTestData, 3, 10);
107 CopyOnWriteBuffer buf2(buf1);
108
109 EnsureBuffersShareData(buf1, buf2);
110
111 // AppendData copies the underlying buffer.
112 buf2.AppendData("foo");
113 EXPECT_EQ(buf2.size(), buf1.size() + 4); // "foo" + trailing 0x00
114 EXPECT_EQ(buf2.capacity(), buf1.capacity());
115 EXPECT_NE(buf2.data(), buf1.data());
116
117 EXPECT_EQ(buf1, CopyOnWriteBuffer(kTestData, 3));
118 const int8_t exp[] = {0x0, 0x1, 0x2, 'f', 'o', 'o', 0x0};
119 EXPECT_EQ(buf2, CopyOnWriteBuffer(exp));
120}
121
Danil Chapovalov2b2779f2016-09-13 14:15:10 +0200122TEST(CopyOnWriteBufferTest, SetEmptyData) {
123 CopyOnWriteBuffer buf(10);
124
125 buf.SetData<uint8_t>(nullptr, 0);
126
127 EXPECT_EQ(0u, buf.size());
128}
129
130TEST(CopyOnWriteBufferTest, SetDataNoMoreThanCapacityDoesntCauseReallocation) {
131 CopyOnWriteBuffer buf1(3, 10);
132 const uint8_t* const original_allocation = buf1.cdata();
133
134 buf1.SetData(kTestData, 10);
135
136 EXPECT_EQ(original_allocation, buf1.cdata());
137 EXPECT_EQ(buf1, CopyOnWriteBuffer(kTestData, 10));
138}
139
140TEST(CopyOnWriteBufferTest, SetDataMakeReferenceCopy) {
jbauch13041cf2016-02-25 06:16:52 -0800141 CopyOnWriteBuffer buf1(kTestData, 3, 10);
142 CopyOnWriteBuffer buf2;
143
144 buf2.SetData(buf1);
jbauch13041cf2016-02-25 06:16:52 -0800145
jbauch13041cf2016-02-25 06:16:52 -0800146 EnsureBuffersShareData(buf1, buf2);
jbaucheec21bd2016-03-20 06:15:43 -0700147}
148
Danil Chapovalov2b2779f2016-09-13 14:15:10 +0200149TEST(CopyOnWriteBufferTest, SetDataOnSharedKeepsOriginal) {
150 const uint8_t data[] = "foo";
151 CopyOnWriteBuffer buf1(kTestData, 3, 10);
152 const uint8_t* const original_allocation = buf1.cdata();
153 CopyOnWriteBuffer buf2(buf1);
154
155 buf2.SetData(data);
156
157 EnsureBuffersDontShareData(buf1, buf2);
158 EXPECT_EQ(original_allocation, buf1.cdata());
159 EXPECT_EQ(buf1, CopyOnWriteBuffer(kTestData, 3));
160 EXPECT_EQ(buf2, CopyOnWriteBuffer(data));
161}
162
163TEST(CopyOnWriteBufferTest, SetDataOnSharedKeepsCapacity) {
164 CopyOnWriteBuffer buf1(kTestData, 3, 10);
165 CopyOnWriteBuffer buf2(buf1);
166 EnsureBuffersShareData(buf1, buf2);
167
168 buf2.SetData(kTestData, 2);
169
170 EnsureBuffersDontShareData(buf1, buf2);
171 EXPECT_EQ(2u, buf2.size());
172 EXPECT_EQ(10u, buf2.capacity());
jbauch13041cf2016-02-25 06:16:52 -0800173}
174
175TEST(CopyOnWriteBufferTest, TestEnsureCapacity) {
176 CopyOnWriteBuffer buf1(kTestData, 3, 10);
177 CopyOnWriteBuffer buf2(buf1);
178
179 // Smaller than existing capacity -> no change and still same contents.
180 buf2.EnsureCapacity(8);
181 EnsureBuffersShareData(buf1, buf2);
182 EXPECT_EQ(buf1.size(), 3u);
183 EXPECT_EQ(buf1.capacity(), 10u);
184 EXPECT_EQ(buf2.size(), 3u);
185 EXPECT_EQ(buf2.capacity(), 10u);
186
187 // Lager than existing capacity -> data is cloned.
188 buf2.EnsureCapacity(16);
189 EnsureBuffersDontShareData(buf1, buf2);
190 EXPECT_EQ(buf1.size(), 3u);
191 EXPECT_EQ(buf1.capacity(), 10u);
192 EXPECT_EQ(buf2.size(), 3u);
193 EXPECT_EQ(buf2.capacity(), 16u);
194 // The size and contents are still the same.
195 EXPECT_EQ(buf1, buf2);
196}
197
Danil Chapovalov2b2779f2016-09-13 14:15:10 +0200198TEST(CopyOnWriteBufferTest, SetSizeDoesntChangeOriginal) {
199 CopyOnWriteBuffer buf1(kTestData, 3, 10);
200 const uint8_t* const original_allocation = buf1.cdata();
201 CopyOnWriteBuffer buf2(buf1);
202
203 buf2.SetSize(16);
204
205 EnsureBuffersDontShareData(buf1, buf2);
206 EXPECT_EQ(original_allocation, buf1.cdata());
207 EXPECT_EQ(3u, buf1.size());
208 EXPECT_EQ(10u, buf1.capacity());
209}
210
211TEST(CopyOnWriteBufferTest, SetSizeCloneContent) {
jbauch13041cf2016-02-25 06:16:52 -0800212 CopyOnWriteBuffer buf1(kTestData, 3, 10);
213 CopyOnWriteBuffer buf2(buf1);
214
215 buf2.SetSize(16);
Danil Chapovalov2b2779f2016-09-13 14:15:10 +0200216
jbauch13041cf2016-02-25 06:16:52 -0800217 EXPECT_EQ(buf2.size(), 16u);
jbauch13041cf2016-02-25 06:16:52 -0800218 EXPECT_EQ(0, memcmp(buf2.data(), kTestData, 3));
219}
220
Danil Chapovalov2b2779f2016-09-13 14:15:10 +0200221TEST(CopyOnWriteBufferTest, SetSizeMayIncreaseCapacity) {
222 CopyOnWriteBuffer buf(kTestData, 3, 10);
223
224 buf.SetSize(16);
225
226 EXPECT_EQ(16u, buf.size());
227 EXPECT_EQ(16u, buf.capacity());
228}
229
230TEST(CopyOnWriteBufferTest, SetSizeDoesntDecreaseCapacity) {
231 CopyOnWriteBuffer buf1(kTestData, 5, 10);
232 CopyOnWriteBuffer buf2(buf1);
233
234 buf2.SetSize(2);
235
236 EXPECT_EQ(2u, buf2.size());
237 EXPECT_EQ(10u, buf2.capacity());
238}
239
240TEST(CopyOnWriteBufferTest, ClearDoesntChangeOriginal) {
241 CopyOnWriteBuffer buf1(kTestData, 3, 10);
242 const uint8_t* const original_allocation = buf1.cdata();
243 CopyOnWriteBuffer buf2(buf1);
244
245 buf2.Clear();
246
247 EnsureBuffersDontShareData(buf1, buf2);
248 EXPECT_EQ(3u, buf1.size());
249 EXPECT_EQ(10u, buf1.capacity());
250 EXPECT_EQ(original_allocation, buf1.cdata());
251 EXPECT_EQ(0u, buf2.size());
252}
253
254TEST(CopyOnWriteBufferTest, ClearDoesntChangeCapacity) {
jbauch13041cf2016-02-25 06:16:52 -0800255 CopyOnWriteBuffer buf1(kTestData, 3, 10);
256 CopyOnWriteBuffer buf2(buf1);
257
258 buf2.Clear();
Danil Chapovalov2b2779f2016-09-13 14:15:10 +0200259
260 EXPECT_EQ(0u, buf2.size());
261 EXPECT_EQ(10u, buf2.capacity());
jbauch13041cf2016-02-25 06:16:52 -0800262}
263
Danil Chapovalove4fd1ba2021-01-21 17:00:16 +0100264TEST(CopyOnWriteBufferTest, DataAccessorDoesntCloneData) {
jbauch13041cf2016-02-25 06:16:52 -0800265 CopyOnWriteBuffer buf1(kTestData, 3, 10);
266 CopyOnWriteBuffer buf2(buf1);
267
Danil Chapovalove4fd1ba2021-01-21 17:00:16 +0100268 EXPECT_EQ(buf1.data(), buf2.data());
jbauch13041cf2016-02-25 06:16:52 -0800269}
270
Danil Chapovalove4fd1ba2021-01-21 17:00:16 +0100271TEST(CopyOnWriteBufferTest, MutableDataClonesDataWhenShared) {
272 CopyOnWriteBuffer buf1(kTestData, 3, 10);
273 CopyOnWriteBuffer buf2(buf1);
274 const uint8_t* cdata = buf1.data();
275
276 uint8_t* data1 = buf1.MutableData();
277 uint8_t* data2 = buf2.MutableData();
278 // buf1 was cloned above.
279 EXPECT_NE(data1, cdata);
280 // Therefore buf2 was no longer sharing data and was not cloned.
281 EXPECT_EQ(data2, cdata);
282}
283
Danil Chapovalov82e18752021-01-07 13:38:48 +0100284TEST(CopyOnWriteBufferTest, SeveralReads) {
jbaucheec21bd2016-03-20 06:15:43 -0700285 CopyOnWriteBuffer buf1(kTestData, 3, 10);
286 CopyOnWriteBuffer buf2(buf1);
287
288 EnsureBuffersShareData(buf1, buf2);
jbaucheec21bd2016-03-20 06:15:43 -0700289 for (size_t i = 0; i != 3u; ++i) {
290 EXPECT_EQ(buf1[i], kTestData[i]);
291 }
jbaucheec21bd2016-03-20 06:15:43 -0700292 EnsureBuffersShareData(buf1, buf2);
293}
294
Danil Chapovalov82e18752021-01-07 13:38:48 +0100295TEST(CopyOnWriteBufferTest, SeveralWrites) {
jbaucheec21bd2016-03-20 06:15:43 -0700296 CopyOnWriteBuffer buf1(kTestData, 3, 10);
297 CopyOnWriteBuffer buf2(buf1);
298
299 EnsureBuffersShareData(buf1, buf2);
300 for (size_t i = 0; i != 3u; ++i) {
Danil Chapovalov82e18752021-01-07 13:38:48 +0100301 buf1.MutableData()[i] = kTestData[i] + 1;
jbaucheec21bd2016-03-20 06:15:43 -0700302 }
303 EXPECT_EQ(buf1.size(), 3u);
304 EXPECT_EQ(buf1.capacity(), 10u);
305 EXPECT_EQ(buf2.size(), 3u);
306 EXPECT_EQ(buf2.capacity(), 10u);
307 EXPECT_EQ(0, memcmp(buf2.cdata(), kTestData, 3));
308}
309
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +0200310TEST(CopyOnWriteBufferTest, CreateSlice) {
311 CopyOnWriteBuffer buf(kTestData, 10, 10);
312 CopyOnWriteBuffer slice = buf.Slice(3, 4);
313 EXPECT_EQ(slice.size(), 4u);
314 EXPECT_EQ(0, memcmp(buf.cdata() + 3, slice.cdata(), 4));
315}
316
317TEST(CopyOnWriteBufferTest, NoCopyDataOnSlice) {
318 CopyOnWriteBuffer buf(kTestData, 10, 10);
319 CopyOnWriteBuffer slice = buf.Slice(3, 4);
320 EXPECT_EQ(buf.cdata() + 3, slice.cdata());
321}
322
323TEST(CopyOnWriteBufferTest, WritingCopiesData) {
324 CopyOnWriteBuffer buf(kTestData, 10, 10);
325 CopyOnWriteBuffer slice = buf.Slice(3, 4);
Danil Chapovalov82e18752021-01-07 13:38:48 +0100326 slice.MutableData()[0] = 0xaa;
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +0200327 EXPECT_NE(buf.cdata() + 3, slice.cdata());
328 EXPECT_EQ(0, memcmp(buf.cdata(), kTestData, 10));
329}
330
331TEST(CopyOnWriteBufferTest, WritingToBufferDoesntAffectsSlice) {
332 CopyOnWriteBuffer buf(kTestData, 10, 10);
333 CopyOnWriteBuffer slice = buf.Slice(3, 4);
Danil Chapovalov82e18752021-01-07 13:38:48 +0100334 buf.MutableData()[0] = 0xaa;
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +0200335 EXPECT_NE(buf.cdata() + 3, slice.cdata());
336 EXPECT_EQ(0, memcmp(slice.cdata(), kTestData + 3, 4));
337}
338
339TEST(CopyOnWriteBufferTest, SliceOfASlice) {
340 CopyOnWriteBuffer buf(kTestData, 10, 10);
341 CopyOnWriteBuffer slice = buf.Slice(3, 7);
342 CopyOnWriteBuffer slice2 = slice.Slice(2, 3);
343 EXPECT_EQ(slice2.size(), 3u);
344 EXPECT_EQ(slice.cdata() + 2, slice2.cdata());
345 EXPECT_EQ(buf.cdata() + 5, slice2.cdata());
346}
347
348TEST(CopyOnWriteBufferTest, SlicesAreIndependent) {
349 CopyOnWriteBuffer buf(kTestData, 10, 10);
350 CopyOnWriteBuffer slice = buf.Slice(3, 7);
351 CopyOnWriteBuffer slice2 = buf.Slice(3, 7);
Danil Chapovalov82e18752021-01-07 13:38:48 +0100352 slice2.MutableData()[0] = 0xaa;
Ilya Nikolaevskiy741bab02019-09-25 14:37:10 +0200353 EXPECT_EQ(buf.cdata() + 3, slice.cdata());
354}
355
philipelafc23772021-09-20 11:22:13 +0200356TEST(CopyOnWriteBufferTest, AcceptsVectorLikeTypes) {
357 std::vector<uint8_t> a = {1, 2};
358 std::vector<int8_t> b = {3, 4};
359 rtc::ArrayView<uint8_t> c(a);
360 rtc::ArrayView<const int8_t> d(b);
361
362 CopyOnWriteBuffer a_buf(a);
363 CopyOnWriteBuffer b_buf(b);
364 CopyOnWriteBuffer c_buf(c);
365 CopyOnWriteBuffer d_buf(d);
366
367 CopyOnWriteBuffer all;
368 all.AppendData(a);
369 all.AppendData(b);
370 all.AppendData(c);
371 all.AppendData(d);
372
373 EXPECT_EQ(all.size(), 8U);
374}
375
jbauch13041cf2016-02-25 06:16:52 -0800376} // namespace rtc