1 // Copyright 2017 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 "components/cbor/writer.h"
6 
7 #include <limits>
8 #include <string>
9 
10 #include "base/stl_util.h"
11 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 
14 /* Leveraging RFC 7049 examples from
15    https://github.com/cbor/test-vectors/blob/master/appendix_a.json. */
16 namespace cbor {
17 
TEST(CBORWriterTest,TestWriteUint)18 TEST(CBORWriterTest, TestWriteUint) {
19   struct UintTestCase {
20     const int64_t value;
21     const base::StringPiece cbor;
22   };
23 
24   static const UintTestCase kUintTestCases[] = {
25       // Reminder: must specify length when creating string pieces
26       // with null bytes, else the string will truncate prematurely.
27       {0, base::StringPiece("\x00", 1)},
28       {1, base::StringPiece("\x01")},
29       {10, base::StringPiece("\x0a")},
30       {23, base::StringPiece("\x17")},
31       {24, base::StringPiece("\x18\x18")},
32       {25, base::StringPiece("\x18\x19")},
33       {100, base::StringPiece("\x18\x64")},
34       {1000, base::StringPiece("\x19\x03\xe8")},
35       {1000000, base::StringPiece("\x1a\x00\x0f\x42\x40", 5)},
36       {0xFFFFFFFF, base::StringPiece("\x1a\xff\xff\xff\xff")},
37       {0x100000000,
38        base::StringPiece("\x1b\x00\x00\x00\x01\x00\x00\x00\x00", 9)},
39       {std::numeric_limits<int64_t>::max(),
40        base::StringPiece("\x1b\x7f\xff\xff\xff\xff\xff\xff\xff")}};
41 
42   for (const UintTestCase& test_case : kUintTestCases) {
43     auto cbor = Writer::Write(Value(test_case.value));
44     ASSERT_TRUE(cbor.has_value());
45     EXPECT_THAT(cbor.value(), testing::ElementsAreArray(test_case.cbor));
46   }
47 }
48 
TEST(CBORWriterTest,TestWriteNegativeInteger)49 TEST(CBORWriterTest, TestWriteNegativeInteger) {
50   static const struct {
51     const int64_t negative_int;
52     const base::StringPiece cbor;
53   } kNegativeIntTestCases[] = {
54       {-1LL, base::StringPiece("\x20")},
55       {-10LL, base::StringPiece("\x29")},
56       {-23LL, base::StringPiece("\x36")},
57       {-24LL, base::StringPiece("\x37")},
58       {-25LL, base::StringPiece("\x38\x18")},
59       {-100LL, base::StringPiece("\x38\x63")},
60       {-1000LL, base::StringPiece("\x39\x03\xe7")},
61       {-4294967296LL, base::StringPiece("\x3a\xff\xff\xff\xff")},
62       {-4294967297LL,
63        base::StringPiece("\x3b\x00\x00\x00\x01\x00\x00\x00\x00", 9)},
64       {std::numeric_limits<int64_t>::min(),
65        base::StringPiece("\x3b\x7f\xff\xff\xff\xff\xff\xff\xff")},
66   };
67 
68   for (const auto& test_case : kNegativeIntTestCases) {
69     SCOPED_TRACE(testing::Message() << "testing  negative int at index: "
70                                     << test_case.negative_int);
71 
72     auto cbor = Writer::Write(Value(test_case.negative_int));
73     ASSERT_TRUE(cbor.has_value());
74     EXPECT_THAT(cbor.value(), testing::ElementsAreArray(test_case.cbor));
75   }
76 }
77 
TEST(CBORWriterTest,TestWriteBytes)78 TEST(CBORWriterTest, TestWriteBytes) {
79   struct BytesTestCase {
80     const std::vector<uint8_t> bytes;
81     const base::StringPiece cbor;
82   };
83 
84   static const BytesTestCase kBytesTestCases[] = {
85       {{}, base::StringPiece("\x40")},
86       {{0x01, 0x02, 0x03, 0x04}, base::StringPiece("\x44\x01\x02\x03\x04")},
87   };
88 
89   for (const BytesTestCase& test_case : kBytesTestCases) {
90     auto cbor = Writer::Write(Value(test_case.bytes));
91     ASSERT_TRUE(cbor.has_value());
92     EXPECT_THAT(cbor.value(), testing::ElementsAreArray(test_case.cbor));
93   }
94 }
95 
TEST(CBORWriterTest,TestWriteString)96 TEST(CBORWriterTest, TestWriteString) {
97   struct StringTestCase {
98     const std::string string;
99     const base::StringPiece cbor;
100   };
101 
102   static const StringTestCase kStringTestCases[] = {
103       {"", base::StringPiece("\x60")},
104       {"a", base::StringPiece("\x61\x61")},
105       {"IETF", base::StringPiece("\x64\x49\x45\x54\x46")},
106       {"\"\\", base::StringPiece("\x62\x22\x5c")},
107       {"\xc3\xbc", base::StringPiece("\x62\xc3\xbc")},
108       {"\xe6\xb0\xb4", base::StringPiece("\x63\xe6\xb0\xb4")},
109       {"\xf0\x90\x85\x91", base::StringPiece("\x64\xf0\x90\x85\x91")}};
110 
111   for (const StringTestCase& test_case : kStringTestCases) {
112     SCOPED_TRACE(testing::Message()
113                  << "testing encoding string : " << test_case.string);
114 
115     auto cbor = Writer::Write(Value(test_case.string));
116     ASSERT_TRUE(cbor.has_value());
117     EXPECT_THAT(cbor.value(), testing::ElementsAreArray(test_case.cbor));
118   }
119 }
120 
TEST(CBORWriterTest,TestWriteArray)121 TEST(CBORWriterTest, TestWriteArray) {
122   static const uint8_t kArrayTestCaseCbor[] = {
123       // clang-format off
124       0x98, 0x19,  // array of 25 elements
125         0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
126         0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
127         0x18, 0x18, 0x19,
128       // clang-format on
129   };
130   std::vector<Value> array;
131   for (int64_t i = 1; i <= 25; i++) {
132     array.push_back(Value(i));
133   }
134   auto cbor = Writer::Write(Value(array));
135   ASSERT_TRUE(cbor.has_value());
136   EXPECT_THAT(cbor.value(),
137               testing::ElementsAreArray(kArrayTestCaseCbor,
138                                         base::size(kArrayTestCaseCbor)));
139 }
140 
TEST(CBORWriterTest,TestWriteMap)141 TEST(CBORWriterTest, TestWriteMap) {
142   static const uint8_t kMapTestCaseCbor[] = {
143       // clang-format off
144       0xb8, 0x19, // map of 25 pairs:
145         0x00,          // key 0
146         0x61, 0x61,    // value "a"
147 
148         0x17,          // key 23
149         0x61,  0x62,   // value "b"
150 
151         0x18, 0x18,    // key 24
152         0x61, 0x63,  // value "c"
153 
154         0x18, 0xFF,        // key 255
155         0x61,  0x64,       // value "d"
156 
157         0x19, 0x01, 0x00,  // key 256
158         0x61, 0x65,        // value "e"
159 
160         0x19, 0xFF, 0xFF,  // key 65535
161         0x61,  0x66,       // value "f"
162 
163         0x1A, 0x00, 0x01, 0x00, 0x00,   // key 65536
164         0x61, 0x67,                     // value "g"
165 
166         0x1A, 0xFF, 0xFF, 0xFF, 0xFF,   // key 4294967295
167         0x61, 0x68,                     // value "h"
168 
169         // key 4294967296
170         0x1B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
171         0x61, 0x69,  //  value "i"
172 
173         // key INT64_MAX
174         0x1b, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
175         0x61, 0x6a,  //  value "j"
176 
177         0x20,          // key -1
178         0x61, 0x6b,    // value "k"
179 
180         0x37,          // key -24
181         0x61,  0x6c,   // value "l"
182 
183         0x38, 0x18,    // key -25
184         0x61, 0x6d,  // value "m"
185 
186         0x38, 0xFF,        // key -256
187         0x61, 0x6e,       // value "n"
188 
189         0x39, 0x01, 0x00,  // key -257
190         0x61, 0x6f,        // value "o"
191 
192         0x3A, 0x00, 0x01, 0x00, 0x00,   // key -65537
193         0x61, 0x70,                     // value "p"
194 
195         0x3A, 0xFF, 0xFF, 0xFF, 0xFF,   // key -4294967296
196         0x61, 0x71,                     // value "q"
197 
198         // key -4294967297
199         0x3B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
200         0x61, 0x72,  //  value "r"
201 
202         // key INT64_MIN
203         0x3b, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
204         0x61, 0x73,  //  value "s"
205 
206         0x41, 'a', // byte string "a"
207         0x02,
208 
209         0x43, 'b', 'a', 'r', // byte string "bar"
210         0x03,
211 
212         0x43, 'f', 'o', 'o', // byte string "foo"
213         0x04,
214 
215         0x60,        // key ""
216         0x61, 0x2e,  // value "."
217 
218         0x61, 0x65,  // key "e"
219         0x61, 0x45,  // value "E"
220 
221         0x62, 0x61, 0x61,  // key "aa"
222         0x62, 0x41, 0x41,  // value "AA"
223       // clang-format on
224   };
225   Value::MapValue map;
226   // Shorter strings sort first in CTAP, thus the “aa” value should be
227   // serialised last in the map.
228   map[Value("aa")] = Value("AA");
229   map[Value("e")] = Value("E");
230   // The empty string is shorter than all others, so should appear first among
231   // the strings.
232   map[Value("")] = Value(".");
233   // Map keys are sorted by major type, by byte length, and then by
234   // byte-wise lexical order. So all integer type keys should appear before
235   // key "" and all positive integer keys should appear before negative integer
236   // keys.
237   map[Value(-1)] = Value("k");
238   map[Value(-24)] = Value("l");
239   map[Value(-25)] = Value("m");
240   map[Value(-256)] = Value("n");
241   map[Value(-257)] = Value("o");
242   map[Value(-65537)] = Value("p");
243   map[Value(int64_t(-4294967296))] = Value("q");
244   map[Value(int64_t(-4294967297))] = Value("r");
245   map[Value(std::numeric_limits<int64_t>::min())] = Value("s");
246   map[Value(Value::BinaryValue{'a'})] = Value(2);
247   map[Value(Value::BinaryValue{'b', 'a', 'r'})] = Value(3);
248   map[Value(Value::BinaryValue{'f', 'o', 'o'})] = Value(4);
249   map[Value(0)] = Value("a");
250   map[Value(23)] = Value("b");
251   map[Value(24)] = Value("c");
252   map[Value(std::numeric_limits<uint8_t>::max())] = Value("d");
253   map[Value(256)] = Value("e");
254   map[Value(std::numeric_limits<uint16_t>::max())] = Value("f");
255   map[Value(65536)] = Value("g");
256   map[Value(int64_t(std::numeric_limits<uint32_t>::max()))] = Value("h");
257   map[Value(int64_t(4294967296))] = Value("i");
258   map[Value(std::numeric_limits<int64_t>::max())] = Value("j");
259   auto cbor = Writer::Write(Value(map));
260   ASSERT_TRUE(cbor.has_value());
261   EXPECT_THAT(cbor.value(),
262               testing::ElementsAreArray(kMapTestCaseCbor,
263                                         base::size(kMapTestCaseCbor)));
264 }
265 
TEST(CBORWriterTest,TestWriteMapWithArray)266 TEST(CBORWriterTest, TestWriteMapWithArray) {
267   static const uint8_t kMapArrayTestCaseCbor[] = {
268       // clang-format off
269       0xa2,  // map of 2 pairs
270         0x61, 0x61,  // "a"
271         0x01,
272 
273         0x61, 0x62,  // "b"
274         0x82,        // array with 2 elements
275           0x02,
276           0x03,
277       // clang-format on
278   };
279   Value::MapValue map;
280   map[Value("a")] = Value(1);
281   Value::ArrayValue array;
282   array.push_back(Value(2));
283   array.push_back(Value(3));
284   map[Value("b")] = Value(array);
285   auto cbor = Writer::Write(Value(map));
286   ASSERT_TRUE(cbor.has_value());
287   EXPECT_THAT(cbor.value(),
288               testing::ElementsAreArray(kMapArrayTestCaseCbor,
289                                         base::size(kMapArrayTestCaseCbor)));
290 }
291 
TEST(CBORWriterTest,TestWriteNestedMap)292 TEST(CBORWriterTest, TestWriteNestedMap) {
293   static const uint8_t kNestedMapTestCase[] = {
294       // clang-format off
295       0xa2,  // map of 2 pairs
296         0x61, 0x61,  // "a"
297         0x01,
298 
299         0x61, 0x62,  // "b"
300         0xa2,        // map of 2 pairs
301           0x61, 0x63,  // "c"
302           0x02,
303 
304           0x61, 0x64,  // "d"
305           0x03,
306       // clang-format on
307   };
308   Value::MapValue map;
309   map[Value("a")] = Value(1);
310   Value::MapValue nested_map;
311   nested_map[Value("c")] = Value(2);
312   nested_map[Value("d")] = Value(3);
313   map[Value("b")] = Value(nested_map);
314   auto cbor = Writer::Write(Value(map));
315   ASSERT_TRUE(cbor.has_value());
316   EXPECT_THAT(cbor.value(),
317               testing::ElementsAreArray(kNestedMapTestCase,
318                                         base::size(kNestedMapTestCase)));
319 }
320 
TEST(CBORWriterTest,TestSignedExchangeExample)321 TEST(CBORWriterTest, TestSignedExchangeExample) {
322   // Example adopted from:
323   // https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html
324   static const uint8_t kSignedExchangeExample[] = {
325       // clang-format off
326       0xa5, // map of 5 pairs
327         0x0a, // 10
328         0x01,
329 
330         0x18, 0x64, // 100
331         0x02,
332 
333         0x20, // -1
334         0x03,
335 
336         0x61, 'z', // text string "z"
337         0x04,
338 
339         0x62, 'a', 'a', // text string "aa"
340         0x05,
341 
342       /*
343         0x81, 0x18, 0x64, // [100] (array as map key is not yet supported)
344         0x06,
345 
346         0x81, 0x20,  // [-1] (array as map key is not yet supported)
347         0x07,
348 
349         0xf4, // false (boolean  as map key is not yet supported)
350         0x08,
351       */
352       // clang-format on
353   };
354   Value::MapValue map;
355   map[Value(10)] = Value(1);
356   map[Value(100)] = Value(2);
357   map[Value(-1)] = Value(3);
358   map[Value("z")] = Value(4);
359   map[Value("aa")] = Value(5);
360 
361   auto cbor = Writer::Write(Value(map));
362   ASSERT_TRUE(cbor.has_value());
363   EXPECT_THAT(cbor.value(),
364               testing::ElementsAreArray(kSignedExchangeExample,
365                                         base::size(kSignedExchangeExample)));
366 }
367 
TEST(CBORWriterTest,TestWriteSimpleValue)368 TEST(CBORWriterTest, TestWriteSimpleValue) {
369   static const struct {
370     Value::SimpleValue simple_value;
371     const base::StringPiece cbor;
372   } kSimpleTestCase[] = {
373       {Value::SimpleValue::FALSE_VALUE, base::StringPiece("\xf4")},
374       {Value::SimpleValue::TRUE_VALUE, base::StringPiece("\xf5")},
375       {Value::SimpleValue::NULL_VALUE, base::StringPiece("\xf6")},
376       {Value::SimpleValue::UNDEFINED, base::StringPiece("\xf7")}};
377 
378   for (const auto& test_case : kSimpleTestCase) {
379     auto cbor = Writer::Write(Value(test_case.simple_value));
380     ASSERT_TRUE(cbor.has_value());
381     EXPECT_THAT(cbor.value(), testing::ElementsAreArray(test_case.cbor));
382   }
383 }
384 
385 // For major type 0, 2, 3, empty CBOR array, and empty CBOR map, the nesting
386 // depth is expected to be 0 since the CBOR decoder does not need to parse
387 // any nested CBOR value elements.
TEST(CBORWriterTest,TestWriteSingleLayer)388 TEST(CBORWriterTest, TestWriteSingleLayer) {
389   const Value simple_uint = Value(1);
390   const Value simple_string = Value("a");
391   const std::vector<uint8_t> byte_data = {0x01, 0x02, 0x03, 0x04};
392   const Value simple_bytestring = Value(byte_data);
393   Value::ArrayValue empty_cbor_array;
394   Value::MapValue empty_cbor_map;
395   const Value empty_array_value = Value(empty_cbor_array);
396   const Value empty_map_value = Value(empty_cbor_map);
397   Value::ArrayValue simple_array;
398   simple_array.push_back(Value(2));
399   Value::MapValue simple_map;
400   simple_map[Value("b")] = Value(3);
401   const Value single_layer_cbor_map = Value(simple_map);
402   const Value single_layer_cbor_array = Value(simple_array);
403 
404   EXPECT_TRUE(Writer::Write(simple_uint, 0).has_value());
405   EXPECT_TRUE(Writer::Write(simple_string, 0).has_value());
406   EXPECT_TRUE(Writer::Write(simple_bytestring, 0).has_value());
407 
408   EXPECT_TRUE(Writer::Write(empty_array_value, 0).has_value());
409   EXPECT_TRUE(Writer::Write(empty_map_value, 0).has_value());
410 
411   EXPECT_FALSE(Writer::Write(single_layer_cbor_array, 0).has_value());
412   EXPECT_TRUE(Writer::Write(single_layer_cbor_array, 1).has_value());
413 
414   EXPECT_FALSE(Writer::Write(single_layer_cbor_map, 0).has_value());
415   EXPECT_TRUE(Writer::Write(single_layer_cbor_map, 1).has_value());
416 }
417 
418 // Major type 5 nested CBOR map value with following structure.
419 //     {"a": 1,
420 //      "b": {"c": 2,
421 //            "d": 3}}
TEST(CBORWriterTest,NestedMaps)422 TEST(CBORWriterTest, NestedMaps) {
423   Value::MapValue cbor_map;
424   cbor_map[Value("a")] = Value(1);
425   Value::MapValue nested_map;
426   nested_map[Value("c")] = Value(2);
427   nested_map[Value("d")] = Value(3);
428   cbor_map[Value("b")] = Value(nested_map);
429   EXPECT_TRUE(Writer::Write(Value(cbor_map), 2).has_value());
430   EXPECT_FALSE(Writer::Write(Value(cbor_map), 1).has_value());
431 }
432 
433 // Testing Write() function for following CBOR structure with depth of 3.
434 //     [1,
435 //      2,
436 //      3,
437 //      {"a": 1,
438 //       "b": {"c": 2,
439 //             "d": 3}}]
TEST(CBORWriterTest,UnbalancedNestedContainers)440 TEST(CBORWriterTest, UnbalancedNestedContainers) {
441   Value::ArrayValue cbor_array;
442   Value::MapValue cbor_map;
443   Value::MapValue nested_map;
444 
445   cbor_map[Value("a")] = Value(1);
446   nested_map[Value("c")] = Value(2);
447   nested_map[Value("d")] = Value(3);
448   cbor_map[Value("b")] = Value(nested_map);
449   cbor_array.push_back(Value(1));
450   cbor_array.push_back(Value(2));
451   cbor_array.push_back(Value(3));
452   cbor_array.push_back(Value(cbor_map));
453 
454   EXPECT_TRUE(Writer::Write(Value(cbor_array), 3).has_value());
455   EXPECT_FALSE(Writer::Write(Value(cbor_array), 2).has_value());
456 }
457 
458 // Testing Write() function for following CBOR structure.
459 //     {"a": 1,
460 //      "b": {"c": 2,
461 //            "d": 3
462 //            "h": { "e": 4,
463 //                   "f": 5,
464 //                   "g": [6, 7, [8]]}}}
465 // Since above CBOR contains 5 nesting levels. Thus, Write() is expected to
466 // return empty optional object when maximum nesting layer size is set to 4.
TEST(CBORWriterTest,OverlyNestedCBOR)467 TEST(CBORWriterTest, OverlyNestedCBOR) {
468   Value::MapValue map;
469   Value::MapValue nested_map;
470   Value::MapValue inner_nested_map;
471   Value::ArrayValue inner_array;
472   Value::ArrayValue array;
473 
474   map[Value("a")] = Value(1);
475   nested_map[Value("c")] = Value(2);
476   nested_map[Value("d")] = Value(3);
477   inner_nested_map[Value("e")] = Value(4);
478   inner_nested_map[Value("f")] = Value(5);
479   inner_array.push_back(Value(6));
480   array.push_back(Value(6));
481   array.push_back(Value(7));
482   array.push_back(Value(inner_array));
483   inner_nested_map[Value("g")] = Value(array);
484   nested_map[Value("h")] = Value(inner_nested_map);
485   map[Value("b")] = Value(nested_map);
486 
487   EXPECT_TRUE(Writer::Write(Value(map), 5).has_value());
488   EXPECT_FALSE(Writer::Write(Value(map), 4).has_value());
489 }
490 
491 }  // namespace cbor
492