cbor_test.cc 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449
  1. // Copyright 2018 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 "cbor.h"
  5. #include <array>
  6. #include <clocale>
  7. #include <cmath>
  8. #include <cstdlib>
  9. #include <cstring>
  10. #include <iomanip>
  11. #include <iostream>
  12. #include <sstream>
  13. #include <string>
  14. #include "json.h"
  15. #include "parser_handler.h"
  16. #include "span.h"
  17. #include "status.h"
  18. #include "status_test_support.h"
  19. #include "test_platform.h"
  20. using testing::ElementsAreArray;
  21. using testing::Eq;
  22. namespace crdtp {
  23. namespace cbor {
  24. // =============================================================================
  25. // Detecting CBOR content
  26. // =============================================================================
  27. TEST(IsCBORMessage, SomeSmokeTests) {
  28. std::vector<uint8_t> empty;
  29. EXPECT_FALSE(IsCBORMessage(SpanFrom(empty)));
  30. std::vector<uint8_t> hello = {'H', 'e', 'l', 'o', ' ', 't',
  31. 'h', 'e', 'r', 'e', '!'};
  32. EXPECT_FALSE(IsCBORMessage(SpanFrom(hello)));
  33. std::vector<uint8_t> example = {0xd8, 0x5a, 0, 0, 0, 0};
  34. EXPECT_TRUE(IsCBORMessage(SpanFrom(example)));
  35. std::vector<uint8_t> one = {0xd8, 0x5a, 0, 0, 0, 1, 1};
  36. EXPECT_TRUE(IsCBORMessage(SpanFrom(one)));
  37. }
  38. TEST(CheckCBORMessage, SmallestValidExample) {
  39. // The smallest example that we consider valid for this lightweight check is
  40. // an empty dictionary inside of an envelope.
  41. std::vector<uint8_t> empty_dict = {
  42. 0xd8, 0x5a, 0, 0, 0, 2, EncodeIndefiniteLengthMapStart(), EncodeStop()};
  43. Status status = CheckCBORMessage(SpanFrom(empty_dict));
  44. EXPECT_THAT(status, StatusIsOk());
  45. }
  46. TEST(CheckCBORMessage, ValidCBORButNotValidMessage) {
  47. // The CBOR parser supports parsing values that aren't messages. E.g., this is
  48. // the encoded unsigned int 7 (CBOR really encodes it as a single byte with
  49. // value 7).
  50. std::vector<uint8_t> not_a_message = {7};
  51. // Show that the parser (happily) decodes it into JSON
  52. std::string json;
  53. Status status;
  54. std::unique_ptr<ParserHandler> json_writer =
  55. json::NewJSONEncoder(&json, &status);
  56. ParseCBOR(SpanFrom(not_a_message), json_writer.get());
  57. EXPECT_THAT(status, StatusIsOk());
  58. EXPECT_EQ("7", json);
  59. // ... but it's not a message.
  60. EXPECT_THAT(CheckCBORMessage(SpanFrom(not_a_message)),
  61. StatusIs(Error::CBOR_INVALID_START_BYTE, 0));
  62. }
  63. TEST(CheckCBORMessage, EmptyMessage) {
  64. std::vector<uint8_t> empty;
  65. Status status = CheckCBORMessage(SpanFrom(empty));
  66. EXPECT_THAT(status, StatusIs(Error::CBOR_UNEXPECTED_EOF_IN_ENVELOPE, 0));
  67. }
  68. TEST(CheckCBORMessage, InvalidStartByte) {
  69. // Here we test that some actual json, which usually starts with {, is not
  70. // considered CBOR. CBOR messages must start with 0xd8, 0x5a, the envelope
  71. // start bytes.
  72. Status status = CheckCBORMessage(SpanFrom("{\"msg\": \"Hello, world.\"}"));
  73. EXPECT_THAT(status, StatusIs(Error::CBOR_INVALID_START_BYTE, 0));
  74. }
  75. TEST(CheckCBORMessage, InvalidEnvelopes) {
  76. std::vector<uint8_t> bytes = {0xd8, 0x5a};
  77. EXPECT_THAT(CheckCBORMessage(SpanFrom(bytes)),
  78. StatusIs(Error::CBOR_UNEXPECTED_EOF_IN_ENVELOPE, 2));
  79. bytes = {0xd8, 0x5a, 0};
  80. EXPECT_THAT(CheckCBORMessage(SpanFrom(bytes)),
  81. StatusIs(Error::CBOR_UNEXPECTED_EOF_IN_ENVELOPE, 3));
  82. bytes = {0xd8, 0x5a, 0, 0};
  83. EXPECT_THAT(CheckCBORMessage(SpanFrom(bytes)),
  84. StatusIs(Error::CBOR_UNEXPECTED_EOF_IN_ENVELOPE, 4));
  85. bytes = {0xd8, 0x5a, 0, 0, 0};
  86. EXPECT_THAT(CheckCBORMessage(SpanFrom(bytes)),
  87. StatusIs(Error::CBOR_UNEXPECTED_EOF_IN_ENVELOPE, 5));
  88. bytes = {0xd8, 0x5a, 0, 0, 0, 0};
  89. EXPECT_THAT(CheckCBORMessage(SpanFrom(bytes)),
  90. StatusIs(Error::CBOR_MAP_OR_ARRAY_EXPECTED_IN_ENVELOPE, 6));
  91. }
  92. TEST(CheckCBORMessage, MapStartExpected) {
  93. std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, 1};
  94. EXPECT_THAT(CheckCBORMessage(SpanFrom(bytes)),
  95. StatusIs(Error::CBOR_ENVELOPE_CONTENTS_LENGTH_MISMATCH, 6));
  96. }
  97. // =============================================================================
  98. // Encoding individual CBOR items
  99. // cbor::CBORTokenizer - for parsing individual CBOR items
  100. // =============================================================================
  101. //
  102. // EncodeInt32 / CBORTokenTag::INT32
  103. //
  104. TEST(EncodeDecodeInt32Test, Roundtrips23) {
  105. // This roundtrips the int32_t value 23 through the pair of EncodeInt32 /
  106. // CBORTokenizer; this is interesting since 23 is encoded as a single byte.
  107. std::vector<uint8_t> encoded;
  108. EncodeInt32(23, &encoded);
  109. // first three bits: major type = 0; remaining five bits: additional info =
  110. // value 23.
  111. EXPECT_THAT(encoded, ElementsAreArray(std::array<uint8_t, 1>{{23}}));
  112. // Reverse direction: decode with CBORTokenizer.
  113. CBORTokenizer tokenizer(SpanFrom(encoded));
  114. EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag());
  115. EXPECT_EQ(23, tokenizer.GetInt32());
  116. tokenizer.Next();
  117. EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
  118. }
  119. TEST(EncodeDecodeInt32Test, RoundtripsUint8) {
  120. // This roundtrips the int32_t value 42 through the pair of EncodeInt32 /
  121. // CBORTokenizer. This is different from Roundtrip23 because 42 is encoded
  122. // in an extra byte after the initial one.
  123. std::vector<uint8_t> encoded;
  124. EncodeInt32(42, &encoded);
  125. // first three bits: major type = 0;
  126. // remaining five bits: additional info = 24, indicating payload is uint8.
  127. EXPECT_THAT(encoded, ElementsAreArray(std::array<uint8_t, 2>{{24, 42}}));
  128. // Reverse direction: decode with CBORTokenizer.
  129. CBORTokenizer tokenizer(SpanFrom(encoded));
  130. EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag());
  131. EXPECT_EQ(42, tokenizer.GetInt32());
  132. tokenizer.Next();
  133. EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
  134. }
  135. TEST(EncodeDecodeInt32Test, RoundtripsUint16) {
  136. // 500 is encoded as a uint16 after the initial byte.
  137. std::vector<uint8_t> encoded;
  138. EncodeInt32(500, &encoded);
  139. // 1 for initial byte, 2 for uint16.
  140. EXPECT_EQ(3u, encoded.size());
  141. // first three bits: major type = 0;
  142. // remaining five bits: additional info = 25, indicating payload is uint16.
  143. EXPECT_EQ(25, encoded[0]);
  144. EXPECT_EQ(0x01, encoded[1]);
  145. EXPECT_EQ(0xf4, encoded[2]);
  146. // Reverse direction: decode with CBORTokenizer.
  147. CBORTokenizer tokenizer(SpanFrom(encoded));
  148. EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag());
  149. EXPECT_EQ(500, tokenizer.GetInt32());
  150. tokenizer.Next();
  151. EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
  152. }
  153. TEST(EncodeDecodeInt32Test, RoundtripsInt32Max) {
  154. // std::numeric_limits<int32_t> is encoded as a uint32 after the initial byte.
  155. std::vector<uint8_t> encoded;
  156. EncodeInt32(std::numeric_limits<int32_t>::max(), &encoded);
  157. // 1 for initial byte, 4 for the uint32.
  158. // first three bits: major type = 0;
  159. // remaining five bits: additional info = 26, indicating payload is uint32.
  160. EXPECT_THAT(
  161. encoded,
  162. ElementsAreArray(std::array<uint8_t, 5>{{26, 0x7f, 0xff, 0xff, 0xff}}));
  163. // Reverse direction: decode with CBORTokenizer.
  164. CBORTokenizer tokenizer(SpanFrom(encoded));
  165. EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag());
  166. EXPECT_EQ(std::numeric_limits<int32_t>::max(), tokenizer.GetInt32());
  167. tokenizer.Next();
  168. EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
  169. }
  170. TEST(EncodeDecodeInt32Test, RoundtripsInt32Min) {
  171. // std::numeric_limits<int32_t> is encoded as a uint32 (4 unsigned bytes)
  172. // after the initial byte, which effectively carries the sign by
  173. // designating the token as NEGATIVE.
  174. std::vector<uint8_t> encoded;
  175. EncodeInt32(std::numeric_limits<int32_t>::min(), &encoded);
  176. // 1 for initial byte, 4 for the uint32.
  177. // first three bits: major type = 1;
  178. // remaining five bits: additional info = 26, indicating payload is uint32.
  179. EXPECT_THAT(encoded, ElementsAreArray(std::array<uint8_t, 5>{
  180. {1 << 5 | 26, 0x7f, 0xff, 0xff, 0xff}}));
  181. // Reverse direction: decode with CBORTokenizer.
  182. CBORTokenizer tokenizer(SpanFrom(encoded));
  183. EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag());
  184. EXPECT_EQ(std::numeric_limits<int32_t>::min(), tokenizer.GetInt32());
  185. // It's nice to see how the min int32 value reads in hex:
  186. // That is, -1 minus the unsigned payload (0x7fffffff, see above).
  187. int32_t expected = -1 - 0x7fffffff;
  188. EXPECT_EQ(expected, tokenizer.GetInt32());
  189. tokenizer.Next();
  190. EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
  191. }
  192. TEST(EncodeDecodeInt32Test, CantRoundtripUint32) {
  193. // 0xdeadbeef is a value which does not fit below
  194. // std::numerical_limits<int32_t>::max(), so we can't encode
  195. // it with EncodeInt32. However, CBOR does support this, so we
  196. // encode it here manually with the internal routine, just to observe
  197. // that it's considered an invalid int32 by CBORTokenizer.
  198. std::vector<uint8_t> encoded;
  199. internals::WriteTokenStart(MajorType::UNSIGNED, 0xdeadbeef, &encoded);
  200. // 1 for initial byte, 4 for the uint32.
  201. // first three bits: major type = 0;
  202. // remaining five bits: additional info = 26, indicating payload is uint32.
  203. EXPECT_THAT(
  204. encoded,
  205. ElementsAreArray(std::array<uint8_t, 5>{{26, 0xde, 0xad, 0xbe, 0xef}}));
  206. // Now try to decode; we treat this as an invalid INT32.
  207. CBORTokenizer tokenizer(SpanFrom(encoded));
  208. // 0xdeadbeef is > std::numerical_limits<int32_t>::max().
  209. EXPECT_EQ(CBORTokenTag::ERROR_VALUE, tokenizer.TokenTag());
  210. EXPECT_THAT(tokenizer.Status(), StatusIs(Error::CBOR_INVALID_INT32, 0u));
  211. }
  212. TEST(EncodeDecodeInt32Test, DecodeErrorCases) {
  213. struct TestCase {
  214. std::vector<uint8_t> data;
  215. std::string msg;
  216. };
  217. std::vector<TestCase> tests{{
  218. TestCase{
  219. {24},
  220. "additional info = 24 would require 1 byte of payload (but it's 0)"},
  221. TestCase{{27, 0xaa, 0xbb, 0xcc},
  222. "additional info = 27 would require 8 bytes of payload (but "
  223. "it's 3)"},
  224. TestCase{{29}, "additional info = 29 isn't recognized"},
  225. TestCase{{1 << 5 | 27, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
  226. "Max UINT64 payload is outside the allowed range"},
  227. TestCase{{1 << 5 | 26, 0xff, 0xff, 0xff, 0xff},
  228. "Max UINT32 payload is outside the allowed range"},
  229. TestCase{{1 << 5 | 26, 0x80, 0x00, 0x00, 0x00},
  230. "UINT32 payload w/ high bit set is outside the allowed range"},
  231. }};
  232. for (const TestCase& test : tests) {
  233. SCOPED_TRACE(test.msg);
  234. CBORTokenizer tokenizer(SpanFrom(test.data));
  235. EXPECT_EQ(CBORTokenTag::ERROR_VALUE, tokenizer.TokenTag());
  236. EXPECT_THAT(tokenizer.Status(), StatusIs(Error::CBOR_INVALID_INT32, 0u));
  237. }
  238. }
  239. TEST(EncodeDecodeInt32Test, RoundtripsMinus24) {
  240. // This roundtrips the int32_t value -24 through the pair of EncodeInt32 /
  241. // CBORTokenizer; this is interesting since -24 is encoded as
  242. // a single byte as NEGATIVE, and it tests the specific encoding
  243. // (note how for unsigned the single byte covers values up to 23).
  244. // Additional examples are covered in RoundtripsAdditionalExamples.
  245. std::vector<uint8_t> encoded;
  246. EncodeInt32(-24, &encoded);
  247. // first three bits: major type = 1; remaining five bits: additional info =
  248. // value 23.
  249. EXPECT_THAT(encoded, ElementsAreArray(std::array<uint8_t, 1>{{1 << 5 | 23}}));
  250. // Reverse direction: decode with CBORTokenizer.
  251. CBORTokenizer tokenizer(SpanFrom(encoded));
  252. EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag());
  253. EXPECT_EQ(-24, tokenizer.GetInt32());
  254. tokenizer.Next();
  255. EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
  256. }
  257. TEST(EncodeDecodeInt32Test, RoundtripsAdditionalNegativeExamples) {
  258. std::vector<int32_t> examples = {-1,
  259. -10,
  260. -24,
  261. -25,
  262. -300,
  263. -30000,
  264. -300 * 1000,
  265. -1000 * 1000,
  266. -1000 * 1000 * 1000,
  267. std::numeric_limits<int32_t>::min()};
  268. for (int32_t example : examples) {
  269. SCOPED_TRACE(std::string("example ") + std::to_string(example));
  270. std::vector<uint8_t> encoded;
  271. EncodeInt32(example, &encoded);
  272. CBORTokenizer tokenizer(SpanFrom(encoded));
  273. EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag());
  274. EXPECT_EQ(example, tokenizer.GetInt32());
  275. tokenizer.Next();
  276. EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
  277. }
  278. }
  279. //
  280. // EncodeString16 / CBORTokenTag::STRING16
  281. //
  282. TEST(EncodeDecodeString16Test, RoundtripsEmpty) {
  283. // This roundtrips the empty utf16 string through the pair of EncodeString16 /
  284. // CBORTokenizer.
  285. std::vector<uint8_t> encoded;
  286. EncodeString16(span<uint16_t>(), &encoded);
  287. EXPECT_EQ(1u, encoded.size());
  288. // first three bits: major type = 2; remaining five bits: additional info =
  289. // size 0.
  290. EXPECT_EQ(2 << 5, encoded[0]);
  291. // Reverse direction: decode with CBORTokenizer.
  292. CBORTokenizer tokenizer(SpanFrom(encoded));
  293. EXPECT_EQ(CBORTokenTag::STRING16, tokenizer.TokenTag());
  294. span<uint8_t> decoded_string16_wirerep = tokenizer.GetString16WireRep();
  295. EXPECT_TRUE(decoded_string16_wirerep.empty());
  296. tokenizer.Next();
  297. EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
  298. }
  299. // On the wire, we STRING16 is encoded as little endian (least
  300. // significant byte first). The host may or may not be little endian,
  301. // so this routine follows the advice in
  302. // https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html.
  303. std::vector<uint16_t> String16WireRepToHost(span<uint8_t> in) {
  304. // must be even number of bytes.
  305. CHECK_EQ(in.size() & 1, 0u);
  306. std::vector<uint16_t> host_out;
  307. for (size_t ii = 0; ii < in.size(); ii += 2)
  308. host_out.push_back(in[ii + 1] << 8 | in[ii]);
  309. return host_out;
  310. }
  311. TEST(EncodeDecodeString16Test, RoundtripsHelloWorld) {
  312. // This roundtrips the hello world message which is given here in utf16
  313. // characters. 0xd83c, 0xdf0e: UTF16 encoding for the "Earth Globe Americas"
  314. // character, 🌎.
  315. std::array<uint16_t, 10> msg{
  316. {'H', 'e', 'l', 'l', 'o', ',', ' ', 0xd83c, 0xdf0e, '.'}};
  317. std::vector<uint8_t> encoded;
  318. EncodeString16(span<uint16_t>(msg.data(), msg.size()), &encoded);
  319. // This will be encoded as BYTE_STRING of length 20, so the 20 is encoded in
  320. // the additional info part of the initial byte. Payload is two bytes for each
  321. // UTF16 character.
  322. uint8_t initial_byte = /*major type=*/2 << 5 | /*additional info=*/20;
  323. std::array<uint8_t, 21> encoded_expected = {
  324. {initial_byte, 'H', 0, 'e', 0, 'l', 0, 'l', 0, 'o', 0,
  325. ',', 0, ' ', 0, 0x3c, 0xd8, 0x0e, 0xdf, '.', 0}};
  326. EXPECT_THAT(encoded, ElementsAreArray(encoded_expected));
  327. // Now decode to complete the roundtrip.
  328. CBORTokenizer tokenizer(SpanFrom(encoded));
  329. EXPECT_EQ(CBORTokenTag::STRING16, tokenizer.TokenTag());
  330. std::vector<uint16_t> decoded =
  331. String16WireRepToHost(tokenizer.GetString16WireRep());
  332. EXPECT_THAT(decoded, ElementsAreArray(msg));
  333. tokenizer.Next();
  334. EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
  335. // For bonus points, we look at the decoded message in UTF8 as well so we can
  336. // easily see it on the terminal screen.
  337. std::string utf8_decoded = UTF16ToUTF8(SpanFrom(decoded));
  338. EXPECT_EQ("Hello, 🌎.", utf8_decoded);
  339. }
  340. TEST(EncodeDecodeString16Test, Roundtrips500) {
  341. // We roundtrip a message that has 250 16 bit values. Each of these are just
  342. // set to their index. 250 is interesting because the cbor spec uses a
  343. // BYTE_STRING of length 500 for one of their examples of how to encode the
  344. // start of it (section 2.1) so it's easy for us to look at the first three
  345. // bytes closely.
  346. std::vector<uint16_t> two_fifty;
  347. for (uint16_t ii = 0; ii < 250; ++ii)
  348. two_fifty.push_back(ii);
  349. std::vector<uint8_t> encoded;
  350. EncodeString16(span<uint16_t>(two_fifty.data(), two_fifty.size()), &encoded);
  351. EXPECT_EQ(3u + 250u * 2, encoded.size());
  352. // Now check the first three bytes:
  353. // Major type: 2 (BYTE_STRING)
  354. // Additional information: 25, indicating size is represented by 2 bytes.
  355. // Bytes 1 and 2 encode 500 (0x01f4).
  356. EXPECT_EQ(2 << 5 | 25, encoded[0]);
  357. EXPECT_EQ(0x01, encoded[1]);
  358. EXPECT_EQ(0xf4, encoded[2]);
  359. // Now decode to complete the roundtrip.
  360. CBORTokenizer tokenizer(SpanFrom(encoded));
  361. EXPECT_EQ(CBORTokenTag::STRING16, tokenizer.TokenTag());
  362. std::vector<uint16_t> decoded =
  363. String16WireRepToHost(tokenizer.GetString16WireRep());
  364. EXPECT_THAT(decoded, ElementsAreArray(two_fifty));
  365. tokenizer.Next();
  366. EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
  367. }
  368. TEST(EncodeDecodeString16Test, ErrorCases) {
  369. struct TestCase {
  370. std::vector<uint8_t> data;
  371. std::string msg;
  372. };
  373. std::vector<TestCase> tests{
  374. {TestCase{{2 << 5 | 1, 'a'},
  375. "length must be divisible by 2 (but it's 1)"},
  376. TestCase{{2 << 5 | 29}, "additional info = 29 isn't recognized"},
  377. TestCase{{2 << 5 | 9, 1, 2, 3, 4, 5, 6, 7, 8},
  378. "length (9) points just past the end of the test case"},
  379. TestCase{{2 << 5 | 27, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  380. 'a', 'b', 'c'},
  381. "large length pointing past the end of the test case"}}};
  382. for (const TestCase& test : tests) {
  383. SCOPED_TRACE(test.msg);
  384. CBORTokenizer tokenizer(SpanFrom(test.data));
  385. EXPECT_EQ(CBORTokenTag::ERROR_VALUE, tokenizer.TokenTag());
  386. EXPECT_THAT(tokenizer.Status(), StatusIs(Error::CBOR_INVALID_STRING16, 0u));
  387. }
  388. }
  389. //
  390. // EncodeString8 / CBORTokenTag::STRING8
  391. //
  392. TEST(EncodeDecodeString8Test, RoundtripsHelloWorld) {
  393. // This roundtrips the hello world message which is given here in utf8
  394. // characters. 🌎 is a four byte utf8 character.
  395. std::string utf8_msg = "Hello, 🌎.";
  396. std::vector<uint8_t> msg(utf8_msg.begin(), utf8_msg.end());
  397. std::vector<uint8_t> encoded;
  398. EncodeString8(SpanFrom(utf8_msg), &encoded);
  399. // This will be encoded as STRING of length 12, so the 12 is encoded in
  400. // the additional info part of the initial byte. Payload is one byte per
  401. // utf8 byte.
  402. uint8_t initial_byte = /*major type=*/3 << 5 | /*additional info=*/12;
  403. std::array<uint8_t, 13> encoded_expected = {{initial_byte, 'H', 'e', 'l', 'l',
  404. 'o', ',', ' ', 0xF0, 0x9f, 0x8c,
  405. 0x8e, '.'}};
  406. EXPECT_THAT(encoded, ElementsAreArray(encoded_expected));
  407. // Now decode to complete the roundtrip.
  408. CBORTokenizer tokenizer(SpanFrom(encoded));
  409. EXPECT_EQ(CBORTokenTag::STRING8, tokenizer.TokenTag());
  410. std::vector<uint8_t> decoded(tokenizer.GetString8().begin(),
  411. tokenizer.GetString8().end());
  412. EXPECT_THAT(decoded, ElementsAreArray(msg));
  413. tokenizer.Next();
  414. EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
  415. }
  416. TEST(EncodeDecodeString8Test, ErrorCases) {
  417. struct TestCase {
  418. std::vector<uint8_t> data;
  419. std::string msg;
  420. };
  421. std::vector<TestCase> tests{
  422. {TestCase{{3 << 5 | 29}, "additional info = 29 isn't recognized"},
  423. TestCase{{3 << 5 | 9, 1, 2, 3, 4, 5, 6, 7, 8},
  424. "length (9) points just past the end of the test case"},
  425. TestCase{{3 << 5 | 27, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  426. 'a', 'b', 'c'},
  427. "large length pointing past the end of the test case"}}};
  428. for (const TestCase& test : tests) {
  429. SCOPED_TRACE(test.msg);
  430. CBORTokenizer tokenizer(SpanFrom(test.data));
  431. EXPECT_EQ(CBORTokenTag::ERROR_VALUE, tokenizer.TokenTag());
  432. EXPECT_THAT(tokenizer.Status(), StatusIs(Error::CBOR_INVALID_STRING8, 0u));
  433. }
  434. }
  435. TEST(EncodeFromLatin1Test, ConvertsToUTF8IfNeeded) {
  436. std::vector<std::pair<std::string, std::string>> examples = {
  437. {"Hello, world.", "Hello, world."},
  438. {"Above: \xDC"
  439. "ber",
  440. "Above: Über"},
  441. {"\xA5 500 are about \xA3 3.50; a y with umlaut is \xFF",
  442. "¥ 500 are about £ 3.50; a y with umlaut is ÿ"}};
  443. for (const auto& example : examples) {
  444. const std::string& latin1 = example.first;
  445. const std::string& expected_utf8 = example.second;
  446. std::vector<uint8_t> encoded;
  447. EncodeFromLatin1(SpanFrom(latin1), &encoded);
  448. CBORTokenizer tokenizer(SpanFrom(encoded));
  449. EXPECT_EQ(CBORTokenTag::STRING8, tokenizer.TokenTag());
  450. std::vector<uint8_t> decoded(tokenizer.GetString8().begin(),
  451. tokenizer.GetString8().end());
  452. std::string decoded_str(decoded.begin(), decoded.end());
  453. EXPECT_THAT(decoded_str, testing::Eq(expected_utf8));
  454. }
  455. }
  456. TEST(EncodeFromUTF16Test, ConvertsToUTF8IfEasy) {
  457. std::vector<uint16_t> ascii = {'e', 'a', 's', 'y'};
  458. std::vector<uint8_t> encoded;
  459. EncodeFromUTF16(span<uint16_t>(ascii.data(), ascii.size()), &encoded);
  460. CBORTokenizer tokenizer(SpanFrom(encoded));
  461. EXPECT_EQ(CBORTokenTag::STRING8, tokenizer.TokenTag());
  462. std::vector<uint8_t> decoded(tokenizer.GetString8().begin(),
  463. tokenizer.GetString8().end());
  464. std::string decoded_str(decoded.begin(), decoded.end());
  465. EXPECT_THAT(decoded_str, testing::Eq("easy"));
  466. }
  467. TEST(EncodeFromUTF16Test, EncodesAsString16IfNeeded) {
  468. // Since this message contains non-ASCII characters, the routine is
  469. // forced to encode as UTF16. We see this below by checking that the
  470. // token tag is STRING16.
  471. std::vector<uint16_t> msg = {'H', 'e', 'l', 'l', 'o',
  472. ',', ' ', 0xd83c, 0xdf0e, '.'};
  473. std::vector<uint8_t> encoded;
  474. EncodeFromUTF16(span<uint16_t>(msg.data(), msg.size()), &encoded);
  475. CBORTokenizer tokenizer(SpanFrom(encoded));
  476. EXPECT_EQ(CBORTokenTag::STRING16, tokenizer.TokenTag());
  477. std::vector<uint16_t> decoded =
  478. String16WireRepToHost(tokenizer.GetString16WireRep());
  479. std::string utf8_decoded = UTF16ToUTF8(SpanFrom(decoded));
  480. EXPECT_EQ("Hello, 🌎.", utf8_decoded);
  481. }
  482. //
  483. // EncodeBinary / CBORTokenTag::BINARY
  484. //
  485. TEST(EncodeDecodeBinaryTest, RoundtripsHelloWorld) {
  486. std::vector<uint8_t> binary = {'H', 'e', 'l', 'l', 'o', ',', ' ',
  487. 'w', 'o', 'r', 'l', 'd', '.'};
  488. std::vector<uint8_t> encoded;
  489. EncodeBinary(span<uint8_t>(binary.data(), binary.size()), &encoded);
  490. // So, on the wire we see that the binary blob travels unmodified.
  491. EXPECT_THAT(
  492. encoded,
  493. ElementsAreArray(std::array<uint8_t, 15>{
  494. {(6 << 5 | 22), // tag 22 indicating base64 interpretation in JSON
  495. (2 << 5 | 13), // BYTE_STRING (type 2) of length 13
  496. 'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '.'}}));
  497. std::vector<uint8_t> decoded;
  498. CBORTokenizer tokenizer(SpanFrom(encoded));
  499. EXPECT_EQ(CBORTokenTag::BINARY, tokenizer.TokenTag());
  500. EXPECT_THAT(tokenizer.Status(), StatusIsOk());
  501. decoded = std::vector<uint8_t>(tokenizer.GetBinary().begin(),
  502. tokenizer.GetBinary().end());
  503. EXPECT_THAT(decoded, ElementsAreArray(binary));
  504. tokenizer.Next();
  505. EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
  506. }
  507. TEST(EncodeDecodeBinaryTest, ErrorCases) {
  508. struct TestCase {
  509. std::vector<uint8_t> data;
  510. std::string msg;
  511. };
  512. std::vector<TestCase> tests{{TestCase{
  513. {6 << 5 | 22, // tag 22 indicating base64 interpretation in JSON
  514. 2 << 5 | 27, // BYTE_STRING (type 2), followed by 8 bytes length
  515. 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
  516. "large length pointing past the end of the test case"}}};
  517. for (const TestCase& test : tests) {
  518. SCOPED_TRACE(test.msg);
  519. CBORTokenizer tokenizer(SpanFrom(test.data));
  520. EXPECT_EQ(CBORTokenTag::ERROR_VALUE, tokenizer.TokenTag());
  521. EXPECT_THAT(tokenizer.Status(), StatusIs(Error::CBOR_INVALID_BINARY, 0u));
  522. }
  523. }
  524. //
  525. // EncodeDouble / CBORTokenTag::DOUBLE
  526. //
  527. TEST(EncodeDecodeDoubleTest, RoundtripsWikipediaExample) {
  528. // https://en.wikipedia.org/wiki/Double-precision_floating-point_format
  529. // provides the example of a hex representation 3FD5 5555 5555 5555, which
  530. // approximates 1/3.
  531. const double kOriginalValue = 1.0 / 3;
  532. std::vector<uint8_t> encoded;
  533. EncodeDouble(kOriginalValue, &encoded);
  534. // first three bits: major type = 7; remaining five bits: additional info =
  535. // value 27. This is followed by 8 bytes of payload (which match Wikipedia).
  536. EXPECT_THAT(
  537. encoded,
  538. ElementsAreArray(std::array<uint8_t, 9>{
  539. {7 << 5 | 27, 0x3f, 0xd5, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55}}));
  540. // Reverse direction: decode and compare with original value.
  541. CBORTokenizer tokenizer(SpanFrom(encoded));
  542. EXPECT_EQ(CBORTokenTag::DOUBLE, tokenizer.TokenTag());
  543. EXPECT_THAT(tokenizer.GetDouble(), testing::DoubleEq(kOriginalValue));
  544. tokenizer.Next();
  545. EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
  546. }
  547. TEST(EncodeDecodeDoubleTest, RoundtripsAdditionalExamples) {
  548. std::vector<double> examples = {0.0,
  549. 1.0,
  550. -1.0,
  551. 3.1415,
  552. std::numeric_limits<double>::min(),
  553. std::numeric_limits<double>::max(),
  554. std::numeric_limits<double>::infinity(),
  555. std::numeric_limits<double>::quiet_NaN()};
  556. for (double example : examples) {
  557. SCOPED_TRACE(std::string("example ") + std::to_string(example));
  558. std::vector<uint8_t> encoded;
  559. EncodeDouble(example, &encoded);
  560. CBORTokenizer tokenizer(SpanFrom(encoded));
  561. EXPECT_EQ(CBORTokenTag::DOUBLE, tokenizer.TokenTag());
  562. if (std::isnan(example))
  563. EXPECT_TRUE(std::isnan(tokenizer.GetDouble()));
  564. else
  565. EXPECT_THAT(tokenizer.GetDouble(), testing::DoubleEq(example));
  566. tokenizer.Next();
  567. EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
  568. }
  569. }
  570. TEST(EncodeDecodeEnvelopesTest, MessageWithNestingAndEnvelopeContentsAccess) {
  571. // This encodes and decodes the following message, which has some nesting
  572. // and therefore envelopes.
  573. // { "inner": { "foo" : "bar" } }
  574. // The decoding is done with the Tokenizer,
  575. // and we test both ::GetEnvelopeContents and GetEnvelope here.
  576. std::vector<uint8_t> message;
  577. EnvelopeEncoder envelope;
  578. envelope.EncodeStart(&message);
  579. size_t pos_after_header = message.size();
  580. message.push_back(EncodeIndefiniteLengthMapStart());
  581. EncodeString8(SpanFrom("inner"), &message);
  582. size_t pos_inside_inner = message.size();
  583. EnvelopeEncoder inner_envelope;
  584. inner_envelope.EncodeStart(&message);
  585. size_t pos_inside_inner_contents = message.size();
  586. message.push_back(EncodeIndefiniteLengthMapStart());
  587. EncodeString8(SpanFrom("foo"), &message);
  588. EncodeString8(SpanFrom("bar"), &message);
  589. message.push_back(EncodeStop());
  590. size_t pos_after_inner = message.size();
  591. inner_envelope.EncodeStop(&message);
  592. message.push_back(EncodeStop());
  593. envelope.EncodeStop(&message);
  594. CBORTokenizer tokenizer(SpanFrom(message));
  595. ASSERT_EQ(CBORTokenTag::ENVELOPE, tokenizer.TokenTag());
  596. EXPECT_EQ(message.size(), tokenizer.GetEnvelope().size());
  597. EXPECT_EQ(message.data(), tokenizer.GetEnvelope().data());
  598. EXPECT_EQ(message.data() + pos_after_header,
  599. tokenizer.GetEnvelopeContents().data());
  600. EXPECT_EQ(message.size() - pos_after_header,
  601. tokenizer.GetEnvelopeContents().size());
  602. tokenizer.EnterEnvelope();
  603. ASSERT_EQ(CBORTokenTag::MAP_START, tokenizer.TokenTag());
  604. tokenizer.Next();
  605. ASSERT_EQ(CBORTokenTag::STRING8, tokenizer.TokenTag());
  606. EXPECT_EQ("inner", std::string(tokenizer.GetString8().begin(),
  607. tokenizer.GetString8().end()));
  608. tokenizer.Next();
  609. ASSERT_EQ(CBORTokenTag::ENVELOPE, tokenizer.TokenTag());
  610. EXPECT_EQ(message.data() + pos_inside_inner, tokenizer.GetEnvelope().data());
  611. EXPECT_EQ(pos_after_inner - pos_inside_inner, tokenizer.GetEnvelope().size());
  612. EXPECT_EQ(message.data() + pos_inside_inner_contents,
  613. tokenizer.GetEnvelopeContents().data());
  614. EXPECT_EQ(pos_after_inner - pos_inside_inner_contents,
  615. tokenizer.GetEnvelopeContents().size());
  616. tokenizer.EnterEnvelope();
  617. ASSERT_EQ(CBORTokenTag::MAP_START, tokenizer.TokenTag());
  618. tokenizer.Next();
  619. ASSERT_EQ(CBORTokenTag::STRING8, tokenizer.TokenTag());
  620. EXPECT_EQ("foo", std::string(tokenizer.GetString8().begin(),
  621. tokenizer.GetString8().end()));
  622. tokenizer.Next();
  623. ASSERT_EQ(CBORTokenTag::STRING8, tokenizer.TokenTag());
  624. EXPECT_EQ("bar", std::string(tokenizer.GetString8().begin(),
  625. tokenizer.GetString8().end()));
  626. tokenizer.Next();
  627. ASSERT_EQ(CBORTokenTag::STOP, tokenizer.TokenTag());
  628. tokenizer.Next();
  629. ASSERT_EQ(CBORTokenTag::STOP, tokenizer.TokenTag());
  630. tokenizer.Next();
  631. ASSERT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
  632. }
  633. // =============================================================================
  634. // cbor::NewCBOREncoder - for encoding from a streaming parser
  635. // =============================================================================
  636. TEST(JSONToCBOREncoderTest, SevenBitStrings) {
  637. // When a string can be represented as 7 bit ASCII, the encoder will use the
  638. // STRING (major Type 3) type, so the actual characters end up as bytes on the
  639. // wire.
  640. std::vector<uint8_t> encoded;
  641. Status status;
  642. std::unique_ptr<ParserHandler> encoder = NewCBOREncoder(&encoded, &status);
  643. std::vector<uint16_t> utf16 = {'f', 'o', 'o'};
  644. encoder->HandleString16(span<uint16_t>(utf16.data(), utf16.size()));
  645. EXPECT_THAT(status, StatusIsOk());
  646. // Here we assert that indeed, seven bit strings are represented as
  647. // bytes on the wire, "foo" is just "foo".
  648. EXPECT_THAT(encoded,
  649. ElementsAreArray(std::array<uint8_t, 4>{
  650. {/*major type 3*/ 3 << 5 | /*length*/ 3, 'f', 'o', 'o'}}));
  651. }
  652. TEST(JsonCborRoundtrip, EncodingDecoding) {
  653. // Hits all the cases except binary and error in ParserHandler, first
  654. // parsing a JSON message into CBOR, then parsing it back from CBOR into JSON.
  655. std::string json =
  656. "{"
  657. "\"string\":\"Hello, \\ud83c\\udf0e.\","
  658. "\"double\":3.1415,"
  659. "\"int\":1,"
  660. "\"negative int\":-1,"
  661. "\"bool\":true,"
  662. "\"null\":null,"
  663. "\"array\":[1,2,3]"
  664. "}";
  665. std::vector<uint8_t> encoded;
  666. Status status;
  667. std::unique_ptr<ParserHandler> encoder = NewCBOREncoder(&encoded, &status);
  668. span<uint8_t> ascii_in = SpanFrom(json);
  669. json::ParseJSON(ascii_in, encoder.get());
  670. std::vector<uint8_t> expected = {
  671. 0xd8, 0x18, // envelope
  672. 0x5a, // byte string with 32 bit length
  673. 0, 0, 0, 95, // length is 95 bytes
  674. };
  675. expected.push_back(0xbf); // indef length map start
  676. EncodeString8(SpanFrom("string"), &expected);
  677. // This is followed by the encoded string for "Hello, 🌎."
  678. // So, it's the same bytes that we tested above in
  679. // EncodeDecodeString16Test.RoundtripsHelloWorld.
  680. expected.push_back(/*major type=*/2 << 5 | /*additional info=*/20);
  681. for (uint8_t ch : std::array<uint8_t, 20>{
  682. {'H', 0, 'e', 0, 'l', 0, 'l', 0, 'o', 0,
  683. ',', 0, ' ', 0, 0x3c, 0xd8, 0x0e, 0xdf, '.', 0}})
  684. expected.push_back(ch);
  685. EncodeString8(SpanFrom("double"), &expected);
  686. EncodeDouble(3.1415, &expected);
  687. EncodeString8(SpanFrom("int"), &expected);
  688. EncodeInt32(1, &expected);
  689. EncodeString8(SpanFrom("negative int"), &expected);
  690. EncodeInt32(-1, &expected);
  691. EncodeString8(SpanFrom("bool"), &expected);
  692. expected.push_back(7 << 5 | 21); // RFC 7049 Section 2.3, Table 2: true
  693. EncodeString8(SpanFrom("null"), &expected);
  694. expected.push_back(7 << 5 | 22); // RFC 7049 Section 2.3, Table 2: null
  695. EncodeString8(SpanFrom("array"), &expected);
  696. expected.push_back(0xd8); // envelope (tag first byte)
  697. expected.push_back(0x18); // envelope (tag second byte)
  698. expected.push_back(0x5a); // byte string with 32 bit length
  699. // the length is 5 bytes (that's up to end indef length array below).
  700. for (uint8_t ch : std::array<uint8_t, 4>{{0, 0, 0, 5}})
  701. expected.push_back(ch);
  702. expected.push_back(0x9f); // RFC 7049 Section 2.2.1, indef length array start
  703. expected.push_back(1); // Three UNSIGNED values (easy since Major Type 0)
  704. expected.push_back(2);
  705. expected.push_back(3);
  706. expected.push_back(0xff); // End indef length array
  707. expected.push_back(0xff); // End indef length map
  708. EXPECT_TRUE(status.ok());
  709. EXPECT_THAT(encoded, ElementsAreArray(expected));
  710. // And now we roundtrip, decoding the message we just encoded.
  711. std::string decoded;
  712. std::unique_ptr<ParserHandler> json_encoder =
  713. json::NewJSONEncoder(&decoded, &status);
  714. ParseCBOR(span<uint8_t>(encoded.data(), encoded.size()), json_encoder.get());
  715. EXPECT_THAT(status, StatusIsOk());
  716. EXPECT_EQ(json, decoded);
  717. }
  718. TEST(JsonCborRoundtrip, MoreRoundtripExamples) {
  719. std::vector<std::string> examples = {
  720. // Tests that after closing a nested objects, additional key/value pairs
  721. // are considered.
  722. "{\"foo\":{\"bar\":1},\"baz\":2}", "{\"foo\":[1,2,3],\"baz\":2}"};
  723. for (const std::string& json : examples) {
  724. SCOPED_TRACE(std::string("example: ") + json);
  725. std::vector<uint8_t> encoded;
  726. Status status;
  727. std::unique_ptr<ParserHandler> encoder = NewCBOREncoder(&encoded, &status);
  728. span<uint8_t> ascii_in = SpanFrom(json);
  729. json::ParseJSON(ascii_in, encoder.get());
  730. std::string decoded;
  731. std::unique_ptr<ParserHandler> json_writer =
  732. json::NewJSONEncoder(&decoded, &status);
  733. ParseCBOR(span<uint8_t>(encoded.data(), encoded.size()), json_writer.get());
  734. EXPECT_THAT(status, StatusIsOk());
  735. EXPECT_EQ(json, decoded);
  736. }
  737. }
  738. TEST(JSONToCBOREncoderTest, HelloWorldBinary_WithTripToJson) {
  739. // The ParserHandler::HandleBinary is a special case: The JSON parser
  740. // will never call this method, because JSON does not natively support the
  741. // binary type. So, we can't fully roundtrip. However, the other direction
  742. // works: binary will be rendered in JSON, as a base64 string. So, we make
  743. // calls to the encoder directly here, to construct a message, and one of
  744. // these calls is ::HandleBinary, to which we pass a "binary" string
  745. // containing "Hello, world.".
  746. std::vector<uint8_t> encoded;
  747. Status status;
  748. std::unique_ptr<ParserHandler> encoder = NewCBOREncoder(&encoded, &status);
  749. encoder->HandleMapBegin();
  750. // Emit a key.
  751. std::vector<uint16_t> key = {'f', 'o', 'o'};
  752. encoder->HandleString16(SpanFrom(key));
  753. // Emit the binary payload, an arbitrary array of bytes that happens to
  754. // be the ascii message "Hello, world.".
  755. encoder->HandleBinary(SpanFrom(std::vector<uint8_t>{
  756. 'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '.'}));
  757. encoder->HandleMapEnd();
  758. EXPECT_THAT(status, StatusIsOk());
  759. // Now drive the json writer via the CBOR decoder.
  760. std::string decoded;
  761. std::unique_ptr<ParserHandler> json_writer =
  762. json::NewJSONEncoder(&decoded, &status);
  763. ParseCBOR(SpanFrom(encoded), json_writer.get());
  764. EXPECT_THAT(status, StatusIsOk());
  765. // "Hello, world." in base64 is "SGVsbG8sIHdvcmxkLg==".
  766. EXPECT_EQ("{\"foo\":\"SGVsbG8sIHdvcmxkLg==\"}", decoded);
  767. }
  768. // =============================================================================
  769. // cbor::ParseCBOR - for receiving streaming parser events for CBOR messages
  770. // =============================================================================
  771. TEST(ParseCBORTest, ParseEmptyCBORMessage) {
  772. // An envelope starting with 0xd8, 0x5a, with the byte length
  773. // of 2, containing a map that's empty (0xbf for map
  774. // start, and 0xff for map end).
  775. std::vector<uint8_t> in = {0xd8, 0x5a, 0, 0, 0, 2, 0xbf, 0xff};
  776. std::string out;
  777. Status status;
  778. std::unique_ptr<ParserHandler> json_writer =
  779. json::NewJSONEncoder(&out, &status);
  780. ParseCBOR(span<uint8_t>(in.data(), in.size()), json_writer.get());
  781. EXPECT_THAT(status, StatusIsOk());
  782. EXPECT_EQ("{}", out);
  783. }
  784. TEST(ParseCBORTest, ParseCBORHelloWorld) {
  785. const uint8_t kPayloadLen = 27;
  786. std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen};
  787. bytes.push_back(0xbf); // start indef length map.
  788. EncodeString8(SpanFrom("msg"), &bytes); // key: msg
  789. // Now write the value, the familiar "Hello, 🌎." where the globe is expressed
  790. // as two utf16 chars.
  791. bytes.push_back(/*major type=*/2 << 5 | /*additional info=*/20);
  792. for (uint8_t ch : std::array<uint8_t, 20>{
  793. {'H', 0, 'e', 0, 'l', 0, 'l', 0, 'o', 0,
  794. ',', 0, ' ', 0, 0x3c, 0xd8, 0x0e, 0xdf, '.', 0}})
  795. bytes.push_back(ch);
  796. bytes.push_back(0xff); // stop byte
  797. EXPECT_EQ(kPayloadLen, bytes.size() - 6);
  798. std::string out;
  799. Status status;
  800. std::unique_ptr<ParserHandler> json_writer =
  801. json::NewJSONEncoder(&out, &status);
  802. ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
  803. EXPECT_THAT(status, StatusIsOk());
  804. EXPECT_EQ("{\"msg\":\"Hello, \\ud83c\\udf0e.\"}", out);
  805. }
  806. TEST(ParseCBORTest, UTF8IsSupportedInKeys) {
  807. const uint8_t kPayloadLen = 11;
  808. std::vector<uint8_t> bytes = {0xd8, 0x5a, // envelope
  809. 0, 0, 0, kPayloadLen};
  810. bytes.push_back(cbor::EncodeIndefiniteLengthMapStart());
  811. // Two UTF16 chars.
  812. EncodeString8(SpanFrom("🌎"), &bytes);
  813. // Can be encoded as a single UTF16 char.
  814. EncodeString8(SpanFrom("☾"), &bytes);
  815. bytes.push_back(cbor::EncodeStop());
  816. EXPECT_EQ(kPayloadLen, bytes.size() - 6);
  817. std::string out;
  818. Status status;
  819. std::unique_ptr<ParserHandler> json_writer =
  820. json::NewJSONEncoder(&out, &status);
  821. ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
  822. EXPECT_THAT(status, StatusIsOk());
  823. EXPECT_EQ("{\"\\ud83c\\udf0e\":\"\\u263e\"}", out);
  824. }
  825. TEST(ParseCBORTest, NoInputError) {
  826. std::vector<uint8_t> in = {};
  827. std::string out;
  828. Status status;
  829. std::unique_ptr<ParserHandler> json_writer =
  830. json::NewJSONEncoder(&out, &status);
  831. ParseCBOR(span<uint8_t>(in.data(), in.size()), json_writer.get());
  832. EXPECT_THAT(status, StatusIs(Error::CBOR_UNEXPECTED_EOF_IN_ENVELOPE, 0u));
  833. EXPECT_EQ("", out);
  834. }
  835. TEST(ParseCBORTest, UnexpectedEofExpectedValueError) {
  836. constexpr uint8_t kPayloadLen = 5;
  837. std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope
  838. 0xbf}; // map start
  839. // A key; so value would be next.
  840. EncodeString8(SpanFrom("key"), &bytes);
  841. EXPECT_EQ(kPayloadLen, bytes.size() - 6);
  842. std::string out;
  843. Status status;
  844. std::unique_ptr<ParserHandler> json_writer =
  845. json::NewJSONEncoder(&out, &status);
  846. ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
  847. EXPECT_THAT(status, StatusIs(Error::CBOR_UNEXPECTED_EOF_EXPECTED_VALUE,
  848. bytes.size()));
  849. EXPECT_EQ("", out);
  850. }
  851. TEST(ParseCBORTest, UnexpectedEofInArrayError) {
  852. constexpr uint8_t kPayloadLen = 8;
  853. std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope
  854. 0xbf}; // The byte for starting a map.
  855. // A key; so value would be next.
  856. EncodeString8(SpanFrom("array"), &bytes);
  857. bytes.push_back(0x9f); // byte for indefinite length array start.
  858. EXPECT_EQ(kPayloadLen, bytes.size() - 6);
  859. std::string out;
  860. Status status;
  861. std::unique_ptr<ParserHandler> json_writer =
  862. json::NewJSONEncoder(&out, &status);
  863. ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
  864. EXPECT_THAT(status,
  865. StatusIs(Error::CBOR_UNEXPECTED_EOF_IN_ARRAY, bytes.size()));
  866. EXPECT_EQ("", out);
  867. }
  868. TEST(ParseCBORTest, UnexpectedEofInMapError) {
  869. constexpr uint8_t kPayloadLen = 1;
  870. std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope
  871. 0xbf}; // The byte for starting a map.
  872. EXPECT_EQ(kPayloadLen, bytes.size() - 6);
  873. std::string out;
  874. Status status;
  875. std::unique_ptr<ParserHandler> json_writer =
  876. json::NewJSONEncoder(&out, &status);
  877. ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
  878. EXPECT_THAT(status, StatusIs(Error::CBOR_UNEXPECTED_EOF_IN_MAP, 7u));
  879. EXPECT_EQ("", out);
  880. }
  881. TEST(ParseCBORTest, EnvelopeEncodingLegacy) {
  882. constexpr uint8_t kPayloadLen = 8;
  883. std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen}; // envelope
  884. bytes.push_back(cbor::EncodeIndefiniteLengthMapStart());
  885. EncodeString8(SpanFrom("foo"), &bytes);
  886. EncodeInt32(42, &bytes);
  887. bytes.emplace_back(EncodeStop());
  888. std::string out;
  889. Status status;
  890. std::unique_ptr<ParserHandler> json_writer =
  891. json::NewJSONEncoder(&out, &status);
  892. ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
  893. EXPECT_THAT(status, StatusIsOk());
  894. EXPECT_EQ(out, "{\"foo\":42}");
  895. }
  896. TEST(ParseCBORTest, EnvelopeEncodingBySpec) {
  897. constexpr uint8_t kPayloadLen = 8;
  898. std::vector<uint8_t> bytes = {0xd8, 0x18, 0x5a, 0,
  899. 0, 0, kPayloadLen}; // envelope
  900. bytes.push_back(cbor::EncodeIndefiniteLengthMapStart());
  901. EncodeString8(SpanFrom("foo"), &bytes);
  902. EncodeInt32(42, &bytes);
  903. bytes.emplace_back(EncodeStop());
  904. std::string out;
  905. Status status;
  906. std::unique_ptr<ParserHandler> json_writer =
  907. json::NewJSONEncoder(&out, &status);
  908. ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
  909. EXPECT_THAT(status, StatusIsOk());
  910. EXPECT_EQ(out, "{\"foo\":42}");
  911. }
  912. TEST(ParseCBORTest, NoEmptyEnvelopesAllowed) {
  913. std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, 0}; // envelope
  914. std::string out;
  915. Status status;
  916. std::unique_ptr<ParserHandler> json_writer =
  917. json::NewJSONEncoder(&out, &status);
  918. ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
  919. EXPECT_THAT(status, StatusIs(Error::CBOR_MAP_OR_ARRAY_EXPECTED_IN_ENVELOPE,
  920. bytes.size()));
  921. EXPECT_EQ("", out);
  922. }
  923. TEST(ParseCBORTest, OnlyMapsAndArraysSupportedInsideEnvelopes) {
  924. // The top level is a map with key "foo", and the value
  925. // is an envelope that contains just a number (1). We don't
  926. // allow numbers to be contained in an envelope though, only
  927. // maps and arrays.
  928. constexpr uint8_t kPayloadLen = 8;
  929. std::vector<uint8_t> bytes = {0xd8,
  930. 0x5a,
  931. 0,
  932. 0,
  933. 0,
  934. kPayloadLen, // envelope
  935. EncodeIndefiniteLengthMapStart()};
  936. EncodeString8(SpanFrom("foo"), &bytes);
  937. for (uint8_t byte : {0xd8, 0x5a, 0, 0, 0, /*payload_len*/ 1})
  938. bytes.emplace_back(byte);
  939. size_t error_pos = bytes.size();
  940. bytes.push_back(1); // Envelope contents / payload = number 1.
  941. bytes.emplace_back(EncodeStop());
  942. std::string out;
  943. Status status;
  944. std::unique_ptr<ParserHandler> json_writer =
  945. json::NewJSONEncoder(&out, &status);
  946. ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
  947. EXPECT_THAT(status, StatusIs(Error::CBOR_MAP_OR_ARRAY_EXPECTED_IN_ENVELOPE,
  948. error_pos));
  949. EXPECT_EQ("", out);
  950. }
  951. TEST(ParseCBORTest, InvalidMapKeyError) {
  952. constexpr uint8_t kPayloadLen = 2;
  953. std::vector<uint8_t> bytes = {0xd8, 0x5a, 0,
  954. 0, 0, kPayloadLen, // envelope
  955. 0xbf, // map start
  956. 7 << 5 | 22}; // null (not a valid map key)
  957. EXPECT_EQ(kPayloadLen, bytes.size() - 6);
  958. std::string out;
  959. Status status;
  960. std::unique_ptr<ParserHandler> json_writer =
  961. json::NewJSONEncoder(&out, &status);
  962. ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
  963. EXPECT_THAT(status, StatusIs(Error::CBOR_INVALID_MAP_KEY, 7u));
  964. EXPECT_EQ("", out);
  965. }
  966. std::vector<uint8_t> MakeNestedCBOR(int depth) {
  967. std::vector<uint8_t> bytes;
  968. std::vector<EnvelopeEncoder> envelopes;
  969. for (int ii = 0; ii < depth; ++ii) {
  970. envelopes.emplace_back();
  971. envelopes.back().EncodeStart(&bytes);
  972. bytes.push_back(0xbf); // indef length map start
  973. EncodeString8(SpanFrom("key"), &bytes);
  974. }
  975. EncodeString8(SpanFrom("innermost_value"), &bytes);
  976. for (int ii = 0; ii < depth; ++ii) {
  977. bytes.push_back(0xff); // stop byte, finishes map.
  978. envelopes.back().EncodeStop(&bytes);
  979. envelopes.pop_back();
  980. }
  981. return bytes;
  982. }
  983. TEST(ParseCBORTest, StackLimitExceededError) {
  984. { // Depth 3: no stack limit exceeded error and is easy to inspect.
  985. std::vector<uint8_t> bytes = MakeNestedCBOR(3);
  986. std::string out;
  987. Status status;
  988. std::unique_ptr<ParserHandler> json_writer =
  989. json::NewJSONEncoder(&out, &status);
  990. ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
  991. EXPECT_THAT(status, StatusIsOk());
  992. EXPECT_EQ("{\"key\":{\"key\":{\"key\":\"innermost_value\"}}}", out);
  993. }
  994. { // Depth 300: no stack limit exceeded.
  995. std::vector<uint8_t> bytes = MakeNestedCBOR(300);
  996. std::string out;
  997. Status status;
  998. std::unique_ptr<ParserHandler> json_writer =
  999. json::NewJSONEncoder(&out, &status);
  1000. ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
  1001. EXPECT_THAT(status, StatusIsOk());
  1002. }
  1003. // We just want to know the length of one opening map so we can compute
  1004. // where the error is encountered. So we look at a small example and find
  1005. // the second envelope start.
  1006. std::vector<uint8_t> small_example = MakeNestedCBOR(3);
  1007. size_t opening_segment_size = 1; // Start after the first envelope start.
  1008. while (opening_segment_size < small_example.size() &&
  1009. small_example[opening_segment_size] != 0xd8)
  1010. opening_segment_size++;
  1011. { // Depth 301: limit exceeded.
  1012. std::vector<uint8_t> bytes = MakeNestedCBOR(301);
  1013. std::string out;
  1014. Status status;
  1015. std::unique_ptr<ParserHandler> json_writer =
  1016. json::NewJSONEncoder(&out, &status);
  1017. ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
  1018. EXPECT_THAT(status, StatusIs(Error::CBOR_STACK_LIMIT_EXCEEDED,
  1019. opening_segment_size * 301));
  1020. }
  1021. { // Depth 320: still limit exceeded, and at the same pos as for 1001
  1022. std::vector<uint8_t> bytes = MakeNestedCBOR(320);
  1023. std::string out;
  1024. Status status;
  1025. std::unique_ptr<ParserHandler> json_writer =
  1026. json::NewJSONEncoder(&out, &status);
  1027. ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
  1028. EXPECT_THAT(status, StatusIs(Error::CBOR_STACK_LIMIT_EXCEEDED,
  1029. opening_segment_size * 301));
  1030. }
  1031. }
  1032. TEST(ParseCBORTest, UnsupportedValueError) {
  1033. constexpr uint8_t kPayloadLen = 6;
  1034. std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope
  1035. 0xbf}; // map start
  1036. EncodeString8(SpanFrom("key"), &bytes);
  1037. size_t error_pos = bytes.size();
  1038. bytes.push_back(6 << 5 | 5); // tags aren't supported yet.
  1039. EXPECT_EQ(kPayloadLen, bytes.size() - 6);
  1040. std::string out;
  1041. Status status;
  1042. std::unique_ptr<ParserHandler> json_writer =
  1043. json::NewJSONEncoder(&out, &status);
  1044. ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
  1045. EXPECT_THAT(status, StatusIs(Error::CBOR_UNSUPPORTED_VALUE, error_pos));
  1046. EXPECT_EQ("", out);
  1047. }
  1048. TEST(ParseCBORTest, InvalidString16Error) {
  1049. constexpr uint8_t kPayloadLen = 11;
  1050. std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope
  1051. 0xbf}; // map start
  1052. EncodeString8(SpanFrom("key"), &bytes);
  1053. size_t error_pos = bytes.size();
  1054. // a BYTE_STRING of length 5 as value; since we interpret these as string16,
  1055. // it's going to be invalid as each character would need two bytes, but
  1056. // 5 isn't divisible by 2.
  1057. bytes.push_back(2 << 5 | 5);
  1058. for (int ii = 0; ii < 5; ++ii)
  1059. bytes.push_back(' ');
  1060. EXPECT_EQ(kPayloadLen, bytes.size() - 6);
  1061. std::string out;
  1062. Status status;
  1063. std::unique_ptr<ParserHandler> json_writer =
  1064. json::NewJSONEncoder(&out, &status);
  1065. ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
  1066. EXPECT_THAT(status, StatusIs(Error::CBOR_INVALID_STRING16, error_pos));
  1067. EXPECT_EQ("", out);
  1068. }
  1069. TEST(ParseCBORTest, InvalidString8Error) {
  1070. constexpr uint8_t kPayloadLen = 6;
  1071. std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope
  1072. 0xbf}; // map start
  1073. EncodeString8(SpanFrom("key"), &bytes);
  1074. size_t error_pos = bytes.size();
  1075. // a STRING of length 5 as value, but we're at the end of the bytes array
  1076. // so it can't be decoded successfully.
  1077. bytes.push_back(3 << 5 | 5);
  1078. EXPECT_EQ(kPayloadLen, bytes.size() - 6);
  1079. std::string out;
  1080. Status status;
  1081. std::unique_ptr<ParserHandler> json_writer =
  1082. json::NewJSONEncoder(&out, &status);
  1083. ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
  1084. EXPECT_THAT(status, StatusIs(Error::CBOR_INVALID_STRING8, error_pos));
  1085. EXPECT_EQ("", out);
  1086. }
  1087. TEST(ParseCBORTest, InvalidBinaryError) {
  1088. constexpr uint8_t kPayloadLen = 9;
  1089. std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope
  1090. 0xbf}; // map start
  1091. EncodeString8(SpanFrom("key"), &bytes);
  1092. size_t error_pos = bytes.size();
  1093. bytes.push_back(6 << 5 | 22); // base64 hint for JSON; indicates binary
  1094. bytes.push_back(2 << 5 | 10); // BYTE_STRING (major type 2) of length 10
  1095. // Just two garbage bytes, not enough for the binary.
  1096. bytes.push_back(0x31);
  1097. bytes.push_back(0x23);
  1098. EXPECT_EQ(kPayloadLen, bytes.size() - 6);
  1099. std::string out;
  1100. Status status;
  1101. std::unique_ptr<ParserHandler> json_writer =
  1102. json::NewJSONEncoder(&out, &status);
  1103. ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
  1104. EXPECT_THAT(status, StatusIs(Error::CBOR_INVALID_BINARY, error_pos));
  1105. EXPECT_EQ("", out);
  1106. }
  1107. TEST(ParseCBORTest, InvalidDoubleError) {
  1108. constexpr uint8_t kPayloadLen = 8;
  1109. std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope
  1110. 0xbf}; // map start
  1111. EncodeString8(SpanFrom("key"), &bytes);
  1112. size_t error_pos = bytes.size();
  1113. bytes.push_back(7 << 5 | 27); // initial byte for double
  1114. // Just two garbage bytes, not enough to represent an actual double.
  1115. bytes.push_back(0x31);
  1116. bytes.push_back(0x23);
  1117. EXPECT_EQ(kPayloadLen, bytes.size() - 6);
  1118. std::string out;
  1119. Status status;
  1120. std::unique_ptr<ParserHandler> json_writer =
  1121. json::NewJSONEncoder(&out, &status);
  1122. ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
  1123. EXPECT_THAT(status, StatusIs(Error::CBOR_INVALID_DOUBLE, error_pos));
  1124. EXPECT_EQ("", out);
  1125. }
  1126. TEST(ParseCBORTest, InvalidSignedError) {
  1127. constexpr uint8_t kPayloadLen = 14;
  1128. std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope
  1129. 0xbf}; // map start
  1130. EncodeString8(SpanFrom("key"), &bytes);
  1131. size_t error_pos = bytes.size();
  1132. // uint64_t max is a perfectly fine value to encode as CBOR unsigned,
  1133. // but we don't support this since we only cover the int32_t range.
  1134. internals::WriteTokenStart(MajorType::UNSIGNED,
  1135. std::numeric_limits<uint64_t>::max(), &bytes);
  1136. EXPECT_EQ(kPayloadLen, bytes.size() - 6);
  1137. std::string out;
  1138. Status status;
  1139. std::unique_ptr<ParserHandler> json_writer =
  1140. json::NewJSONEncoder(&out, &status);
  1141. ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
  1142. EXPECT_THAT(status, StatusIs(Error::CBOR_INVALID_INT32, error_pos));
  1143. EXPECT_EQ("", out);
  1144. }
  1145. TEST(ParseCBORTest, TrailingJunk) {
  1146. constexpr uint8_t kPayloadLen = 12;
  1147. std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope
  1148. 0xbf}; // map start
  1149. EncodeString8(SpanFrom("key"), &bytes);
  1150. EncodeString8(SpanFrom("value"), &bytes);
  1151. bytes.push_back(0xff); // Up to here, it's a perfectly fine msg.
  1152. ASSERT_EQ(kPayloadLen, bytes.size() - 6);
  1153. size_t error_pos = bytes.size();
  1154. // Now write some trailing junk after the message.
  1155. EncodeString8(SpanFrom("trailing junk"), &bytes);
  1156. internals::WriteTokenStart(MajorType::UNSIGNED,
  1157. std::numeric_limits<uint64_t>::max(), &bytes);
  1158. std::string out;
  1159. Status status;
  1160. std::unique_ptr<ParserHandler> json_writer =
  1161. json::NewJSONEncoder(&out, &status);
  1162. ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
  1163. EXPECT_THAT(status, StatusIs(Error::CBOR_TRAILING_JUNK, error_pos));
  1164. EXPECT_EQ("", out);
  1165. }
  1166. TEST(ParseCBORTest, EnvelopeContentsLengthMismatch) {
  1167. constexpr uint8_t kPartialPayloadLen = 5;
  1168. std::vector<uint8_t> bytes = {0xd8, 0x5a, 0,
  1169. 0, 0, kPartialPayloadLen, // envelope
  1170. 0xbf}; // map start
  1171. EncodeString8(SpanFrom("key"), &bytes);
  1172. // kPartialPayloadLen would need to indicate the length of the entire map,
  1173. // all the way past the 0xff map stop character. Instead, it only covers
  1174. // a portion of the map.
  1175. EXPECT_EQ(bytes.size() - 6, kPartialPayloadLen);
  1176. EncodeString8(SpanFrom("value"), &bytes);
  1177. bytes.push_back(0xff); // map stop
  1178. std::string out;
  1179. Status status;
  1180. std::unique_ptr<ParserHandler> json_writer =
  1181. json::NewJSONEncoder(&out, &status);
  1182. ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
  1183. EXPECT_THAT(status, StatusIs(Error::CBOR_ENVELOPE_CONTENTS_LENGTH_MISMATCH,
  1184. bytes.size()));
  1185. EXPECT_EQ("", out);
  1186. }
  1187. // =============================================================================
  1188. // cbor::EnvelopeHeader - for parsing envelope headers
  1189. // =============================================================================
  1190. // Note most of converage for this is historically on a higher level of
  1191. // ParseCBOR(). This provides just a few essnetial scenarios for now.
  1192. template <typename T>
  1193. class EnvelopeHeaderTest : public ::testing::Test {};
  1194. TEST(EnvelopeHeaderTest, EnvelopeStartLegacy) {
  1195. std::vector<uint8_t> bytes = {0xd8, // Tag start
  1196. 0x5a, // Byte string, 4 bytes length
  1197. 0, 0, 0, 2, // Length
  1198. 0xbf, 0xff}; // map start / map end
  1199. auto result = EnvelopeHeader::Parse(SpanFrom(bytes));
  1200. ASSERT_THAT(result.status(), StatusIsOk());
  1201. EXPECT_THAT((*result).header_size(), Eq(6u));
  1202. EXPECT_THAT((*result).content_size(), Eq(2u));
  1203. EXPECT_THAT((*result).outer_size(), Eq(8u));
  1204. }
  1205. TEST(EnvelopeHeaderTest, EnvelopeStartSpecCompliant) {
  1206. std::vector<uint8_t> bytes = {0xd8, // Tag start
  1207. 0x18, // Tag type (CBOR)
  1208. 0x5a, // Byte string, 4 bytes length
  1209. 0, 0, 0, 2, // Length
  1210. 0xbf, 0xff}; // map start / map end
  1211. auto result = EnvelopeHeader::Parse(SpanFrom(bytes));
  1212. ASSERT_THAT(result.status(), StatusIsOk());
  1213. EXPECT_THAT((*result).header_size(), Eq(7u));
  1214. EXPECT_THAT((*result).content_size(), Eq(2u));
  1215. EXPECT_THAT((*result).outer_size(), Eq(9u));
  1216. }
  1217. TEST(EnvelopeHeaderTest, EnvelopeStartShortLen) {
  1218. std::vector<uint8_t> bytes = {0xd8, // Tag start
  1219. 0x18, // Tag type (CBOR)
  1220. 0x58, // Byte string, 1 byte length
  1221. 2, // Length
  1222. 0xbf, 0xff}; // map start / map end
  1223. auto result = EnvelopeHeader::Parse(SpanFrom(bytes));
  1224. ASSERT_THAT(result.status(), StatusIsOk());
  1225. EXPECT_THAT((*result).header_size(), Eq(4u));
  1226. EXPECT_THAT((*result).content_size(), Eq(2u));
  1227. EXPECT_THAT((*result).outer_size(), Eq(6u));
  1228. }
  1229. TEST(EnvelopeHeaderTest, ParseFragment) {
  1230. std::vector<uint8_t> bytes = {0xd8, // Tag start
  1231. 0x18, // Tag type (CBOR)
  1232. 0x5a, // Byte string, 4 bytes length
  1233. 0, 0, 0, 20, 0xbf}; // map start
  1234. auto result = EnvelopeHeader::ParseFromFragment(SpanFrom(bytes));
  1235. ASSERT_THAT(result.status(), StatusIsOk());
  1236. EXPECT_THAT((*result).header_size(), Eq(7u));
  1237. EXPECT_THAT((*result).content_size(), Eq(20u));
  1238. EXPECT_THAT((*result).outer_size(), Eq(27u));
  1239. result = EnvelopeHeader::Parse(SpanFrom(bytes));
  1240. ASSERT_THAT(result.status(),
  1241. StatusIs(Error::CBOR_ENVELOPE_CONTENTS_LENGTH_MISMATCH, 8));
  1242. }
  1243. // =============================================================================
  1244. // cbor::AppendString8EntryToMap - for limited in-place editing of messages
  1245. // =============================================================================
  1246. template <typename T>
  1247. class AppendString8EntryToMapTest : public ::testing::Test {};
  1248. using ContainerTestTypes = ::testing::Types<std::vector<uint8_t>, std::string>;
  1249. TYPED_TEST_SUITE(AppendString8EntryToMapTest, ContainerTestTypes);
  1250. TEST(AppendString8EntryToMapTest, AppendsEntrySuccessfully) {
  1251. constexpr uint8_t kPayloadLen = 12;
  1252. std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope
  1253. 0xbf}; // map start
  1254. size_t pos_before_payload = bytes.size() - 1;
  1255. EncodeString8(SpanFrom("key"), &bytes);
  1256. EncodeString8(SpanFrom("value"), &bytes);
  1257. bytes.push_back(0xff); // A perfectly fine cbor message.
  1258. EXPECT_EQ(kPayloadLen, bytes.size() - pos_before_payload);
  1259. std::vector<uint8_t> msg(bytes.begin(), bytes.end());
  1260. Status status =
  1261. AppendString8EntryToCBORMap(SpanFrom("foo"), SpanFrom("bar"), &msg);
  1262. EXPECT_THAT(status, StatusIsOk());
  1263. std::string out;
  1264. std::unique_ptr<ParserHandler> json_writer =
  1265. json::NewJSONEncoder(&out, &status);
  1266. ParseCBOR(SpanFrom(msg), json_writer.get());
  1267. EXPECT_EQ("{\"key\":\"value\",\"foo\":\"bar\"}", out);
  1268. EXPECT_THAT(status, StatusIsOk());
  1269. }
  1270. TYPED_TEST(AppendString8EntryToMapTest, AppendThreeEntries) {
  1271. std::vector<uint8_t> encoded = {
  1272. 0xd8, 0x5a, 0, 0, 0, 2, EncodeIndefiniteLengthMapStart(), EncodeStop()};
  1273. EXPECT_THAT(
  1274. AppendString8EntryToCBORMap(SpanFrom("key"), SpanFrom("value"), &encoded),
  1275. StatusIsOk());
  1276. EXPECT_THAT(AppendString8EntryToCBORMap(SpanFrom("key1"), SpanFrom("value1"),
  1277. &encoded),
  1278. StatusIsOk());
  1279. EXPECT_THAT(AppendString8EntryToCBORMap(SpanFrom("key2"), SpanFrom("value2"),
  1280. &encoded),
  1281. StatusIsOk());
  1282. TypeParam msg(encoded.begin(), encoded.end());
  1283. std::string out;
  1284. Status status;
  1285. std::unique_ptr<ParserHandler> json_writer =
  1286. json::NewJSONEncoder(&out, &status);
  1287. ParseCBOR(SpanFrom(msg), json_writer.get());
  1288. EXPECT_EQ("{\"key\":\"value\",\"key1\":\"value1\",\"key2\":\"value2\"}", out);
  1289. EXPECT_THAT(status, StatusIsOk());
  1290. }
  1291. TEST(AppendString8EntryToMapTest, MapStartExpected_Error) {
  1292. std::vector<uint8_t> msg = {
  1293. 0xd8, 0x5a, 0, 0, 0, 1, EncodeIndefiniteLengthArrayStart()};
  1294. Status status =
  1295. AppendString8EntryToCBORMap(SpanFrom("key"), SpanFrom("value"), &msg);
  1296. EXPECT_THAT(status, StatusIs(Error::CBOR_MAP_START_EXPECTED, 6u));
  1297. }
  1298. TEST(AppendString8EntryToMapTest, MapStopExpected_Error) {
  1299. std::vector<uint8_t> msg = {
  1300. 0xd8, 0x5a, 0, 0, 0, 2, EncodeIndefiniteLengthMapStart(), 42};
  1301. Status status =
  1302. AppendString8EntryToCBORMap(SpanFrom("key"), SpanFrom("value"), &msg);
  1303. EXPECT_THAT(status, StatusIs(Error::CBOR_MAP_STOP_EXPECTED, 7u));
  1304. }
  1305. TEST(AppendString8EntryToMapTest, InvalidEnvelope_Error) {
  1306. { // Second byte is wrong.
  1307. std::vector<uint8_t> msg = {
  1308. 0x5a, 0, 0, 0, 2, EncodeIndefiniteLengthMapStart(), EncodeStop(), 0};
  1309. Status status =
  1310. AppendString8EntryToCBORMap(SpanFrom("key"), SpanFrom("value"), &msg);
  1311. EXPECT_THAT(status, StatusIs(Error::CBOR_INVALID_ENVELOPE, 0u));
  1312. }
  1313. { // Second byte is wrong.
  1314. std::vector<uint8_t> msg = {
  1315. 0xd8, 0x7a, 0, 0, 0, 2, EncodeIndefiniteLengthMapStart(), EncodeStop()};
  1316. Status status =
  1317. AppendString8EntryToCBORMap(SpanFrom("key"), SpanFrom("value"), &msg);
  1318. EXPECT_THAT(status, StatusIs(Error::CBOR_INVALID_ENVELOPE, 1u));
  1319. }
  1320. { // Invalid envelope size example.
  1321. std::vector<uint8_t> msg = {
  1322. 0xd8, 0x5a, 0, 0, 0, 3, EncodeIndefiniteLengthMapStart(), EncodeStop(),
  1323. };
  1324. Status status =
  1325. AppendString8EntryToCBORMap(SpanFrom("key"), SpanFrom("value"), &msg);
  1326. EXPECT_THAT(status,
  1327. StatusIs(Error::CBOR_ENVELOPE_CONTENTS_LENGTH_MISMATCH, 8u));
  1328. }
  1329. { // Invalid envelope size example.
  1330. std::vector<uint8_t> msg = {
  1331. 0xd8, 0x5a, 0, 0, 0, 1, EncodeIndefiniteLengthMapStart(), EncodeStop(),
  1332. };
  1333. Status status =
  1334. AppendString8EntryToCBORMap(SpanFrom("key"), SpanFrom("value"), &msg);
  1335. EXPECT_THAT(status, StatusIs(Error::CBOR_INVALID_ENVELOPE, 0));
  1336. }
  1337. }
  1338. } // namespace cbor
  1339. } // namespace crdtp