1 // Copyright (c) 2020 The Chromium Authors. All rights reserved.
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 "net/third_party/quiche/src/common/quiche_data_writer.h"
6
7 #include <cstdint>
8 #include <cstring>
9
10 #include "absl/base/macros.h"
11 #include "absl/strings/string_view.h"
12 #include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
13 #include "net/third_party/quiche/src/common/platform/api/quiche_test.h"
14 #include "net/third_party/quiche/src/common/quiche_data_reader.h"
15 #include "net/third_party/quiche/src/common/quiche_endian.h"
16 #include "net/third_party/quiche/src/common/test_tools/quiche_test_utils.h"
17
18 namespace quiche {
19 namespace test {
20 namespace {
21
AsChars(unsigned char * data)22 char* AsChars(unsigned char* data) {
23 return reinterpret_cast<char*>(data);
24 }
25
26 struct TestParams {
TestParamsquiche::test::__anon2e69ef980111::TestParams27 explicit TestParams(quiche::Endianness endianness) : endianness(endianness) {}
28
29 quiche::Endianness endianness;
30 };
31
32 // Used by ::testing::PrintToStringParamName().
PrintToString(const TestParams & p)33 std::string PrintToString(const TestParams& p) {
34 return quiche::QuicheStrCat(
35 (p.endianness == quiche::NETWORK_BYTE_ORDER ? "Network" : "Host"),
36 "ByteOrder");
37 }
38
GetTestParams()39 std::vector<TestParams> GetTestParams() {
40 std::vector<TestParams> params;
41 for (quiche::Endianness endianness :
42 {quiche::NETWORK_BYTE_ORDER, quiche::HOST_BYTE_ORDER}) {
43 params.push_back(TestParams(endianness));
44 }
45 return params;
46 }
47
48 class QuicheDataWriterTest : public QuicheTestWithParam<TestParams> {};
49
50 INSTANTIATE_TEST_SUITE_P(QuicheDataWriterTests,
51 QuicheDataWriterTest,
52 ::testing::ValuesIn(GetTestParams()),
53 ::testing::PrintToStringParamName());
54
TEST_P(QuicheDataWriterTest,Write16BitUnsignedIntegers)55 TEST_P(QuicheDataWriterTest, Write16BitUnsignedIntegers) {
56 char little_endian16[] = {0x22, 0x11};
57 char big_endian16[] = {0x11, 0x22};
58 char buffer16[2];
59 {
60 uint16_t in_memory16 = 0x1122;
61 QuicheDataWriter writer(2, buffer16, GetParam().endianness);
62 writer.WriteUInt16(in_memory16);
63 test::CompareCharArraysWithHexError(
64 "uint16_t", buffer16, 2,
65 GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian16
66 : little_endian16,
67 2);
68
69 uint16_t read_number16;
70 QuicheDataReader reader(buffer16, 2, GetParam().endianness);
71 reader.ReadUInt16(&read_number16);
72 EXPECT_EQ(in_memory16, read_number16);
73 }
74
75 {
76 uint64_t in_memory16 = 0x0000000000001122;
77 QuicheDataWriter writer(2, buffer16, GetParam().endianness);
78 writer.WriteBytesToUInt64(2, in_memory16);
79 test::CompareCharArraysWithHexError(
80 "uint16_t", buffer16, 2,
81 GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian16
82 : little_endian16,
83 2);
84
85 uint64_t read_number16;
86 QuicheDataReader reader(buffer16, 2, GetParam().endianness);
87 reader.ReadBytesToUInt64(2, &read_number16);
88 EXPECT_EQ(in_memory16, read_number16);
89 }
90 }
91
TEST_P(QuicheDataWriterTest,Write24BitUnsignedIntegers)92 TEST_P(QuicheDataWriterTest, Write24BitUnsignedIntegers) {
93 char little_endian24[] = {0x33, 0x22, 0x11};
94 char big_endian24[] = {0x11, 0x22, 0x33};
95 char buffer24[3];
96 uint64_t in_memory24 = 0x0000000000112233;
97 QuicheDataWriter writer(3, buffer24, GetParam().endianness);
98 writer.WriteBytesToUInt64(3, in_memory24);
99 test::CompareCharArraysWithHexError(
100 "uint24", buffer24, 3,
101 GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian24
102 : little_endian24,
103 3);
104
105 uint64_t read_number24;
106 QuicheDataReader reader(buffer24, 3, GetParam().endianness);
107 reader.ReadBytesToUInt64(3, &read_number24);
108 EXPECT_EQ(in_memory24, read_number24);
109 }
110
TEST_P(QuicheDataWriterTest,Write32BitUnsignedIntegers)111 TEST_P(QuicheDataWriterTest, Write32BitUnsignedIntegers) {
112 char little_endian32[] = {0x44, 0x33, 0x22, 0x11};
113 char big_endian32[] = {0x11, 0x22, 0x33, 0x44};
114 char buffer32[4];
115 {
116 uint32_t in_memory32 = 0x11223344;
117 QuicheDataWriter writer(4, buffer32, GetParam().endianness);
118 writer.WriteUInt32(in_memory32);
119 test::CompareCharArraysWithHexError(
120 "uint32_t", buffer32, 4,
121 GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian32
122 : little_endian32,
123 4);
124
125 uint32_t read_number32;
126 QuicheDataReader reader(buffer32, 4, GetParam().endianness);
127 reader.ReadUInt32(&read_number32);
128 EXPECT_EQ(in_memory32, read_number32);
129 }
130
131 {
132 uint64_t in_memory32 = 0x11223344;
133 QuicheDataWriter writer(4, buffer32, GetParam().endianness);
134 writer.WriteBytesToUInt64(4, in_memory32);
135 test::CompareCharArraysWithHexError(
136 "uint32_t", buffer32, 4,
137 GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian32
138 : little_endian32,
139 4);
140
141 uint64_t read_number32;
142 QuicheDataReader reader(buffer32, 4, GetParam().endianness);
143 reader.ReadBytesToUInt64(4, &read_number32);
144 EXPECT_EQ(in_memory32, read_number32);
145 }
146 }
147
TEST_P(QuicheDataWriterTest,Write40BitUnsignedIntegers)148 TEST_P(QuicheDataWriterTest, Write40BitUnsignedIntegers) {
149 uint64_t in_memory40 = 0x0000001122334455;
150 char little_endian40[] = {0x55, 0x44, 0x33, 0x22, 0x11};
151 char big_endian40[] = {0x11, 0x22, 0x33, 0x44, 0x55};
152 char buffer40[5];
153 QuicheDataWriter writer(5, buffer40, GetParam().endianness);
154 writer.WriteBytesToUInt64(5, in_memory40);
155 test::CompareCharArraysWithHexError(
156 "uint40", buffer40, 5,
157 GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian40
158 : little_endian40,
159 5);
160
161 uint64_t read_number40;
162 QuicheDataReader reader(buffer40, 5, GetParam().endianness);
163 reader.ReadBytesToUInt64(5, &read_number40);
164 EXPECT_EQ(in_memory40, read_number40);
165 }
166
TEST_P(QuicheDataWriterTest,Write48BitUnsignedIntegers)167 TEST_P(QuicheDataWriterTest, Write48BitUnsignedIntegers) {
168 uint64_t in_memory48 = 0x0000112233445566;
169 char little_endian48[] = {0x66, 0x55, 0x44, 0x33, 0x22, 0x11};
170 char big_endian48[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
171 char buffer48[6];
172 QuicheDataWriter writer(6, buffer48, GetParam().endianness);
173 writer.WriteBytesToUInt64(6, in_memory48);
174 test::CompareCharArraysWithHexError(
175 "uint48", buffer48, 6,
176 GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian48
177 : little_endian48,
178 6);
179
180 uint64_t read_number48;
181 QuicheDataReader reader(buffer48, 6, GetParam().endianness);
182 reader.ReadBytesToUInt64(6., &read_number48);
183 EXPECT_EQ(in_memory48, read_number48);
184 }
185
TEST_P(QuicheDataWriterTest,Write56BitUnsignedIntegers)186 TEST_P(QuicheDataWriterTest, Write56BitUnsignedIntegers) {
187 uint64_t in_memory56 = 0x0011223344556677;
188 char little_endian56[] = {0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11};
189 char big_endian56[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
190 char buffer56[7];
191 QuicheDataWriter writer(7, buffer56, GetParam().endianness);
192 writer.WriteBytesToUInt64(7, in_memory56);
193 test::CompareCharArraysWithHexError(
194 "uint56", buffer56, 7,
195 GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian56
196 : little_endian56,
197 7);
198
199 uint64_t read_number56;
200 QuicheDataReader reader(buffer56, 7, GetParam().endianness);
201 reader.ReadBytesToUInt64(7, &read_number56);
202 EXPECT_EQ(in_memory56, read_number56);
203 }
204
TEST_P(QuicheDataWriterTest,Write64BitUnsignedIntegers)205 TEST_P(QuicheDataWriterTest, Write64BitUnsignedIntegers) {
206 uint64_t in_memory64 = 0x1122334455667788;
207 unsigned char little_endian64[] = {0x88, 0x77, 0x66, 0x55,
208 0x44, 0x33, 0x22, 0x11};
209 unsigned char big_endian64[] = {0x11, 0x22, 0x33, 0x44,
210 0x55, 0x66, 0x77, 0x88};
211 char buffer64[8];
212 QuicheDataWriter writer(8, buffer64, GetParam().endianness);
213 writer.WriteBytesToUInt64(8, in_memory64);
214 test::CompareCharArraysWithHexError(
215 "uint64_t", buffer64, 8,
216 GetParam().endianness == quiche::NETWORK_BYTE_ORDER
217 ? AsChars(big_endian64)
218 : AsChars(little_endian64),
219 8);
220
221 uint64_t read_number64;
222 QuicheDataReader reader(buffer64, 8, GetParam().endianness);
223 reader.ReadBytesToUInt64(8, &read_number64);
224 EXPECT_EQ(in_memory64, read_number64);
225
226 QuicheDataWriter writer2(8, buffer64, GetParam().endianness);
227 writer2.WriteUInt64(in_memory64);
228 test::CompareCharArraysWithHexError(
229 "uint64_t", buffer64, 8,
230 GetParam().endianness == quiche::NETWORK_BYTE_ORDER
231 ? AsChars(big_endian64)
232 : AsChars(little_endian64),
233 8);
234 read_number64 = 0u;
235 QuicheDataReader reader2(buffer64, 8, GetParam().endianness);
236 reader2.ReadUInt64(&read_number64);
237 EXPECT_EQ(in_memory64, read_number64);
238 }
239
TEST_P(QuicheDataWriterTest,WriteIntegers)240 TEST_P(QuicheDataWriterTest, WriteIntegers) {
241 char buf[43];
242 uint8_t i8 = 0x01;
243 uint16_t i16 = 0x0123;
244 uint32_t i32 = 0x01234567;
245 uint64_t i64 = 0x0123456789ABCDEF;
246 QuicheDataWriter writer(46, buf, GetParam().endianness);
247 for (size_t i = 0; i < 10; ++i) {
248 switch (i) {
249 case 0u:
250 EXPECT_TRUE(writer.WriteBytesToUInt64(i, i64));
251 break;
252 case 1u:
253 EXPECT_TRUE(writer.WriteUInt8(i8));
254 EXPECT_TRUE(writer.WriteBytesToUInt64(i, i64));
255 break;
256 case 2u:
257 EXPECT_TRUE(writer.WriteUInt16(i16));
258 EXPECT_TRUE(writer.WriteBytesToUInt64(i, i64));
259 break;
260 case 3u:
261 EXPECT_TRUE(writer.WriteBytesToUInt64(i, i64));
262 break;
263 case 4u:
264 EXPECT_TRUE(writer.WriteUInt32(i32));
265 EXPECT_TRUE(writer.WriteBytesToUInt64(i, i64));
266 break;
267 case 5u:
268 case 6u:
269 case 7u:
270 case 8u:
271 EXPECT_TRUE(writer.WriteBytesToUInt64(i, i64));
272 break;
273 default:
274 EXPECT_FALSE(writer.WriteBytesToUInt64(i, i64));
275 }
276 }
277
278 QuicheDataReader reader(buf, 46, GetParam().endianness);
279 for (size_t i = 0; i < 10; ++i) {
280 uint8_t read8;
281 uint16_t read16;
282 uint32_t read32;
283 uint64_t read64;
284 switch (i) {
285 case 0u:
286 EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64));
287 EXPECT_EQ(0u, read64);
288 break;
289 case 1u:
290 EXPECT_TRUE(reader.ReadUInt8(&read8));
291 EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64));
292 EXPECT_EQ(i8, read8);
293 EXPECT_EQ(0xEFu, read64);
294 break;
295 case 2u:
296 EXPECT_TRUE(reader.ReadUInt16(&read16));
297 EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64));
298 EXPECT_EQ(i16, read16);
299 EXPECT_EQ(0xCDEFu, read64);
300 break;
301 case 3u:
302 EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64));
303 EXPECT_EQ(0xABCDEFu, read64);
304 break;
305 case 4u:
306 EXPECT_TRUE(reader.ReadUInt32(&read32));
307 EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64));
308 EXPECT_EQ(i32, read32);
309 EXPECT_EQ(0x89ABCDEFu, read64);
310 break;
311 case 5u:
312 EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64));
313 EXPECT_EQ(0x6789ABCDEFu, read64);
314 break;
315 case 6u:
316 EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64));
317 EXPECT_EQ(0x456789ABCDEFu, read64);
318 break;
319 case 7u:
320 EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64));
321 EXPECT_EQ(0x23456789ABCDEFu, read64);
322 break;
323 case 8u:
324 EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64));
325 EXPECT_EQ(0x0123456789ABCDEFu, read64);
326 break;
327 default:
328 EXPECT_FALSE(reader.ReadBytesToUInt64(i, &read64));
329 }
330 }
331 }
332
TEST_P(QuicheDataWriterTest,WriteBytes)333 TEST_P(QuicheDataWriterTest, WriteBytes) {
334 char bytes[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
335 char buf[ABSL_ARRAYSIZE(bytes)];
336 QuicheDataWriter writer(ABSL_ARRAYSIZE(buf), buf, GetParam().endianness);
337 EXPECT_TRUE(writer.WriteBytes(bytes, ABSL_ARRAYSIZE(bytes)));
338 for (unsigned int i = 0; i < ABSL_ARRAYSIZE(bytes); ++i) {
339 EXPECT_EQ(bytes[i], buf[i]);
340 }
341 }
342
TEST_P(QuicheDataWriterTest,Seek)343 TEST_P(QuicheDataWriterTest, Seek) {
344 char buffer[3] = {};
345 QuicheDataWriter writer(ABSL_ARRAYSIZE(buffer), buffer,
346 GetParam().endianness);
347 EXPECT_TRUE(writer.WriteUInt8(42));
348 EXPECT_TRUE(writer.Seek(1));
349 EXPECT_TRUE(writer.WriteUInt8(3));
350
351 char expected[] = {42, 0, 3};
352 for (size_t i = 0; i < ABSL_ARRAYSIZE(expected); ++i) {
353 EXPECT_EQ(buffer[i], expected[i]);
354 }
355 }
356
TEST_P(QuicheDataWriterTest,SeekTooFarFails)357 TEST_P(QuicheDataWriterTest, SeekTooFarFails) {
358 char buffer[20];
359
360 // Check that one can seek to the end of the writer, but not past.
361 {
362 QuicheDataWriter writer(ABSL_ARRAYSIZE(buffer), buffer,
363 GetParam().endianness);
364 EXPECT_TRUE(writer.Seek(20));
365 EXPECT_FALSE(writer.Seek(1));
366 }
367
368 // Seeking several bytes past the end fails.
369 {
370 QuicheDataWriter writer(ABSL_ARRAYSIZE(buffer), buffer,
371 GetParam().endianness);
372 EXPECT_FALSE(writer.Seek(100));
373 }
374
375 // Seeking so far that arithmetic overflow could occur also fails.
376 {
377 QuicheDataWriter writer(ABSL_ARRAYSIZE(buffer), buffer,
378 GetParam().endianness);
379 EXPECT_TRUE(writer.Seek(10));
380 EXPECT_FALSE(writer.Seek(std::numeric_limits<size_t>::max()));
381 }
382 }
383
TEST_P(QuicheDataWriterTest,PayloadReads)384 TEST_P(QuicheDataWriterTest, PayloadReads) {
385 char buffer[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
386 char expected_first_read[4] = {1, 2, 3, 4};
387 char expected_remaining[12] = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
388 QuicheDataReader reader(buffer, sizeof(buffer));
389 absl::string_view previously_read_payload1 = reader.PreviouslyReadPayload();
390 EXPECT_TRUE(previously_read_payload1.empty());
391 char first_read_buffer[4] = {};
392 EXPECT_TRUE(reader.ReadBytes(first_read_buffer, sizeof(first_read_buffer)));
393 test::CompareCharArraysWithHexError(
394 "first read", first_read_buffer, sizeof(first_read_buffer),
395 expected_first_read, sizeof(expected_first_read));
396 absl::string_view peeked_remaining_payload = reader.PeekRemainingPayload();
397 test::CompareCharArraysWithHexError(
398 "peeked_remaining_payload", peeked_remaining_payload.data(),
399 peeked_remaining_payload.length(), expected_remaining,
400 sizeof(expected_remaining));
401 absl::string_view full_payload = reader.FullPayload();
402 test::CompareCharArraysWithHexError("full_payload", full_payload.data(),
403 full_payload.length(), buffer,
404 sizeof(buffer));
405 absl::string_view previously_read_payload2 = reader.PreviouslyReadPayload();
406 test::CompareCharArraysWithHexError(
407 "previously_read_payload2", previously_read_payload2.data(),
408 previously_read_payload2.length(), first_read_buffer,
409 sizeof(first_read_buffer));
410 absl::string_view read_remaining_payload = reader.ReadRemainingPayload();
411 test::CompareCharArraysWithHexError(
412 "read_remaining_payload", read_remaining_payload.data(),
413 read_remaining_payload.length(), expected_remaining,
414 sizeof(expected_remaining));
415 EXPECT_TRUE(reader.IsDoneReading());
416 absl::string_view full_payload2 = reader.FullPayload();
417 test::CompareCharArraysWithHexError("full_payload2", full_payload2.data(),
418 full_payload2.length(), buffer,
419 sizeof(buffer));
420 absl::string_view previously_read_payload3 = reader.PreviouslyReadPayload();
421 test::CompareCharArraysWithHexError(
422 "previously_read_payload3", previously_read_payload3.data(),
423 previously_read_payload3.length(), buffer, sizeof(buffer));
424 }
425
426 } // namespace
427 } // namespace test
428 } // namespace quiche
429