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