blob: fc569bdd62ca902328ad89cd007c355e248cd53f [file] [log] [blame]
jbauch13041cf2016-02-25 14:16:521/*
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 17:11:0011#include "rtc_base/copy_on_write_buffer.h"
Yves Gerey3e707812018-11-28 15:47:4912
13#include <cstdint>
14
15#include "test/gtest.h"
jbauch13041cf2016-02-25 14:16:5216
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 13:15:4347TEST(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 14:16:5254TEST(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 12:15:10122TEST(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 14:16:52141 CopyOnWriteBuffer buf1(kTestData, 3, 10);
142 CopyOnWriteBuffer buf2;
143
144 buf2.SetData(buf1);
jbauch13041cf2016-02-25 14:16:52145
jbauch13041cf2016-02-25 14:16:52146 EnsureBuffersShareData(buf1, buf2);
jbaucheec21bd2016-03-20 13:15:43147}
148
Danil Chapovalov2b2779f2016-09-13 12:15:10149TEST(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 14:16:52173}
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 12:15:10198TEST(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 14:16:52212 CopyOnWriteBuffer buf1(kTestData, 3, 10);
213 CopyOnWriteBuffer buf2(buf1);
214
215 buf2.SetSize(16);
Danil Chapovalov2b2779f2016-09-13 12:15:10216
jbauch13041cf2016-02-25 14:16:52217 EXPECT_EQ(buf2.size(), 16u);
jbauch13041cf2016-02-25 14:16:52218 EXPECT_EQ(0, memcmp(buf2.data(), kTestData, 3));
219}
220
Danil Chapovalov2b2779f2016-09-13 12:15:10221TEST(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 14:16:52255 CopyOnWriteBuffer buf1(kTestData, 3, 10);
256 CopyOnWriteBuffer buf2(buf1);
257
258 buf2.Clear();
Danil Chapovalov2b2779f2016-09-13 12:15:10259
260 EXPECT_EQ(0u, buf2.size());
261 EXPECT_EQ(10u, buf2.capacity());
jbauch13041cf2016-02-25 14:16:52262}
263
264TEST(CopyOnWriteBufferTest, TestConstDataAccessor) {
265 CopyOnWriteBuffer buf1(kTestData, 3, 10);
266 CopyOnWriteBuffer buf2(buf1);
267
268 // .cdata() doesn't clone data.
269 const uint8_t* cdata1 = buf1.cdata();
270 const uint8_t* cdata2 = buf2.cdata();
271 EXPECT_EQ(cdata1, cdata2);
272
273 // Non-const .data() clones data if shared.
274 const uint8_t* data1 = buf1.data();
275 const uint8_t* data2 = buf2.data();
276 EXPECT_NE(data1, data2);
277 // buf1 was cloned above.
278 EXPECT_NE(data1, cdata1);
279 // Therefore buf2 was no longer sharing data and was not cloned.
280 EXPECT_EQ(data2, cdata1);
281}
282
jbaucheec21bd2016-03-20 13:15:43283TEST(CopyOnWriteBufferTest, TestBacketRead) {
284 CopyOnWriteBuffer buf1(kTestData, 3, 10);
285 CopyOnWriteBuffer buf2(buf1);
286
287 EnsureBuffersShareData(buf1, buf2);
288 // Non-const reads clone the data if shared.
289 for (size_t i = 0; i != 3u; ++i) {
290 EXPECT_EQ(buf1[i], kTestData[i]);
291 }
292 EnsureBuffersDontShareData(buf1, buf2);
293}
294
295TEST(CopyOnWriteBufferTest, TestBacketReadConst) {
296 CopyOnWriteBuffer buf1(kTestData, 3, 10);
297 CopyOnWriteBuffer buf2(buf1);
298
299 EnsureBuffersShareData(buf1, buf2);
300 const CopyOnWriteBuffer& cbuf1 = buf1;
301 for (size_t i = 0; i != 3u; ++i) {
302 EXPECT_EQ(cbuf1[i], kTestData[i]);
303 }
304 EnsureBuffersShareData(buf1, buf2);
305}
306
307TEST(CopyOnWriteBufferTest, TestBacketWrite) {
308 CopyOnWriteBuffer buf1(kTestData, 3, 10);
309 CopyOnWriteBuffer buf2(buf1);
310
311 EnsureBuffersShareData(buf1, buf2);
312 for (size_t i = 0; i != 3u; ++i) {
313 buf1[i] = kTestData[i] + 1;
314 }
315 EXPECT_EQ(buf1.size(), 3u);
316 EXPECT_EQ(buf1.capacity(), 10u);
317 EXPECT_EQ(buf2.size(), 3u);
318 EXPECT_EQ(buf2.capacity(), 10u);
319 EXPECT_EQ(0, memcmp(buf2.cdata(), kTestData, 3));
320}
321
jbauch13041cf2016-02-25 14:16:52322} // namespace rtc