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 "quiche/common/quiche_data_writer.h"
6
7 #include <cstdint>
8 #include <cstring>
9
10 #include "absl/base/macros.h"
11 #include "absl/strings/str_cat.h"
12 #include "absl/strings/string_view.h"
13 #include "quiche/common/platform/api/quiche_test.h"
14 #include "quiche/common/quiche_data_reader.h"
15 #include "quiche/common/quiche_endian.h"
16 #include "quiche/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) { return reinterpret_cast<char*>(data); }
23
24 struct TestParams {
TestParamsquiche::test::__anon3eb70a620111::TestParams25 explicit TestParams(quiche::Endianness endianness) : endianness(endianness) {}
26
27 quiche::Endianness endianness;
28 };
29
30 // Used by ::testing::PrintToStringParamName().
PrintToString(const TestParams & p)31 std::string PrintToString(const TestParams& p) {
32 return absl::StrCat(
33 (p.endianness == quiche::NETWORK_BYTE_ORDER ? "Network" : "Host"),
34 "ByteOrder");
35 }
36
GetTestParams()37 std::vector<TestParams> GetTestParams() {
38 std::vector<TestParams> params;
39 for (quiche::Endianness endianness :
40 {quiche::NETWORK_BYTE_ORDER, quiche::HOST_BYTE_ORDER}) {
41 params.push_back(TestParams(endianness));
42 }
43 return params;
44 }
45
46 class QuicheDataWriterTest : public QuicheTestWithParam<TestParams> {};
47
48 INSTANTIATE_TEST_SUITE_P(QuicheDataWriterTests, QuicheDataWriterTest,
49 ::testing::ValuesIn(GetTestParams()),
50 ::testing::PrintToStringParamName());
51
TEST_P(QuicheDataWriterTest,Write16BitUnsignedIntegers)52 TEST_P(QuicheDataWriterTest, Write16BitUnsignedIntegers) {
53 char little_endian16[] = {0x22, 0x11};
54 char big_endian16[] = {0x11, 0x22};
55 char buffer16[2];
56 {
57 uint16_t in_memory16 = 0x1122;
58 QuicheDataWriter writer(2, buffer16, GetParam().endianness);
59 writer.WriteUInt16(in_memory16);
60 test::CompareCharArraysWithHexError(
61 "uint16_t", buffer16, 2,
62 GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian16
63 : little_endian16,
64 2);
65
66 uint16_t read_number16;
67 QuicheDataReader reader(buffer16, 2, GetParam().endianness);
68 reader.ReadUInt16(&read_number16);
69 EXPECT_EQ(in_memory16, read_number16);
70 }
71
72 {
73 uint64_t in_memory16 = 0x0000000000001122;
74 QuicheDataWriter writer(2, buffer16, GetParam().endianness);
75 writer.WriteBytesToUInt64(2, in_memory16);
76 test::CompareCharArraysWithHexError(
77 "uint16_t", buffer16, 2,
78 GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian16
79 : little_endian16,
80 2);
81
82 uint64_t read_number16;
83 QuicheDataReader reader(buffer16, 2, GetParam().endianness);
84 reader.ReadBytesToUInt64(2, &read_number16);
85 EXPECT_EQ(in_memory16, read_number16);
86 }
87 }
88
TEST_P(QuicheDataWriterTest,Write24BitUnsignedIntegers)89 TEST_P(QuicheDataWriterTest, Write24BitUnsignedIntegers) {
90 char little_endian24[] = {0x33, 0x22, 0x11};
91 char big_endian24[] = {0x11, 0x22, 0x33};
92 char buffer24[3];
93 uint64_t in_memory24 = 0x0000000000112233;
94 QuicheDataWriter writer(3, buffer24, GetParam().endianness);
95 writer.WriteBytesToUInt64(3, in_memory24);
96 test::CompareCharArraysWithHexError(
97 "uint24", buffer24, 3,
98 GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian24
99 : little_endian24,
100 3);
101
102 uint64_t read_number24;
103 QuicheDataReader reader(buffer24, 3, GetParam().endianness);
104 reader.ReadBytesToUInt64(3, &read_number24);
105 EXPECT_EQ(in_memory24, read_number24);
106 }
107
TEST_P(QuicheDataWriterTest,Write32BitUnsignedIntegers)108 TEST_P(QuicheDataWriterTest, Write32BitUnsignedIntegers) {
109 char little_endian32[] = {0x44, 0x33, 0x22, 0x11};
110 char big_endian32[] = {0x11, 0x22, 0x33, 0x44};
111 char buffer32[4];
112 {
113 uint32_t in_memory32 = 0x11223344;
114 QuicheDataWriter writer(4, buffer32, GetParam().endianness);
115 writer.WriteUInt32(in_memory32);
116 test::CompareCharArraysWithHexError(
117 "uint32_t", buffer32, 4,
118 GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian32
119 : little_endian32,
120 4);
121
122 uint32_t read_number32;
123 QuicheDataReader reader(buffer32, 4, GetParam().endianness);
124 reader.ReadUInt32(&read_number32);
125 EXPECT_EQ(in_memory32, read_number32);
126 }
127
128 {
129 uint64_t in_memory32 = 0x11223344;
130 QuicheDataWriter writer(4, buffer32, GetParam().endianness);
131 writer.WriteBytesToUInt64(4, in_memory32);
132 test::CompareCharArraysWithHexError(
133 "uint32_t", buffer32, 4,
134 GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian32
135 : little_endian32,
136 4);
137
138 uint64_t read_number32;
139 QuicheDataReader reader(buffer32, 4, GetParam().endianness);
140 reader.ReadBytesToUInt64(4, &read_number32);
141 EXPECT_EQ(in_memory32, read_number32);
142 }
143 }
144
TEST_P(QuicheDataWriterTest,Write40BitUnsignedIntegers)145 TEST_P(QuicheDataWriterTest, Write40BitUnsignedIntegers) {
146 uint64_t in_memory40 = 0x0000001122334455;
147 char little_endian40[] = {0x55, 0x44, 0x33, 0x22, 0x11};
148 char big_endian40[] = {0x11, 0x22, 0x33, 0x44, 0x55};
149 char buffer40[5];
150 QuicheDataWriter writer(5, buffer40, GetParam().endianness);
151 writer.WriteBytesToUInt64(5, in_memory40);
152 test::CompareCharArraysWithHexError(
153 "uint40", buffer40, 5,
154 GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian40
155 : little_endian40,
156 5);
157
158 uint64_t read_number40;
159 QuicheDataReader reader(buffer40, 5, GetParam().endianness);
160 reader.ReadBytesToUInt64(5, &read_number40);
161 EXPECT_EQ(in_memory40, read_number40);
162 }
163
TEST_P(QuicheDataWriterTest,Write48BitUnsignedIntegers)164 TEST_P(QuicheDataWriterTest, Write48BitUnsignedIntegers) {
165 uint64_t in_memory48 = 0x0000112233445566;
166 char little_endian48[] = {0x66, 0x55, 0x44, 0x33, 0x22, 0x11};
167 char big_endian48[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
168 char buffer48[6];
169 QuicheDataWriter writer(6, buffer48, GetParam().endianness);
170 writer.WriteBytesToUInt64(6, in_memory48);
171 test::CompareCharArraysWithHexError(
172 "uint48", buffer48, 6,
173 GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian48
174 : little_endian48,
175 6);
176
177 uint64_t read_number48;
178 QuicheDataReader reader(buffer48, 6, GetParam().endianness);
179 reader.ReadBytesToUInt64(6., &read_number48);
180 EXPECT_EQ(in_memory48, read_number48);
181 }
182
TEST_P(QuicheDataWriterTest,Write56BitUnsignedIntegers)183 TEST_P(QuicheDataWriterTest, Write56BitUnsignedIntegers) {
184 uint64_t in_memory56 = 0x0011223344556677;
185 char little_endian56[] = {0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11};
186 char big_endian56[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
187 char buffer56[7];
188 QuicheDataWriter writer(7, buffer56, GetParam().endianness);
189 writer.WriteBytesToUInt64(7, in_memory56);
190 test::CompareCharArraysWithHexError(
191 "uint56", buffer56, 7,
192 GetParam().endianness == quiche::NETWORK_BYTE_ORDER ? big_endian56
193 : little_endian56,
194 7);
195
196 uint64_t read_number56;
197 QuicheDataReader reader(buffer56, 7, GetParam().endianness);
198 reader.ReadBytesToUInt64(7, &read_number56);
199 EXPECT_EQ(in_memory56, read_number56);
200 }
201
TEST_P(QuicheDataWriterTest,Write64BitUnsignedIntegers)202 TEST_P(QuicheDataWriterTest, Write64BitUnsignedIntegers) {
203 uint64_t in_memory64 = 0x1122334455667788;
204 unsigned char little_endian64[] = {0x88, 0x77, 0x66, 0x55,
205 0x44, 0x33, 0x22, 0x11};
206 unsigned char big_endian64[] = {0x11, 0x22, 0x33, 0x44,
207 0x55, 0x66, 0x77, 0x88};
208 char buffer64[8];
209 QuicheDataWriter writer(8, buffer64, GetParam().endianness);
210 writer.WriteBytesToUInt64(8, in_memory64);
211 test::CompareCharArraysWithHexError(
212 "uint64_t", buffer64, 8,
213 GetParam().endianness == quiche::NETWORK_BYTE_ORDER
214 ? AsChars(big_endian64)
215 : AsChars(little_endian64),
216 8);
217
218 uint64_t read_number64;
219 QuicheDataReader reader(buffer64, 8, GetParam().endianness);
220 reader.ReadBytesToUInt64(8, &read_number64);
221 EXPECT_EQ(in_memory64, read_number64);
222
223 QuicheDataWriter writer2(8, buffer64, GetParam().endianness);
224 writer2.WriteUInt64(in_memory64);
225 test::CompareCharArraysWithHexError(
226 "uint64_t", buffer64, 8,
227 GetParam().endianness == quiche::NETWORK_BYTE_ORDER
228 ? AsChars(big_endian64)
229 : AsChars(little_endian64),
230 8);
231 read_number64 = 0u;
232 QuicheDataReader reader2(buffer64, 8, GetParam().endianness);
233 reader2.ReadUInt64(&read_number64);
234 EXPECT_EQ(in_memory64, read_number64);
235 }
236
TEST_P(QuicheDataWriterTest,WriteIntegers)237 TEST_P(QuicheDataWriterTest, WriteIntegers) {
238 char buf[43];
239 uint8_t i8 = 0x01;
240 uint16_t i16 = 0x0123;
241 uint32_t i32 = 0x01234567;
242 uint64_t i64 = 0x0123456789ABCDEF;
243 QuicheDataWriter writer(46, buf, GetParam().endianness);
244 for (size_t i = 0; i < 10; ++i) {
245 switch (i) {
246 case 0u:
247 EXPECT_TRUE(writer.WriteBytesToUInt64(i, i64));
248 break;
249 case 1u:
250 EXPECT_TRUE(writer.WriteUInt8(i8));
251 EXPECT_TRUE(writer.WriteBytesToUInt64(i, i64));
252 break;
253 case 2u:
254 EXPECT_TRUE(writer.WriteUInt16(i16));
255 EXPECT_TRUE(writer.WriteBytesToUInt64(i, i64));
256 break;
257 case 3u:
258 EXPECT_TRUE(writer.WriteBytesToUInt64(i, i64));
259 break;
260 case 4u:
261 EXPECT_TRUE(writer.WriteUInt32(i32));
262 EXPECT_TRUE(writer.WriteBytesToUInt64(i, i64));
263 break;
264 case 5u:
265 case 6u:
266 case 7u:
267 case 8u:
268 EXPECT_TRUE(writer.WriteBytesToUInt64(i, i64));
269 break;
270 default:
271 EXPECT_FALSE(writer.WriteBytesToUInt64(i, i64));
272 }
273 }
274
275 QuicheDataReader reader(buf, 46, GetParam().endianness);
276 for (size_t i = 0; i < 10; ++i) {
277 uint8_t read8;
278 uint16_t read16;
279 uint32_t read32;
280 uint64_t read64;
281 switch (i) {
282 case 0u:
283 EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64));
284 EXPECT_EQ(0u, read64);
285 break;
286 case 1u:
287 EXPECT_TRUE(reader.ReadUInt8(&read8));
288 EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64));
289 EXPECT_EQ(i8, read8);
290 EXPECT_EQ(0xEFu, read64);
291 break;
292 case 2u:
293 EXPECT_TRUE(reader.ReadUInt16(&read16));
294 EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64));
295 EXPECT_EQ(i16, read16);
296 EXPECT_EQ(0xCDEFu, read64);
297 break;
298 case 3u:
299 EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64));
300 EXPECT_EQ(0xABCDEFu, read64);
301 break;
302 case 4u:
303 EXPECT_TRUE(reader.ReadUInt32(&read32));
304 EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64));
305 EXPECT_EQ(i32, read32);
306 EXPECT_EQ(0x89ABCDEFu, read64);
307 break;
308 case 5u:
309 EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64));
310 EXPECT_EQ(0x6789ABCDEFu, read64);
311 break;
312 case 6u:
313 EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64));
314 EXPECT_EQ(0x456789ABCDEFu, read64);
315 break;
316 case 7u:
317 EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64));
318 EXPECT_EQ(0x23456789ABCDEFu, read64);
319 break;
320 case 8u:
321 EXPECT_TRUE(reader.ReadBytesToUInt64(i, &read64));
322 EXPECT_EQ(0x0123456789ABCDEFu, read64);
323 break;
324 default:
325 EXPECT_FALSE(reader.ReadBytesToUInt64(i, &read64));
326 }
327 }
328 }
329
TEST_P(QuicheDataWriterTest,WriteBytes)330 TEST_P(QuicheDataWriterTest, WriteBytes) {
331 char bytes[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
332 char buf[ABSL_ARRAYSIZE(bytes)];
333 QuicheDataWriter writer(ABSL_ARRAYSIZE(buf), buf, GetParam().endianness);
334 EXPECT_TRUE(writer.WriteBytes(bytes, ABSL_ARRAYSIZE(bytes)));
335 for (unsigned int i = 0; i < ABSL_ARRAYSIZE(bytes); ++i) {
336 EXPECT_EQ(bytes[i], buf[i]);
337 }
338 }
339
340 const int kVarIntBufferLength = 1024;
341
342 // Encodes and then decodes a specified value, checks that the
343 // value that was encoded is the same as the decoded value, the length
344 // is correct, and that after decoding, all data in the buffer has
345 // been consumed..
346 // Returns true if everything works, false if not.
EncodeDecodeValue(uint64_t value_in,char * buffer,size_t size_of_buffer)347 bool EncodeDecodeValue(uint64_t value_in, char* buffer, size_t size_of_buffer) {
348 // Init the buffer to all 0, just for cleanliness. Makes for better
349 // output if, in debugging, we need to dump out the buffer.
350 memset(buffer, 0, size_of_buffer);
351 // make a writer. Note that for IETF encoding
352 // we do not care about endianness... It's always big-endian,
353 // but the c'tor expects to be told what endianness is in force...
354 QuicheDataWriter writer(size_of_buffer, buffer,
355 quiche::Endianness::NETWORK_BYTE_ORDER);
356
357 // Try to write the value.
358 if (writer.WriteVarInt62(value_in) != true) {
359 return false;
360 }
361 // Look at the value we encoded. Determine how much should have been
362 // used based on the value, and then check the state of the writer
363 // to see that it matches.
364 size_t expected_length = 0;
365 if (value_in <= 0x3f) {
366 expected_length = 1;
367 } else if (value_in <= 0x3fff) {
368 expected_length = 2;
369 } else if (value_in <= 0x3fffffff) {
370 expected_length = 4;
371 } else {
372 expected_length = 8;
373 }
374 if (writer.length() != expected_length) {
375 return false;
376 }
377
378 // set up a reader, just the length we've used, no more, no less.
379 QuicheDataReader reader(buffer, expected_length,
380 quiche::Endianness::NETWORK_BYTE_ORDER);
381 uint64_t value_out;
382
383 if (reader.ReadVarInt62(&value_out) == false) {
384 return false;
385 }
386 if (value_in != value_out) {
387 return false;
388 }
389 // We only write one value so there had better be nothing left to read
390 return reader.IsDoneReading();
391 }
392
393 // Test that 8-byte-encoded Variable Length Integers are properly laid
394 // out in the buffer.
TEST_P(QuicheDataWriterTest,VarInt8Layout)395 TEST_P(QuicheDataWriterTest, VarInt8Layout) {
396 char buffer[1024];
397
398 // Check that the layout of bytes in the buffer is correct. Bytes
399 // are always encoded big endian...
400 memset(buffer, 0, sizeof(buffer));
401 QuicheDataWriter writer(sizeof(buffer), static_cast<char*>(buffer),
402 quiche::Endianness::NETWORK_BYTE_ORDER);
403 EXPECT_TRUE(writer.WriteVarInt62(UINT64_C(0x3142f3e4d5c6b7a8)));
404 EXPECT_EQ(static_cast<unsigned char>(*(writer.data() + 0)),
405 (0x31 + 0xc0)); // 0xc0 for encoding
406 EXPECT_EQ(static_cast<unsigned char>(*(writer.data() + 1)), 0x42);
407 EXPECT_EQ(static_cast<unsigned char>(*(writer.data() + 2)), 0xf3);
408 EXPECT_EQ(static_cast<unsigned char>(*(writer.data() + 3)), 0xe4);
409 EXPECT_EQ(static_cast<unsigned char>(*(writer.data() + 4)), 0xd5);
410 EXPECT_EQ(static_cast<unsigned char>(*(writer.data() + 5)), 0xc6);
411 EXPECT_EQ(static_cast<unsigned char>(*(writer.data() + 6)), 0xb7);
412 EXPECT_EQ(static_cast<unsigned char>(*(writer.data() + 7)), 0xa8);
413 }
414
415 // Test that 4-byte-encoded Variable Length Integers are properly laid
416 // out in the buffer.
TEST_P(QuicheDataWriterTest,VarInt4Layout)417 TEST_P(QuicheDataWriterTest, VarInt4Layout) {
418 char buffer[1024];
419
420 // Check that the layout of bytes in the buffer is correct. Bytes
421 // are always encoded big endian...
422 memset(buffer, 0, sizeof(buffer));
423 QuicheDataWriter writer(sizeof(buffer), static_cast<char*>(buffer),
424 quiche::Endianness::NETWORK_BYTE_ORDER);
425 EXPECT_TRUE(writer.WriteVarInt62(0x3243f4e5));
426 EXPECT_EQ(static_cast<unsigned char>(*(writer.data() + 0)),
427 (0x32 + 0x80)); // 0x80 for encoding
428 EXPECT_EQ(static_cast<unsigned char>(*(writer.data() + 1)), 0x43);
429 EXPECT_EQ(static_cast<unsigned char>(*(writer.data() + 2)), 0xf4);
430 EXPECT_EQ(static_cast<unsigned char>(*(writer.data() + 3)), 0xe5);
431 }
432
433 // Test that 2-byte-encoded Variable Length Integers are properly laid
434 // out in the buffer.
TEST_P(QuicheDataWriterTest,VarInt2Layout)435 TEST_P(QuicheDataWriterTest, VarInt2Layout) {
436 char buffer[1024];
437
438 // Check that the layout of bytes in the buffer is correct. Bytes
439 // are always encoded big endian...
440 memset(buffer, 0, sizeof(buffer));
441 QuicheDataWriter writer(sizeof(buffer), static_cast<char*>(buffer),
442 quiche::Endianness::NETWORK_BYTE_ORDER);
443 EXPECT_TRUE(writer.WriteVarInt62(0x3647));
444 EXPECT_EQ(static_cast<unsigned char>(*(writer.data() + 0)),
445 (0x36 + 0x40)); // 0x40 for encoding
446 EXPECT_EQ(static_cast<unsigned char>(*(writer.data() + 1)), 0x47);
447 }
448
449 // Test that 1-byte-encoded Variable Length Integers are properly laid
450 // out in the buffer.
TEST_P(QuicheDataWriterTest,VarInt1Layout)451 TEST_P(QuicheDataWriterTest, VarInt1Layout) {
452 char buffer[1024];
453
454 // Check that the layout of bytes in the buffer
455 // is correct. Bytes are always encoded big endian...
456 memset(buffer, 0, sizeof(buffer));
457 QuicheDataWriter writer(sizeof(buffer), static_cast<char*>(buffer),
458 quiche::Endianness::NETWORK_BYTE_ORDER);
459 EXPECT_TRUE(writer.WriteVarInt62(0x3f));
460 EXPECT_EQ(static_cast<unsigned char>(*(writer.data() + 0)), 0x3f);
461 }
462
463 // Test certain, targeted, values that are expected to succeed:
464 // 0, 1,
465 // 0x3e, 0x3f, 0x40, 0x41 (around the 1-2 byte transitions)
466 // 0x3ffe, 0x3fff, 0x4000, 0x4001 (the 2-4 byte transition)
467 // 0x3ffffffe, 0x3fffffff, 0x40000000, 0x40000001 (the 4-8 byte
468 // transition)
469 // 0x3ffffffffffffffe, 0x3fffffffffffffff, (the highest valid values)
470 // 0xfe, 0xff, 0x100, 0x101,
471 // 0xfffe, 0xffff, 0x10000, 0x10001,
472 // 0xfffffe, 0xffffff, 0x1000000, 0x1000001,
473 // 0xfffffffe, 0xffffffff, 0x100000000, 0x100000001,
474 // 0xfffffffffe, 0xffffffffff, 0x10000000000, 0x10000000001,
475 // 0xfffffffffffe, 0xffffffffffff, 0x1000000000000, 0x1000000000001,
476 // 0xfffffffffffffe, 0xffffffffffffff, 0x100000000000000, 0x100000000000001,
TEST_P(QuicheDataWriterTest,VarIntGoodTargetedValues)477 TEST_P(QuicheDataWriterTest, VarIntGoodTargetedValues) {
478 char buffer[kVarIntBufferLength];
479 uint64_t passing_values[] = {
480 0,
481 1,
482 0x3e,
483 0x3f,
484 0x40,
485 0x41,
486 0x3ffe,
487 0x3fff,
488 0x4000,
489 0x4001,
490 0x3ffffffe,
491 0x3fffffff,
492 0x40000000,
493 0x40000001,
494 0x3ffffffffffffffe,
495 0x3fffffffffffffff,
496 0xfe,
497 0xff,
498 0x100,
499 0x101,
500 0xfffe,
501 0xffff,
502 0x10000,
503 0x10001,
504 0xfffffe,
505 0xffffff,
506 0x1000000,
507 0x1000001,
508 0xfffffffe,
509 0xffffffff,
510 0x100000000,
511 0x100000001,
512 0xfffffffffe,
513 0xffffffffff,
514 0x10000000000,
515 0x10000000001,
516 0xfffffffffffe,
517 0xffffffffffff,
518 0x1000000000000,
519 0x1000000000001,
520 0xfffffffffffffe,
521 0xffffffffffffff,
522 0x100000000000000,
523 0x100000000000001,
524 };
525 for (uint64_t test_val : passing_values) {
526 EXPECT_TRUE(
527 EncodeDecodeValue(test_val, static_cast<char*>(buffer), sizeof(buffer)))
528 << " encode/decode of " << test_val << " failed";
529 }
530 }
531 //
532 // Test certain, targeted, values where failure is expected (the
533 // values are invalid w.r.t. IETF VarInt encoding):
534 // 0x4000000000000000, 0x4000000000000001, ( Just above max allowed value)
535 // 0xfffffffffffffffe, 0xffffffffffffffff, (should fail)
TEST_P(QuicheDataWriterTest,VarIntBadTargetedValues)536 TEST_P(QuicheDataWriterTest, VarIntBadTargetedValues) {
537 char buffer[kVarIntBufferLength];
538 uint64_t failing_values[] = {
539 0x4000000000000000,
540 0x4000000000000001,
541 0xfffffffffffffffe,
542 0xffffffffffffffff,
543 };
544 for (uint64_t test_val : failing_values) {
545 EXPECT_FALSE(
546 EncodeDecodeValue(test_val, static_cast<char*>(buffer), sizeof(buffer)))
547 << " encode/decode of " << test_val << " succeeded, but was an "
548 << "invalid value";
549 }
550 }
551 // Test writing varints with a forced length.
TEST_P(QuicheDataWriterTest,WriteVarInt62WithForcedLength)552 TEST_P(QuicheDataWriterTest, WriteVarInt62WithForcedLength) {
553 char buffer[90];
554 memset(buffer, 0, sizeof(buffer));
555 QuicheDataWriter writer(sizeof(buffer), static_cast<char*>(buffer));
556
557 writer.WriteVarInt62WithForcedLength(1, VARIABLE_LENGTH_INTEGER_LENGTH_1);
558 writer.WriteVarInt62WithForcedLength(1, VARIABLE_LENGTH_INTEGER_LENGTH_2);
559 writer.WriteVarInt62WithForcedLength(1, VARIABLE_LENGTH_INTEGER_LENGTH_4);
560 writer.WriteVarInt62WithForcedLength(1, VARIABLE_LENGTH_INTEGER_LENGTH_8);
561
562 writer.WriteVarInt62WithForcedLength(63, VARIABLE_LENGTH_INTEGER_LENGTH_1);
563 writer.WriteVarInt62WithForcedLength(63, VARIABLE_LENGTH_INTEGER_LENGTH_2);
564 writer.WriteVarInt62WithForcedLength(63, VARIABLE_LENGTH_INTEGER_LENGTH_4);
565 writer.WriteVarInt62WithForcedLength(63, VARIABLE_LENGTH_INTEGER_LENGTH_8);
566
567 writer.WriteVarInt62WithForcedLength(64, VARIABLE_LENGTH_INTEGER_LENGTH_2);
568 writer.WriteVarInt62WithForcedLength(64, VARIABLE_LENGTH_INTEGER_LENGTH_4);
569 writer.WriteVarInt62WithForcedLength(64, VARIABLE_LENGTH_INTEGER_LENGTH_8);
570
571 writer.WriteVarInt62WithForcedLength(16383, VARIABLE_LENGTH_INTEGER_LENGTH_2);
572 writer.WriteVarInt62WithForcedLength(16383, VARIABLE_LENGTH_INTEGER_LENGTH_4);
573 writer.WriteVarInt62WithForcedLength(16383, VARIABLE_LENGTH_INTEGER_LENGTH_8);
574
575 writer.WriteVarInt62WithForcedLength(16384, VARIABLE_LENGTH_INTEGER_LENGTH_4);
576 writer.WriteVarInt62WithForcedLength(16384, VARIABLE_LENGTH_INTEGER_LENGTH_8);
577
578 writer.WriteVarInt62WithForcedLength(1073741823,
579 VARIABLE_LENGTH_INTEGER_LENGTH_4);
580 writer.WriteVarInt62WithForcedLength(1073741823,
581 VARIABLE_LENGTH_INTEGER_LENGTH_8);
582
583 writer.WriteVarInt62WithForcedLength(1073741824,
584 VARIABLE_LENGTH_INTEGER_LENGTH_8);
585
586 QuicheDataReader reader(buffer, sizeof(buffer));
587
588 uint64_t test_val = 0;
589 for (int i = 0; i < 4; ++i) {
590 EXPECT_TRUE(reader.ReadVarInt62(&test_val));
591 EXPECT_EQ(test_val, 1u);
592 }
593 for (int i = 0; i < 4; ++i) {
594 EXPECT_TRUE(reader.ReadVarInt62(&test_val));
595 EXPECT_EQ(test_val, 63u);
596 }
597
598 for (int i = 0; i < 3; ++i) {
599 EXPECT_TRUE(reader.ReadVarInt62(&test_val));
600 EXPECT_EQ(test_val, 64u);
601 }
602 for (int i = 0; i < 3; ++i) {
603 EXPECT_TRUE(reader.ReadVarInt62(&test_val));
604 EXPECT_EQ(test_val, 16383u);
605 }
606
607 for (int i = 0; i < 2; ++i) {
608 EXPECT_TRUE(reader.ReadVarInt62(&test_val));
609 EXPECT_EQ(test_val, 16384u);
610 }
611 for (int i = 0; i < 2; ++i) {
612 EXPECT_TRUE(reader.ReadVarInt62(&test_val));
613 EXPECT_EQ(test_val, 1073741823u);
614 }
615
616 EXPECT_TRUE(reader.ReadVarInt62(&test_val));
617 EXPECT_EQ(test_val, 1073741824u);
618
619 // We are at the end of the buffer so this should fail.
620 EXPECT_FALSE(reader.ReadVarInt62(&test_val));
621 }
622
623 // Following tests all try to fill the buffer with multiple values,
624 // go one value more than the buffer can accommodate, then read
625 // the successfully encoded values, and try to read the unsuccessfully
626 // encoded value. The following is the number of values to encode.
627 const int kMultiVarCount = 1000;
628
629 // Test writing & reading multiple 8-byte-encoded varints
TEST_P(QuicheDataWriterTest,MultiVarInt8)630 TEST_P(QuicheDataWriterTest, MultiVarInt8) {
631 uint64_t test_val;
632 char buffer[8 * kMultiVarCount];
633 memset(buffer, 0, sizeof(buffer));
634 QuicheDataWriter writer(sizeof(buffer), static_cast<char*>(buffer),
635 quiche::Endianness::NETWORK_BYTE_ORDER);
636 // Put N values into the buffer. Adding i to the value ensures that
637 // each value is different so we can detect if we overwrite values,
638 // or read the same value over and over.
639 for (int i = 0; i < kMultiVarCount; i++) {
640 EXPECT_TRUE(writer.WriteVarInt62(UINT64_C(0x3142f3e4d5c6b7a8) + i));
641 }
642 EXPECT_EQ(writer.length(), 8u * kMultiVarCount);
643
644 // N+1st should fail, the buffer is full.
645 EXPECT_FALSE(writer.WriteVarInt62(UINT64_C(0x3142f3e4d5c6b7a8)));
646
647 // Now we should be able to read out the N values that were
648 // successfully encoded.
649 QuicheDataReader reader(buffer, sizeof(buffer),
650 quiche::Endianness::NETWORK_BYTE_ORDER);
651 for (int i = 0; i < kMultiVarCount; i++) {
652 EXPECT_TRUE(reader.ReadVarInt62(&test_val));
653 EXPECT_EQ(test_val, (UINT64_C(0x3142f3e4d5c6b7a8) + i));
654 }
655 // And the N+1st should fail.
656 EXPECT_FALSE(reader.ReadVarInt62(&test_val));
657 }
658
659 // Test writing & reading multiple 4-byte-encoded varints
TEST_P(QuicheDataWriterTest,MultiVarInt4)660 TEST_P(QuicheDataWriterTest, MultiVarInt4) {
661 uint64_t test_val;
662 char buffer[4 * kMultiVarCount];
663 memset(buffer, 0, sizeof(buffer));
664 QuicheDataWriter writer(sizeof(buffer), static_cast<char*>(buffer),
665 quiche::Endianness::NETWORK_BYTE_ORDER);
666 // Put N values into the buffer. Adding i to the value ensures that
667 // each value is different so we can detect if we overwrite values,
668 // or read the same value over and over.
669 for (int i = 0; i < kMultiVarCount; i++) {
670 EXPECT_TRUE(writer.WriteVarInt62(UINT64_C(0x3142f3e4) + i));
671 }
672 EXPECT_EQ(writer.length(), 4u * kMultiVarCount);
673
674 // N+1st should fail, the buffer is full.
675 EXPECT_FALSE(writer.WriteVarInt62(UINT64_C(0x3142f3e4)));
676
677 // Now we should be able to read out the N values that were
678 // successfully encoded.
679 QuicheDataReader reader(buffer, sizeof(buffer),
680 quiche::Endianness::NETWORK_BYTE_ORDER);
681 for (int i = 0; i < kMultiVarCount; i++) {
682 EXPECT_TRUE(reader.ReadVarInt62(&test_val));
683 EXPECT_EQ(test_val, (UINT64_C(0x3142f3e4) + i));
684 }
685 // And the N+1st should fail.
686 EXPECT_FALSE(reader.ReadVarInt62(&test_val));
687 }
688
689 // Test writing & reading multiple 2-byte-encoded varints
TEST_P(QuicheDataWriterTest,MultiVarInt2)690 TEST_P(QuicheDataWriterTest, MultiVarInt2) {
691 uint64_t test_val;
692 char buffer[2 * kMultiVarCount];
693 memset(buffer, 0, sizeof(buffer));
694 QuicheDataWriter writer(sizeof(buffer), static_cast<char*>(buffer),
695 quiche::Endianness::NETWORK_BYTE_ORDER);
696 // Put N values into the buffer. Adding i to the value ensures that
697 // each value is different so we can detect if we overwrite values,
698 // or read the same value over and over.
699 for (int i = 0; i < kMultiVarCount; i++) {
700 EXPECT_TRUE(writer.WriteVarInt62(UINT64_C(0x3142) + i));
701 }
702 EXPECT_EQ(writer.length(), 2u * kMultiVarCount);
703
704 // N+1st should fail, the buffer is full.
705 EXPECT_FALSE(writer.WriteVarInt62(UINT64_C(0x3142)));
706
707 // Now we should be able to read out the N values that were
708 // successfully encoded.
709 QuicheDataReader reader(buffer, sizeof(buffer),
710 quiche::Endianness::NETWORK_BYTE_ORDER);
711 for (int i = 0; i < kMultiVarCount; i++) {
712 EXPECT_TRUE(reader.ReadVarInt62(&test_val));
713 EXPECT_EQ(test_val, (UINT64_C(0x3142) + i));
714 }
715 // And the N+1st should fail.
716 EXPECT_FALSE(reader.ReadVarInt62(&test_val));
717 }
718
719 // Test writing & reading multiple 1-byte-encoded varints
TEST_P(QuicheDataWriterTest,MultiVarInt1)720 TEST_P(QuicheDataWriterTest, MultiVarInt1) {
721 uint64_t test_val;
722 char buffer[1 * kMultiVarCount];
723 memset(buffer, 0, sizeof(buffer));
724 QuicheDataWriter writer(sizeof(buffer), static_cast<char*>(buffer),
725 quiche::Endianness::NETWORK_BYTE_ORDER);
726 // Put N values into the buffer. Adding i to the value ensures that
727 // each value is different so we can detect if we overwrite values,
728 // or read the same value over and over. &0xf ensures we do not
729 // overflow the max value for single-byte encoding.
730 for (int i = 0; i < kMultiVarCount; i++) {
731 EXPECT_TRUE(writer.WriteVarInt62(UINT64_C(0x30) + (i & 0xf)));
732 }
733 EXPECT_EQ(writer.length(), 1u * kMultiVarCount);
734
735 // N+1st should fail, the buffer is full.
736 EXPECT_FALSE(writer.WriteVarInt62(UINT64_C(0x31)));
737
738 // Now we should be able to read out the N values that were
739 // successfully encoded.
740 QuicheDataReader reader(buffer, sizeof(buffer),
741 quiche::Endianness::NETWORK_BYTE_ORDER);
742 for (int i = 0; i < kMultiVarCount; i++) {
743 EXPECT_TRUE(reader.ReadVarInt62(&test_val));
744 EXPECT_EQ(test_val, (UINT64_C(0x30) + (i & 0xf)));
745 }
746 // And the N+1st should fail.
747 EXPECT_FALSE(reader.ReadVarInt62(&test_val));
748 }
749
TEST_P(QuicheDataWriterTest,Seek)750 TEST_P(QuicheDataWriterTest, Seek) {
751 char buffer[3] = {};
752 QuicheDataWriter writer(ABSL_ARRAYSIZE(buffer), buffer,
753 GetParam().endianness);
754 EXPECT_TRUE(writer.WriteUInt8(42));
755 EXPECT_TRUE(writer.Seek(1));
756 EXPECT_TRUE(writer.WriteUInt8(3));
757
758 char expected[] = {42, 0, 3};
759 for (size_t i = 0; i < ABSL_ARRAYSIZE(expected); ++i) {
760 EXPECT_EQ(buffer[i], expected[i]);
761 }
762 }
763
TEST_P(QuicheDataWriterTest,SeekTooFarFails)764 TEST_P(QuicheDataWriterTest, SeekTooFarFails) {
765 char buffer[20];
766
767 // Check that one can seek to the end of the writer, but not past.
768 {
769 QuicheDataWriter writer(ABSL_ARRAYSIZE(buffer), buffer,
770 GetParam().endianness);
771 EXPECT_TRUE(writer.Seek(20));
772 EXPECT_FALSE(writer.Seek(1));
773 }
774
775 // Seeking several bytes past the end fails.
776 {
777 QuicheDataWriter writer(ABSL_ARRAYSIZE(buffer), buffer,
778 GetParam().endianness);
779 EXPECT_FALSE(writer.Seek(100));
780 }
781
782 // Seeking so far that arithmetic overflow could occur also fails.
783 {
784 QuicheDataWriter writer(ABSL_ARRAYSIZE(buffer), buffer,
785 GetParam().endianness);
786 EXPECT_TRUE(writer.Seek(10));
787 EXPECT_FALSE(writer.Seek(std::numeric_limits<size_t>::max()));
788 }
789 }
790
TEST_P(QuicheDataWriterTest,PayloadReads)791 TEST_P(QuicheDataWriterTest, PayloadReads) {
792 char buffer[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
793 char expected_first_read[4] = {1, 2, 3, 4};
794 char expected_remaining[12] = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
795 QuicheDataReader reader(buffer, sizeof(buffer));
796 absl::string_view previously_read_payload1 = reader.PreviouslyReadPayload();
797 EXPECT_TRUE(previously_read_payload1.empty());
798 char first_read_buffer[4] = {};
799 EXPECT_TRUE(reader.ReadBytes(first_read_buffer, sizeof(first_read_buffer)));
800 test::CompareCharArraysWithHexError(
801 "first read", first_read_buffer, sizeof(first_read_buffer),
802 expected_first_read, sizeof(expected_first_read));
803 absl::string_view peeked_remaining_payload = reader.PeekRemainingPayload();
804 test::CompareCharArraysWithHexError(
805 "peeked_remaining_payload", peeked_remaining_payload.data(),
806 peeked_remaining_payload.length(), expected_remaining,
807 sizeof(expected_remaining));
808 absl::string_view full_payload = reader.FullPayload();
809 test::CompareCharArraysWithHexError("full_payload", full_payload.data(),
810 full_payload.length(), buffer,
811 sizeof(buffer));
812 absl::string_view previously_read_payload2 = reader.PreviouslyReadPayload();
813 test::CompareCharArraysWithHexError(
814 "previously_read_payload2", previously_read_payload2.data(),
815 previously_read_payload2.length(), first_read_buffer,
816 sizeof(first_read_buffer));
817 absl::string_view read_remaining_payload = reader.ReadRemainingPayload();
818 test::CompareCharArraysWithHexError(
819 "read_remaining_payload", read_remaining_payload.data(),
820 read_remaining_payload.length(), expected_remaining,
821 sizeof(expected_remaining));
822 EXPECT_TRUE(reader.IsDoneReading());
823 absl::string_view full_payload2 = reader.FullPayload();
824 test::CompareCharArraysWithHexError("full_payload2", full_payload2.data(),
825 full_payload2.length(), buffer,
826 sizeof(buffer));
827 absl::string_view previously_read_payload3 = reader.PreviouslyReadPayload();
828 test::CompareCharArraysWithHexError(
829 "previously_read_payload3", previously_read_payload3.data(),
830 previously_read_payload3.length(), buffer, sizeof(buffer));
831 }
832
833 } // namespace
834 } // namespace test
835 } // namespace quiche
836