writer_unittest.cc 16 KB

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