• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2024 The Chromium Authors
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 "base/containers/span_writer.h"
6 
7 #include <array>
8 #include <memory>
9 
10 #include "testing/gmock/include/gmock/gmock.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 
13 namespace base {
14 namespace {
15 
16 using testing::ElementsAre;
17 using testing::Optional;
18 using testing::Pointee;
19 
TEST(SpanWriterTest,Construct)20 TEST(SpanWriterTest, Construct) {
21   std::array<int, 5u> kArray = {1, 2, 3, 4, 5};
22 
23   auto r = SpanWriter(span(kArray));
24   EXPECT_EQ(r.remaining(), 5u);
25   EXPECT_EQ(r.remaining_span().data(), &kArray[0u]);
26   EXPECT_EQ(r.remaining_span().size(), 5u);
27 }
28 
TEST(SpanWriterTest,WriteSpan)29 TEST(SpanWriterTest, WriteSpan) {
30   // Dynamic size.
31   {
32     std::array<int, 5u> kArray = {1, 2, 3, 4, 5};
33     auto r = SpanWriter(span(kArray));
34     EXPECT_EQ(r.num_written(), 0u);
35 
36     EXPECT_TRUE(r.Write(span<const int>({9, 8}).subspan(0u)));
37     EXPECT_EQ(r.remaining(), 3u);
38     EXPECT_EQ(r.num_written(), 2u);
39     EXPECT_EQ(kArray, span<const int>({9, 8, 3, 4, 5}));
40 
41     EXPECT_TRUE(r.Write(span<int>()));
42     EXPECT_EQ(r.remaining(), 3u);
43     EXPECT_EQ(r.num_written(), 2u);
44     EXPECT_EQ(kArray, span<const int>({9, 8, 3, 4, 5}));
45 
46     EXPECT_FALSE(r.Write(span<const int>({7, 6, -1, -1}).subspan(0u)));
47     EXPECT_EQ(r.remaining(), 3u);
48     EXPECT_EQ(r.num_written(), 2u);
49     EXPECT_EQ(kArray, span<const int>({9, 8, 3, 4, 5}));
50 
51     EXPECT_TRUE(r.Write(span<const int>({7, 6, -1}).subspan(0u)));
52     EXPECT_EQ(r.remaining(), 0u);
53     EXPECT_EQ(r.num_written(), 5u);
54     EXPECT_EQ(kArray, span<const int>({9, 8, 7, 6, -1}));
55 
56     EXPECT_TRUE(r.Write(span<int>()));
57     EXPECT_EQ(r.remaining(), 0u);
58     EXPECT_EQ(r.num_written(), 5u);
59     EXPECT_EQ(kArray, span<const int>({9, 8, 7, 6, -1}));
60   }
61 
62   // Fixed size with mutable input.
63   {
64     std::array<int, 5u> kArray = {1, 2, 3, 4, 5};
65     auto r = SpanWriter(span(kArray));
66     EXPECT_EQ(r.num_written(), 0u);
67 
68     EXPECT_TRUE(r.Write(span<const int>({9, 8})));
69     EXPECT_EQ(r.remaining(), 3u);
70     EXPECT_EQ(r.num_written(), 2u);
71     EXPECT_EQ(kArray, span<const int>({9, 8, 3, 4, 5}));
72 
73     EXPECT_TRUE(r.Write(span<int, 0u>()));
74     EXPECT_EQ(r.remaining(), 3u);
75     EXPECT_EQ(r.num_written(), 2u);
76     EXPECT_EQ(kArray, span<const int>({9, 8, 3, 4, 5}));
77 
78     EXPECT_FALSE(r.Write(span<const int>({7, 6, -1, -1})));
79     EXPECT_EQ(r.remaining(), 3u);
80     EXPECT_EQ(r.num_written(), 2u);
81     EXPECT_EQ(kArray, span<const int>({9, 8, 3, 4, 5}));
82 
83     EXPECT_TRUE(r.Write(span<const int>({7, 6, -1})));
84     EXPECT_EQ(r.remaining(), 0u);
85     EXPECT_EQ(r.num_written(), 5u);
86     EXPECT_EQ(kArray, span<const int>({9, 8, 7, 6, -1}));
87 
88     EXPECT_TRUE(r.Write(span<int, 0u>()));
89     EXPECT_EQ(r.remaining(), 0u);
90     EXPECT_EQ(r.num_written(), 5u);
91     EXPECT_EQ(kArray, span<const int>({9, 8, 7, 6, -1}));
92   }
93 
94   // Fixed size with const input.
95   {
96     std::array<int, 5u> kArray = {1, 2, 3, 4, 5};
97     auto r = SpanWriter(span(kArray));
98     EXPECT_EQ(r.num_written(), 0u);
99 
100     std::array<const int, 2u> kConstArray = {9, 8};
101     EXPECT_TRUE(r.Write(span(kConstArray)));
102     EXPECT_EQ(r.remaining(), 3u);
103     EXPECT_EQ(r.num_written(), 2u);
104     EXPECT_EQ(kArray, span<const int>({9, 8, 3, 4, 5}));
105   }
106 }
107 
TEST(SpanWriterTest,WriteValue)108 TEST(SpanWriterTest, WriteValue) {
109   auto array = std::to_array<int>({1, 2});
110 
111   auto r = SpanWriter(span(array));
112   EXPECT_TRUE(r.Write(10));
113   EXPECT_TRUE(r.Write(20));
114   EXPECT_THAT(array, ElementsAre(10, 20));
115 }
116 
TEST(SpanWriterTest,WriteValueMoveOnly)117 TEST(SpanWriterTest, WriteValueMoveOnly) {
118   std::array<std::unique_ptr<int>, 2> array;
119 
120   auto r = SpanWriter(span(array));
121   EXPECT_TRUE(r.Write(std::make_unique<int>(23)));
122   EXPECT_TRUE(r.Write(std::make_unique<int>(88)));
123   EXPECT_THAT(array, ElementsAre(testing::Pointee(23), testing::Pointee(88)));
124 }
125 
TEST(SpanWriterTest,Skip)126 TEST(SpanWriterTest, Skip) {
127   std::array<int, 5u> kArray = {1, 2, 3, 4, 5};
128 
129   auto r = SpanWriter(span(kArray));
130   auto s = r.Skip(2u);
131   static_assert(std::same_as<decltype(s), std::optional<span<int>>>);
132   EXPECT_THAT(s, Optional(span(kArray).first<2u>()));
133   EXPECT_EQ(r.remaining(), 3u);
134   EXPECT_EQ(r.remaining_span(), span<const int>({3, 4, 5}));
135 
136   EXPECT_FALSE(r.Skip(12u));
137   EXPECT_EQ(r.remaining(), 3u);
138   EXPECT_EQ(r.remaining_span(), span<const int>({3, 4, 5}));
139 }
140 
TEST(SpanWriterTest,SkipFixed)141 TEST(SpanWriterTest, SkipFixed) {
142   std::array<int, 5u> kArray = {1, 2, 3, 4, 5};
143 
144   auto r = SpanWriter(span(kArray));
145   auto s = r.Skip<2u>();
146   static_assert(std::same_as<decltype(s), std::optional<span<int, 2>>>);
147   EXPECT_THAT(s, Optional(span(kArray).first<2u>()));
148   EXPECT_EQ(r.remaining(), 3u);
149   EXPECT_EQ(r.remaining_span(), span<const int>({3, 4, 5}));
150 
151   EXPECT_FALSE(r.Skip<12u>());
152   EXPECT_EQ(r.remaining(), 3u);
153   EXPECT_EQ(r.remaining_span(), span<const int>({3, 4, 5}));
154 }
155 
TEST(SpanWriterTest,WriteNativeEndian_Unsigned)156 TEST(SpanWriterTest, WriteNativeEndian_Unsigned) {
157   std::array<uint8_t, 5u> kArray = {1, 2, 3, 4, 5};
158   std::array<uint8_t, 9u> kBigArray = {1, 1, 1, 1, 1, 1, 1, 1, 1};
159 
160   {
161     auto r = SpanWriter(span(kArray));
162     EXPECT_TRUE(r.Skip(1u));
163     EXPECT_TRUE(r.WriteU8NativeEndian(0x09));
164     EXPECT_EQ(r.remaining(), 3u);
165     EXPECT_EQ(kArray, span<const uint8_t>({1, 9, 3, 4, 5}));
166   }
167   {
168     auto r = SpanWriter(span(kArray));
169     EXPECT_TRUE(r.Skip(1u));
170     EXPECT_TRUE(r.WriteU16NativeEndian(0x0809));
171     EXPECT_EQ(r.remaining(), 2u);
172     EXPECT_EQ(kArray, span<const uint8_t>({1, 9, 8, 4, 5}));
173   }
174   {
175     auto r = SpanWriter(span(kArray));
176     EXPECT_TRUE(r.Skip(1u));
177     EXPECT_TRUE(r.WriteU32NativeEndian(0x06070809u));
178     EXPECT_EQ(r.remaining(), 0u);
179     EXPECT_EQ(kArray, span<const uint8_t>({1, 9, 8, 7, 6}));
180   }
181   {
182     auto r = SpanWriter(span(kBigArray));
183     EXPECT_TRUE(r.Skip(1u));
184     EXPECT_TRUE(r.WriteU64NativeEndian(0x0203040506070809lu));
185     EXPECT_EQ(r.remaining(), 0u);
186     EXPECT_EQ(kBigArray, span<const uint8_t>({1, 9, 8, 7, 6, 5, 4, 3, 2}));
187   }
188 }
189 
TEST(SpanWriterTest,WriteNativeEndian_Signed)190 TEST(SpanWriterTest, WriteNativeEndian_Signed) {
191   std::array<uint8_t, 5u> kArray = {1, 2, 3, 4, 5};
192   std::array<uint8_t, 9u> kBigArray = {1, 1, 1, 1, 1, 1, 1, 1, 1};
193 
194   {
195     auto r = SpanWriter(span(kArray));
196     EXPECT_TRUE(r.Skip(1u));
197     EXPECT_TRUE(r.WriteI8NativeEndian(-0x09));
198     EXPECT_EQ(r.remaining(), 3u);
199     EXPECT_EQ(kArray, span<const uint8_t>({1, 0xf7, 3, 4, 5}));
200   }
201   {
202     auto r = SpanWriter(span(kArray));
203     EXPECT_TRUE(r.Skip(1u));
204     EXPECT_TRUE(r.WriteI16NativeEndian(-0x0809));
205     EXPECT_EQ(r.remaining(), 2u);
206     EXPECT_EQ(kArray, span<const uint8_t>({1, 0xf7, 0xf7, 4, 5}));
207   }
208   {
209     auto r = SpanWriter(span(kArray));
210     EXPECT_TRUE(r.Skip(1u));
211     EXPECT_TRUE(r.WriteI32NativeEndian(-0x06070809));
212     EXPECT_EQ(r.remaining(), 0u);
213     EXPECT_EQ(kArray, span<const uint8_t>({1, 0xf7, 0xf7, 0xf8, 0xf9}));
214   }
215   {
216     auto r = SpanWriter(span(kBigArray));
217     EXPECT_TRUE(r.Skip(1u));
218     EXPECT_TRUE(r.WriteI64NativeEndian(-0x0203040506070809l));
219     EXPECT_EQ(r.remaining(), 0u);
220     EXPECT_EQ(kBigArray, span<const uint8_t>({1, 0xf7, 0xf7, 0xf8, 0xf9, 0xfa,
221                                               0xfb, 0xfc, 0xfd}));
222   }
223 }
224 
TEST(SpanWriterTest,WriteLittleEndian_Unsigned)225 TEST(SpanWriterTest, WriteLittleEndian_Unsigned) {
226   std::array<uint8_t, 5u> kArray = {1, 2, 3, 4, 5};
227   std::array<uint8_t, 9u> kBigArray = {1, 1, 1, 1, 1, 1, 1, 1, 1};
228 
229   {
230     auto r = SpanWriter(span(kArray));
231     EXPECT_TRUE(r.Skip(1u));
232     EXPECT_TRUE(r.WriteU8LittleEndian(0x09));
233     EXPECT_EQ(r.remaining(), 3u);
234     EXPECT_EQ(kArray, span<const uint8_t>({1, 9, 3, 4, 5}));
235   }
236   {
237     auto r = SpanWriter(span(kArray));
238     EXPECT_TRUE(r.Skip(1u));
239     EXPECT_TRUE(r.WriteU16LittleEndian(0x0809));
240     EXPECT_EQ(r.remaining(), 2u);
241     EXPECT_EQ(kArray, span<const uint8_t>({1, 9, 8, 4, 5}));
242   }
243   {
244     auto r = SpanWriter(span(kArray));
245     EXPECT_TRUE(r.Skip(1u));
246     EXPECT_TRUE(r.WriteU32LittleEndian(0x06070809u));
247     EXPECT_EQ(r.remaining(), 0u);
248     EXPECT_EQ(kArray, span<const uint8_t>({1, 9, 8, 7, 6}));
249   }
250   {
251     auto r = SpanWriter(span(kBigArray));
252     EXPECT_TRUE(r.Skip(1u));
253     EXPECT_TRUE(r.WriteU64LittleEndian(0x0203040506070809lu));
254     EXPECT_EQ(r.remaining(), 0u);
255     EXPECT_EQ(kBigArray, span<const uint8_t>({1, 9, 8, 7, 6, 5, 4, 3, 2}));
256   }
257 }
258 
TEST(SpanWriterTest,WriteLittleEndian_Signed)259 TEST(SpanWriterTest, WriteLittleEndian_Signed) {
260   std::array<uint8_t, 5u> kArray = {1, 2, 3, 4, 5};
261   std::array<uint8_t, 9u> kBigArray = {1, 1, 1, 1, 1, 1, 1, 1, 1};
262 
263   {
264     auto r = SpanWriter(span(kArray));
265     EXPECT_TRUE(r.Skip(1u));
266     EXPECT_TRUE(r.WriteI8LittleEndian(-0x09));
267     EXPECT_EQ(r.remaining(), 3u);
268     EXPECT_EQ(kArray, span<const uint8_t>({1, 0xf7, 3, 4, 5}));
269   }
270   {
271     auto r = SpanWriter(span(kArray));
272     EXPECT_TRUE(r.Skip(1u));
273     EXPECT_TRUE(r.WriteI16LittleEndian(-0x0809));
274     EXPECT_EQ(r.remaining(), 2u);
275     EXPECT_EQ(kArray, span<const uint8_t>({1, 0xf7, 0xf7, 4, 5}));
276   }
277   {
278     auto r = SpanWriter(span(kArray));
279     EXPECT_TRUE(r.Skip(1u));
280     EXPECT_TRUE(r.WriteI32LittleEndian(-0x06070809));
281     EXPECT_EQ(r.remaining(), 0u);
282     EXPECT_EQ(kArray, span<const uint8_t>({1, 0xf7, 0xf7, 0xf8, 0xf9}));
283   }
284   {
285     auto r = SpanWriter(span(kBigArray));
286     EXPECT_TRUE(r.Skip(1u));
287     EXPECT_TRUE(r.WriteI64LittleEndian(-0x0203040506070809l));
288     EXPECT_EQ(r.remaining(), 0u);
289     EXPECT_EQ(kBigArray, span<const uint8_t>({1, 0xf7, 0xf7, 0xf8, 0xf9, 0xfa,
290                                               0xfb, 0xfc, 0xfd}));
291   }
292 }
293 
TEST(SpanWriterTest,WriteBigEndian_Unsigned)294 TEST(SpanWriterTest, WriteBigEndian_Unsigned) {
295   std::array<uint8_t, 5u> kArray = {1, 2, 3, 4, 5};
296   std::array<uint8_t, 9u> kBigArray = {1, 1, 1, 1, 1, 1, 1, 1, 1};
297 
298   {
299     auto r = SpanWriter(span(kArray));
300     EXPECT_TRUE(r.Skip(1u));
301     EXPECT_TRUE(r.WriteU8BigEndian(0x09));
302     EXPECT_EQ(r.remaining(), 3u);
303     EXPECT_EQ(kArray, span<const uint8_t>({1, 9, 3, 4, 5}));
304   }
305   {
306     auto r = SpanWriter(span(kArray));
307     EXPECT_TRUE(r.Skip(1u));
308     EXPECT_TRUE(r.WriteU16BigEndian(0x0809));
309     EXPECT_EQ(r.remaining(), 2u);
310     EXPECT_EQ(kArray, span<const uint8_t>({1, 8, 9, 4, 5}));
311   }
312   {
313     auto r = SpanWriter(span(kArray));
314     EXPECT_TRUE(r.Skip(1u));
315     EXPECT_TRUE(r.WriteU32BigEndian(0x06070809u));
316     EXPECT_EQ(r.remaining(), 0u);
317     EXPECT_EQ(kArray, span<const uint8_t>({1, 6, 7, 8, 9}));
318   }
319   {
320     auto r = SpanWriter(span(kBigArray));
321     EXPECT_TRUE(r.Skip(1u));
322     EXPECT_TRUE(r.WriteU64BigEndian(0x0203040506070809lu));
323     EXPECT_EQ(r.remaining(), 0u);
324     EXPECT_EQ(kBigArray, span<const uint8_t>({1, 2, 3, 4, 5, 6, 7, 8, 9}));
325   }
326 }
327 
TEST(SpanWriterTest,WriteBigEndian_Signed)328 TEST(SpanWriterTest, WriteBigEndian_Signed) {
329   std::array<uint8_t, 5u> kArray = {1, 2, 3, 4, 5};
330   std::array<uint8_t, 9u> kBigArray = {1, 1, 1, 1, 1, 1, 1, 1, 1};
331 
332   {
333     auto r = SpanWriter(span(kArray));
334     EXPECT_TRUE(r.Skip(1u));
335     EXPECT_TRUE(r.WriteI8BigEndian(-0x09));
336     EXPECT_EQ(r.remaining(), 3u);
337     EXPECT_EQ(kArray, span<const uint8_t>({1, 0xf7, 3, 4, 5}));
338   }
339   {
340     auto r = SpanWriter(span(kArray));
341     EXPECT_TRUE(r.Skip(1u));
342     EXPECT_TRUE(r.WriteI16BigEndian(-0x0809));
343     EXPECT_EQ(r.remaining(), 2u);
344     EXPECT_EQ(kArray, span<const uint8_t>({1, 0xf7, 0xf7, 4, 5}));
345   }
346   {
347     auto r = SpanWriter(span(kArray));
348     EXPECT_TRUE(r.Skip(1u));
349     EXPECT_TRUE(r.WriteI32BigEndian(-0x06070809));
350     EXPECT_EQ(r.remaining(), 0u);
351     EXPECT_EQ(kArray, span<const uint8_t>({1, 0xf9, 0xf8, 0xf7, 0xf7}));
352   }
353   {
354     auto r = SpanWriter(span(kBigArray));
355     EXPECT_TRUE(r.Skip(1u));
356     EXPECT_TRUE(r.WriteI64BigEndian(-0x0203040506070809l));
357     EXPECT_EQ(r.remaining(), 0u);
358     EXPECT_EQ(kBigArray, span<const uint8_t>({1, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9,
359                                               0xf8, 0xf7, 0xf7}));
360   }
361 }
362 
TEST(SpanWriterTest,Chars)363 TEST(SpanWriterTest, Chars) {
364   std::array<char, 5u> kArray = {'a', 'b', 'c', 'd', 'e'};
365 
366   auto r = SpanWriter(span(kArray));
367   EXPECT_TRUE(r.Skip(1u));
368   EXPECT_TRUE(r.Write(span<const char>({'f', 'g'})));
369   EXPECT_EQ(r.remaining(), 2u);
370   EXPECT_EQ(kArray, span<const char>({'a', 'f', 'g', 'd', 'e'}));
371 }
372 
373 }  // namespace
374 }  // namespace base
375