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 "testing/gmock/include/gmock/gmock.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9
10 namespace base {
11 namespace {
12
13 using testing::Optional;
14
TEST(SpanWriterTest,Construct)15 TEST(SpanWriterTest, Construct) {
16 std::array<int, 5u> kArray = {1, 2, 3, 4, 5};
17
18 auto r = SpanWriter(base::span(kArray));
19 EXPECT_EQ(r.remaining(), 5u);
20 EXPECT_EQ(r.remaining_span().data(), &kArray[0u]);
21 EXPECT_EQ(r.remaining_span().size(), 5u);
22 }
23
TEST(SpanWriterTest,Write)24 TEST(SpanWriterTest, Write) {
25 // Dynamic size.
26 {
27 std::array<int, 5u> kArray = {1, 2, 3, 4, 5};
28 auto r = SpanWriter(base::span(kArray));
29 EXPECT_EQ(r.num_written(), 0u);
30
31 EXPECT_TRUE(r.Write(base::span({9, 8}).subspan(0u)));
32 EXPECT_EQ(r.remaining(), 3u);
33 EXPECT_EQ(r.num_written(), 2u);
34 EXPECT_EQ(kArray, base::span({9, 8, 3, 4, 5}));
35
36 EXPECT_TRUE(r.Write(base::span<int>()));
37 EXPECT_EQ(r.remaining(), 3u);
38 EXPECT_EQ(r.num_written(), 2u);
39 EXPECT_EQ(kArray, base::span({9, 8, 3, 4, 5}));
40
41 EXPECT_FALSE(r.Write(base::span({7, 6, -1, -1}).subspan(0u)));
42 EXPECT_EQ(r.remaining(), 3u);
43 EXPECT_EQ(r.num_written(), 2u);
44 EXPECT_EQ(kArray, base::span({9, 8, 3, 4, 5}));
45
46 EXPECT_TRUE(r.Write(base::span({7, 6, -1}).subspan(0u)));
47 EXPECT_EQ(r.remaining(), 0u);
48 EXPECT_EQ(r.num_written(), 5u);
49 EXPECT_EQ(kArray, base::span({9, 8, 7, 6, -1}));
50
51 EXPECT_TRUE(r.Write(base::span<int>()));
52 EXPECT_EQ(r.remaining(), 0u);
53 EXPECT_EQ(r.num_written(), 5u);
54 EXPECT_EQ(kArray, base::span({9, 8, 7, 6, -1}));
55 }
56
57 // Fixed size with mutable input.
58 {
59 std::array<int, 5u> kArray = {1, 2, 3, 4, 5};
60 auto r = SpanWriter(base::span(kArray));
61 EXPECT_EQ(r.num_written(), 0u);
62
63 EXPECT_TRUE(r.Write(base::span({9, 8})));
64 EXPECT_EQ(r.remaining(), 3u);
65 EXPECT_EQ(r.num_written(), 2u);
66 EXPECT_EQ(kArray, base::span({9, 8, 3, 4, 5}));
67
68 EXPECT_TRUE(r.Write(base::span<int, 0u>()));
69 EXPECT_EQ(r.remaining(), 3u);
70 EXPECT_EQ(r.num_written(), 2u);
71 EXPECT_EQ(kArray, base::span({9, 8, 3, 4, 5}));
72
73 EXPECT_FALSE(r.Write(base::span({7, 6, -1, -1})));
74 EXPECT_EQ(r.remaining(), 3u);
75 EXPECT_EQ(r.num_written(), 2u);
76 EXPECT_EQ(kArray, base::span({9, 8, 3, 4, 5}));
77
78 EXPECT_TRUE(r.Write(base::span({7, 6, -1})));
79 EXPECT_EQ(r.remaining(), 0u);
80 EXPECT_EQ(r.num_written(), 5u);
81 EXPECT_EQ(kArray, base::span({9, 8, 7, 6, -1}));
82
83 EXPECT_TRUE(r.Write(base::span<int, 0u>()));
84 EXPECT_EQ(r.remaining(), 0u);
85 EXPECT_EQ(r.num_written(), 5u);
86 EXPECT_EQ(kArray, base::span({9, 8, 7, 6, -1}));
87 }
88
89 // Fixed size with const input.
90 {
91 std::array<int, 5u> kArray = {1, 2, 3, 4, 5};
92 auto r = SpanWriter(base::span(kArray));
93 EXPECT_EQ(r.num_written(), 0u);
94
95 std::array<const int, 2u> kConstArray = {9, 8};
96 EXPECT_TRUE(r.Write(base::span(kConstArray)));
97 EXPECT_EQ(r.remaining(), 3u);
98 EXPECT_EQ(r.num_written(), 2u);
99 EXPECT_EQ(kArray, base::span({9, 8, 3, 4, 5}));
100 }
101 }
102
TEST(SpanWriterTest,Skip)103 TEST(SpanWriterTest, Skip) {
104 std::array<int, 5u> kArray = {1, 2, 3, 4, 5};
105
106 auto r = SpanWriter(base::span(kArray));
107 auto s = r.Skip(2u);
108 static_assert(std::same_as<decltype(s), std::optional<base::span<int>>>);
109 EXPECT_THAT(s, Optional(base::span(kArray).first<2u>()));
110 EXPECT_EQ(r.remaining(), 3u);
111 EXPECT_EQ(r.remaining_span(), base::span({3, 4, 5}));
112
113 EXPECT_FALSE(r.Skip(12u));
114 EXPECT_EQ(r.remaining(), 3u);
115 EXPECT_EQ(r.remaining_span(), base::span({3, 4, 5}));
116 }
117
TEST(SpanWriterTest,SkipFixed)118 TEST(SpanWriterTest, SkipFixed) {
119 std::array<int, 5u> kArray = {1, 2, 3, 4, 5};
120
121 auto r = SpanWriter(base::span(kArray));
122 auto s = r.Skip<2u>();
123 static_assert(std::same_as<decltype(s), std::optional<base::span<int, 2>>>);
124 EXPECT_THAT(s, Optional(base::span(kArray).first<2u>()));
125 EXPECT_EQ(r.remaining(), 3u);
126 EXPECT_EQ(r.remaining_span(), base::span({3, 4, 5}));
127
128 EXPECT_FALSE(r.Skip<12u>());
129 EXPECT_EQ(r.remaining(), 3u);
130 EXPECT_EQ(r.remaining_span(), base::span({3, 4, 5}));
131 }
132
TEST(SpanWriterTest,WriteNativeEndian)133 TEST(SpanWriterTest, WriteNativeEndian) {
134 std::array<uint8_t, 5u> kArray = {uint8_t{1}, uint8_t{2}, uint8_t{3},
135 uint8_t{4}, uint8_t{5}};
136
137 {
138 auto r = SpanWriter(base::span(kArray));
139 EXPECT_TRUE(r.Skip(1u));
140 EXPECT_TRUE(r.WriteU8NativeEndian(uint8_t{0x09}));
141 EXPECT_EQ(r.remaining(), 3u);
142 EXPECT_EQ(kArray, base::span({uint8_t{1}, uint8_t{9}, uint8_t{3},
143 uint8_t{4}, uint8_t{5}}));
144 }
145
146 {
147 auto r = SpanWriter(base::span(kArray));
148 EXPECT_TRUE(r.Skip(1u));
149 EXPECT_TRUE(r.WriteU16NativeEndian(uint16_t{0x0809}));
150 EXPECT_EQ(r.remaining(), 2u);
151 EXPECT_EQ(kArray, base::span({uint8_t{1}, uint8_t{9}, uint8_t{8},
152 uint8_t{4}, uint8_t{5}}));
153 }
154
155 {
156 auto r = SpanWriter(base::span(kArray));
157 EXPECT_TRUE(r.Skip(1u));
158 EXPECT_TRUE(r.WriteU32NativeEndian(0x06070809u));
159 EXPECT_EQ(r.remaining(), 0u);
160 EXPECT_EQ(kArray, base::span({uint8_t{1}, uint8_t{9}, uint8_t{8},
161 uint8_t{7}, uint8_t{6}}));
162 }
163
164 std::array<uint8_t, 9u> kBigArray = {uint8_t{1}, uint8_t{1}, uint8_t{1},
165 uint8_t{1}, uint8_t{1}, uint8_t{1},
166 uint8_t{1}, uint8_t{1}, uint8_t{1}};
167
168 {
169 auto r = SpanWriter(base::span(kBigArray));
170 EXPECT_TRUE(r.Skip(1u));
171 EXPECT_TRUE(r.WriteU64NativeEndian(0x0203040506070809lu));
172 EXPECT_EQ(r.remaining(), 0u);
173 EXPECT_EQ(kBigArray, base::span({uint8_t{1}, uint8_t{9}, uint8_t{8},
174 uint8_t{7}, uint8_t{6}, uint8_t{5},
175 uint8_t{4}, uint8_t{3}, uint8_t{2}}));
176 }
177 }
178
TEST(SpanWriterTest,WriteLittleEndian)179 TEST(SpanWriterTest, WriteLittleEndian) {
180 std::array<uint8_t, 5u> kArray = {uint8_t{1}, uint8_t{2}, uint8_t{3},
181 uint8_t{4}, uint8_t{5}};
182
183 {
184 auto r = SpanWriter(base::span(kArray));
185 EXPECT_TRUE(r.Skip(1u));
186 EXPECT_TRUE(r.WriteU8LittleEndian(uint8_t{0x09}));
187 EXPECT_EQ(r.remaining(), 3u);
188 EXPECT_EQ(kArray, base::span({uint8_t{1}, uint8_t{9}, uint8_t{3},
189 uint8_t{4}, uint8_t{5}}));
190 }
191
192 {
193 auto r = SpanWriter(base::span(kArray));
194 EXPECT_TRUE(r.Skip(1u));
195 EXPECT_TRUE(r.WriteU16LittleEndian(uint16_t{0x0809}));
196 EXPECT_EQ(r.remaining(), 2u);
197 EXPECT_EQ(kArray, base::span({uint8_t{1}, uint8_t{9}, uint8_t{8},
198 uint8_t{4}, uint8_t{5}}));
199 }
200
201 {
202 auto r = SpanWriter(base::span(kArray));
203 EXPECT_TRUE(r.Skip(1u));
204 EXPECT_TRUE(r.WriteU32LittleEndian(0x06070809u));
205 EXPECT_EQ(r.remaining(), 0u);
206 EXPECT_EQ(kArray, base::span({uint8_t{1}, uint8_t{9}, uint8_t{8},
207 uint8_t{7}, uint8_t{6}}));
208 }
209
210 std::array<uint8_t, 9u> kBigArray = {uint8_t{1}, uint8_t{1}, uint8_t{1},
211 uint8_t{1}, uint8_t{1}, uint8_t{1},
212 uint8_t{1}, uint8_t{1}, uint8_t{1}};
213
214 {
215 auto r = SpanWriter(base::span(kBigArray));
216 EXPECT_TRUE(r.Skip(1u));
217 EXPECT_TRUE(r.WriteU64LittleEndian(0x0203040506070809lu));
218 EXPECT_EQ(r.remaining(), 0u);
219 EXPECT_EQ(kBigArray, base::span({uint8_t{1}, uint8_t{9}, uint8_t{8},
220 uint8_t{7}, uint8_t{6}, uint8_t{5},
221 uint8_t{4}, uint8_t{3}, uint8_t{2}}));
222 }
223 }
224
TEST(SpanWriterTest,WriteBigEndian)225 TEST(SpanWriterTest, WriteBigEndian) {
226 std::array<uint8_t, 5u> kArray = {uint8_t{1}, uint8_t{2}, uint8_t{3},
227 uint8_t{4}, uint8_t{5}};
228
229 {
230 auto r = SpanWriter(base::span(kArray));
231 EXPECT_TRUE(r.Skip(1u));
232 EXPECT_TRUE(r.WriteU8BigEndian(uint8_t{0x09}));
233 EXPECT_EQ(r.remaining(), 3u);
234 EXPECT_EQ(kArray, base::span({uint8_t{1}, uint8_t{9}, uint8_t{3},
235 uint8_t{4}, uint8_t{5}}));
236 }
237
238 {
239 auto r = SpanWriter(base::span(kArray));
240 EXPECT_TRUE(r.Skip(1u));
241 EXPECT_TRUE(r.WriteU16BigEndian(uint16_t{0x0809}));
242 EXPECT_EQ(r.remaining(), 2u);
243 EXPECT_EQ(kArray, base::span({uint8_t{1}, uint8_t{8}, uint8_t{9},
244 uint8_t{4}, uint8_t{5}}));
245 }
246
247 {
248 auto r = SpanWriter(base::span(kArray));
249 EXPECT_TRUE(r.Skip(1u));
250 EXPECT_TRUE(r.WriteU32BigEndian(0x06070809u));
251 EXPECT_EQ(r.remaining(), 0u);
252 EXPECT_EQ(kArray, base::span({uint8_t{1}, uint8_t{6}, uint8_t{7},
253 uint8_t{8}, uint8_t{9}}));
254 }
255
256 std::array<uint8_t, 9u> kBigArray = {uint8_t{1}, uint8_t{1}, uint8_t{1},
257 uint8_t{1}, uint8_t{1}, uint8_t{1},
258 uint8_t{1}, uint8_t{1}, uint8_t{1}};
259
260 {
261 auto r = SpanWriter(base::span(kBigArray));
262 EXPECT_TRUE(r.Skip(1u));
263 EXPECT_TRUE(r.WriteU64BigEndian(0x0203040506070809lu));
264 EXPECT_EQ(r.remaining(), 0u);
265 EXPECT_EQ(kBigArray, base::span({uint8_t{1}, uint8_t{2}, uint8_t{3},
266 uint8_t{4}, uint8_t{5}, uint8_t{6},
267 uint8_t{7}, uint8_t{8}, uint8_t{9}}));
268 }
269 }
270
TEST(SpanWriterTest,Chars)271 TEST(SpanWriterTest, Chars) {
272 std::array<char, 5u> kArray = {'a', 'b', 'c', 'd', 'e'};
273
274 auto r = SpanWriter(base::span(kArray));
275 EXPECT_TRUE(r.Skip(1u));
276 EXPECT_TRUE(r.Write(base::span({'f', 'g'})));
277 EXPECT_EQ(r.remaining(), 2u);
278 EXPECT_EQ(kArray, base::span({'a', 'f', 'g', 'd', 'e'}));
279 }
280
281 } // namespace
282 } // namespace base
283