• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
5 #include "encoding.h"
6 
7 #include <array>
8 #include <clocale>
9 #include <cmath>
10 #include <cstdlib>
11 #include <cstring>
12 #include <iomanip>
13 #include <iostream>
14 #include <sstream>
15 #include <string>
16 
17 #include "encoding_test_helper.h"
18 
19 using testing::ElementsAreArray;
20 
21 namespace v8_inspector_protocol_encoding {
22 
23 class TestPlatform : public json::Platform {
StrToD(const char * str,double * result) const24   bool StrToD(const char* str, double* result) const override {
25     // This is not thread-safe
26     // (see https://en.cppreference.com/w/cpp/locale/setlocale)
27     // but good enough for a unittest.
28     const char* saved_locale = std::setlocale(LC_NUMERIC, nullptr);
29     char* end;
30     *result = std::strtod(str, &end);
31     std::setlocale(LC_NUMERIC, saved_locale);
32     if (errno == ERANGE) {
33       // errno must be reset, e.g. see the example here:
34       // https://en.cppreference.com/w/cpp/string/byte/strtof
35       errno = 0;
36       return false;
37     }
38     return end == str + strlen(str);
39   }
40 
DToStr(double value) const41   std::unique_ptr<char[]> DToStr(double value) const override {
42     std::stringstream ss;
43     ss.imbue(std::locale("C"));
44     ss << value;
45     std::string str = ss.str();
46     std::unique_ptr<char[]> result(new char[str.size() + 1]);
47     memcpy(result.get(), str.c_str(), str.size() + 1);
48     return result;
49   }
50 };
51 
GetTestPlatform()52 const json::Platform& GetTestPlatform() {
53   static TestPlatform* platform = new TestPlatform;
54   return *platform;
55 }
56 
57 // =============================================================================
58 // span - sequence of bytes
59 // =============================================================================
60 
61 template <typename T>
62 class SpanTest : public ::testing::Test {};
63 
64 using TestTypes = ::testing::Types<uint8_t, uint16_t>;
65 TYPED_TEST_SUITE(SpanTest, TestTypes);
66 
TYPED_TEST(SpanTest,Empty)67 TYPED_TEST(SpanTest, Empty) {
68   span<TypeParam> empty;
69   EXPECT_TRUE(empty.empty());
70   EXPECT_EQ(0u, empty.size());
71   EXPECT_EQ(0u, empty.size_bytes());
72   EXPECT_EQ(empty.begin(), empty.end());
73 }
74 
TYPED_TEST(SpanTest,SingleItem)75 TYPED_TEST(SpanTest, SingleItem) {
76   TypeParam single_item = 42;
77   span<TypeParam> singular(&single_item, 1);
78   EXPECT_FALSE(singular.empty());
79   EXPECT_EQ(1u, singular.size());
80   EXPECT_EQ(sizeof(TypeParam), singular.size_bytes());
81   EXPECT_EQ(singular.begin() + 1, singular.end());
82   EXPECT_EQ(42, singular[0]);
83 }
84 
TYPED_TEST(SpanTest,FiveItems)85 TYPED_TEST(SpanTest, FiveItems) {
86   std::vector<TypeParam> test_input = {31, 32, 33, 34, 35};
87   span<TypeParam> five_items(test_input.data(), 5);
88   EXPECT_FALSE(five_items.empty());
89   EXPECT_EQ(5u, five_items.size());
90   EXPECT_EQ(sizeof(TypeParam) * 5, five_items.size_bytes());
91   EXPECT_EQ(five_items.begin() + 5, five_items.end());
92   EXPECT_EQ(31, five_items[0]);
93   EXPECT_EQ(32, five_items[1]);
94   EXPECT_EQ(33, five_items[2]);
95   EXPECT_EQ(34, five_items[3]);
96   EXPECT_EQ(35, five_items[4]);
97   span<TypeParam> three_items = five_items.subspan(2);
98   EXPECT_EQ(3u, three_items.size());
99   EXPECT_EQ(33, three_items[0]);
100   EXPECT_EQ(34, three_items[1]);
101   EXPECT_EQ(35, three_items[2]);
102   span<TypeParam> two_items = five_items.subspan(2, 2);
103   EXPECT_EQ(2u, two_items.size());
104   EXPECT_EQ(33, two_items[0]);
105   EXPECT_EQ(34, two_items[1]);
106 }
107 
TEST(SpanFromTest,FromConstCharAndLiteral)108 TEST(SpanFromTest, FromConstCharAndLiteral) {
109   // Testing this is useful because strlen(nullptr) is undefined.
110   EXPECT_EQ(nullptr, SpanFrom(nullptr).data());
111   EXPECT_EQ(0u, SpanFrom(nullptr).size());
112 
113   const char* kEmpty = "";
114   EXPECT_EQ(kEmpty, reinterpret_cast<const char*>(SpanFrom(kEmpty).data()));
115   EXPECT_EQ(0u, SpanFrom(kEmpty).size());
116 
117   const char* kFoo = "foo";
118   EXPECT_EQ(kFoo, reinterpret_cast<const char*>(SpanFrom(kFoo).data()));
119   EXPECT_EQ(3u, SpanFrom(kFoo).size());
120 
121   EXPECT_EQ(3u, SpanFrom("foo").size());
122 }
123 
124 // =============================================================================
125 // Status and Error codes
126 // =============================================================================
127 
TEST(StatusTest,StatusToASCIIString)128 TEST(StatusTest, StatusToASCIIString) {
129   Status ok_status;
130   EXPECT_EQ("OK", ok_status.ToASCIIString());
131   Status json_error(Error::JSON_PARSER_COLON_EXPECTED, 42);
132   EXPECT_EQ("JSON: colon expected at position 42", json_error.ToASCIIString());
133   Status cbor_error(Error::CBOR_TRAILING_JUNK, 21);
134   EXPECT_EQ("CBOR: trailing junk at position 21", cbor_error.ToASCIIString());
135 }
136 
137 namespace cbor {
138 
139 // =============================================================================
140 // Detecting CBOR content
141 // =============================================================================
142 
TEST(IsCBORMessage,SomeSmokeTests)143 TEST(IsCBORMessage, SomeSmokeTests) {
144   std::vector<uint8_t> empty;
145   EXPECT_FALSE(IsCBORMessage(SpanFrom(empty)));
146   std::vector<uint8_t> hello = {'H', 'e', 'l', 'o', ' ', 't',
147                                 'h', 'e', 'r', 'e', '!'};
148   EXPECT_FALSE(IsCBORMessage(SpanFrom(hello)));
149   std::vector<uint8_t> example = {0xd8, 0x5a, 0, 0, 0, 0};
150   EXPECT_TRUE(IsCBORMessage(SpanFrom(example)));
151   std::vector<uint8_t> one = {0xd8, 0x5a, 0, 0, 0, 1, 1};
152   EXPECT_TRUE(IsCBORMessage(SpanFrom(one)));
153 }
154 
155 // =============================================================================
156 // Encoding individual CBOR items
157 // cbor::CBORTokenizer - for parsing individual CBOR items
158 // =============================================================================
159 
160 //
161 // EncodeInt32 / CBORTokenTag::INT32
162 //
TEST(EncodeDecodeInt32Test,Roundtrips23)163 TEST(EncodeDecodeInt32Test, Roundtrips23) {
164   // This roundtrips the int32_t value 23 through the pair of EncodeInt32 /
165   // CBORTokenizer; this is interesting since 23 is encoded as a single byte.
166   std::vector<uint8_t> encoded;
167   EncodeInt32(23, &encoded);
168   // first three bits: major type = 0; remaining five bits: additional info =
169   // value 23.
170   EXPECT_THAT(encoded, ElementsAreArray(std::array<uint8_t, 1>{{23}}));
171 
172   // Reverse direction: decode with CBORTokenizer.
173   CBORTokenizer tokenizer(SpanFrom(encoded));
174   EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag());
175   EXPECT_EQ(23, tokenizer.GetInt32());
176   tokenizer.Next();
177   EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
178 }
179 
TEST(EncodeDecodeInt32Test,RoundtripsUint8)180 TEST(EncodeDecodeInt32Test, RoundtripsUint8) {
181   // This roundtrips the int32_t value 42 through the pair of EncodeInt32 /
182   // CBORTokenizer. This is different from Roundtrip23 because 42 is encoded
183   // in an extra byte after the initial one.
184   std::vector<uint8_t> encoded;
185   EncodeInt32(42, &encoded);
186   // first three bits: major type = 0;
187   // remaining five bits: additional info = 24, indicating payload is uint8.
188   EXPECT_THAT(encoded, ElementsAreArray(std::array<uint8_t, 2>{{24, 42}}));
189 
190   // Reverse direction: decode with CBORTokenizer.
191   CBORTokenizer tokenizer(SpanFrom(encoded));
192   EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag());
193   EXPECT_EQ(42, tokenizer.GetInt32());
194   tokenizer.Next();
195   EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
196 }
197 
TEST(EncodeDecodeInt32Test,RoundtripsUint16)198 TEST(EncodeDecodeInt32Test, RoundtripsUint16) {
199   // 500 is encoded as a uint16 after the initial byte.
200   std::vector<uint8_t> encoded;
201   EncodeInt32(500, &encoded);
202   // 1 for initial byte, 2 for uint16.
203   EXPECT_EQ(3u, encoded.size());
204   // first three bits: major type = 0;
205   // remaining five bits: additional info = 25, indicating payload is uint16.
206   EXPECT_EQ(25, encoded[0]);
207   EXPECT_EQ(0x01, encoded[1]);
208   EXPECT_EQ(0xf4, encoded[2]);
209 
210   // Reverse direction: decode with CBORTokenizer.
211   CBORTokenizer tokenizer(SpanFrom(encoded));
212   EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag());
213   EXPECT_EQ(500, tokenizer.GetInt32());
214   tokenizer.Next();
215   EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
216 }
217 
TEST(EncodeDecodeInt32Test,RoundtripsInt32Max)218 TEST(EncodeDecodeInt32Test, RoundtripsInt32Max) {
219   // std::numeric_limits<int32_t> is encoded as a uint32 after the initial byte.
220   std::vector<uint8_t> encoded;
221   EncodeInt32(std::numeric_limits<int32_t>::max(), &encoded);
222   // 1 for initial byte, 4 for the uint32.
223   // first three bits: major type = 0;
224   // remaining five bits: additional info = 26, indicating payload is uint32.
225   EXPECT_THAT(
226       encoded,
227       ElementsAreArray(std::array<uint8_t, 5>{{26, 0x7f, 0xff, 0xff, 0xff}}));
228 
229   // Reverse direction: decode with CBORTokenizer.
230   CBORTokenizer tokenizer(SpanFrom(encoded));
231   EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag());
232   EXPECT_EQ(std::numeric_limits<int32_t>::max(), tokenizer.GetInt32());
233   tokenizer.Next();
234   EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
235 }
236 
TEST(EncodeDecodeInt32Test,CantRoundtripUint32)237 TEST(EncodeDecodeInt32Test, CantRoundtripUint32) {
238   // 0xdeadbeef is a value which does not fit below
239   // std::numerical_limits<int32_t>::max(), so we can't encode
240   // it with EncodeInt32. However, CBOR does support this, so we
241   // encode it here manually with the internal routine, just to observe
242   // that it's considered an invalid int32 by CBORTokenizer.
243   std::vector<uint8_t> encoded;
244   internals::WriteTokenStart(MajorType::UNSIGNED, 0xdeadbeef, &encoded);
245   // 1 for initial byte, 4 for the uint32.
246   // first three bits: major type = 0;
247   // remaining five bits: additional info = 26, indicating payload is uint32.
248   EXPECT_THAT(
249       encoded,
250       ElementsAreArray(std::array<uint8_t, 5>{{26, 0xde, 0xad, 0xbe, 0xef}}));
251 
252   // Now try to decode; we treat this as an invalid INT32.
253   CBORTokenizer tokenizer(SpanFrom(encoded));
254   // 0xdeadbeef is > std::numerical_limits<int32_t>::max().
255   EXPECT_EQ(CBORTokenTag::ERROR_VALUE, tokenizer.TokenTag());
256   EXPECT_EQ(Error::CBOR_INVALID_INT32, tokenizer.Status().error);
257 }
258 
TEST(EncodeDecodeInt32Test,DecodeErrorCases)259 TEST(EncodeDecodeInt32Test, DecodeErrorCases) {
260   struct TestCase {
261     std::vector<uint8_t> data;
262     std::string msg;
263   };
264   std::vector<TestCase> tests{
265       {TestCase{
266            {24},
267            "additional info = 24 would require 1 byte of payload (but it's 0)"},
268        TestCase{{27, 0xaa, 0xbb, 0xcc},
269                 "additional info = 27 would require 8 bytes of payload (but "
270                 "it's 3)"},
271        TestCase{{29}, "additional info = 29 isn't recognized"}}};
272 
273   for (const TestCase& test : tests) {
274     SCOPED_TRACE(test.msg);
275     CBORTokenizer tokenizer(SpanFrom(test.data));
276     EXPECT_EQ(CBORTokenTag::ERROR_VALUE, tokenizer.TokenTag());
277     EXPECT_EQ(Error::CBOR_INVALID_INT32, tokenizer.Status().error);
278   }
279 }
280 
TEST(EncodeDecodeInt32Test,RoundtripsMinus24)281 TEST(EncodeDecodeInt32Test, RoundtripsMinus24) {
282   // This roundtrips the int32_t value -24 through the pair of EncodeInt32 /
283   // CBORTokenizer; this is interesting since -24 is encoded as
284   // a single byte as NEGATIVE, and it tests the specific encoding
285   // (note how for unsigned the single byte covers values up to 23).
286   // Additional examples are covered in RoundtripsAdditionalExamples.
287   std::vector<uint8_t> encoded;
288   EncodeInt32(-24, &encoded);
289   // first three bits: major type = 1; remaining five bits: additional info =
290   // value 23.
291   EXPECT_THAT(encoded, ElementsAreArray(std::array<uint8_t, 1>{{1 << 5 | 23}}));
292 
293   // Reverse direction: decode with CBORTokenizer.
294   CBORTokenizer tokenizer(SpanFrom(encoded));
295   EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag());
296   EXPECT_EQ(-24, tokenizer.GetInt32());
297   tokenizer.Next();
298   EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
299 }
300 
TEST(EncodeDecodeInt32Test,RoundtripsAdditionalNegativeExamples)301 TEST(EncodeDecodeInt32Test, RoundtripsAdditionalNegativeExamples) {
302   std::vector<int32_t> examples = {-1,
303                                    -10,
304                                    -24,
305                                    -25,
306                                    -300,
307                                    -30000,
308                                    -300 * 1000,
309                                    -1000 * 1000,
310                                    -1000 * 1000 * 1000,
311                                    std::numeric_limits<int32_t>::min()};
312   for (int32_t example : examples) {
313     SCOPED_TRACE(std::string("example ") + std::to_string(example));
314     std::vector<uint8_t> encoded;
315     EncodeInt32(example, &encoded);
316     CBORTokenizer tokenizer(SpanFrom(encoded));
317     EXPECT_EQ(CBORTokenTag::INT32, tokenizer.TokenTag());
318     EXPECT_EQ(example, tokenizer.GetInt32());
319     tokenizer.Next();
320     EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
321   }
322 }
323 
324 //
325 // EncodeString16 / CBORTokenTag::STRING16
326 //
TEST(EncodeDecodeString16Test,RoundtripsEmpty)327 TEST(EncodeDecodeString16Test, RoundtripsEmpty) {
328   // This roundtrips the empty utf16 string through the pair of EncodeString16 /
329   // CBORTokenizer.
330   std::vector<uint8_t> encoded;
331   EncodeString16(span<uint16_t>(), &encoded);
332   EXPECT_EQ(1u, encoded.size());
333   // first three bits: major type = 2; remaining five bits: additional info =
334   // size 0.
335   EXPECT_EQ(2 << 5, encoded[0]);
336 
337   // Reverse direction: decode with CBORTokenizer.
338   CBORTokenizer tokenizer(SpanFrom(encoded));
339   EXPECT_EQ(CBORTokenTag::STRING16, tokenizer.TokenTag());
340   span<uint8_t> decoded_string16_wirerep = tokenizer.GetString16WireRep();
341   EXPECT_TRUE(decoded_string16_wirerep.empty());
342   tokenizer.Next();
343   EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
344 }
345 
346 // On the wire, we STRING16 is encoded as little endian (least
347 // significant byte first). The host may or may not be little endian,
348 // so this routine follows the advice in
349 // https://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html.
String16WireRepToHost(span<uint8_t> in)350 std::vector<uint16_t> String16WireRepToHost(span<uint8_t> in) {
351   // must be even number of bytes.
352   CHECK_EQ(in.size() & 1, 0u);
353   std::vector<uint16_t> host_out;
354   for (size_t ii = 0; ii < in.size(); ii += 2)
355     host_out.push_back(in[ii + 1] << 8 | in[ii]);
356   return host_out;
357 }
358 
TEST(EncodeDecodeString16Test,RoundtripsHelloWorld)359 TEST(EncodeDecodeString16Test, RoundtripsHelloWorld) {
360   // This roundtrips the hello world message which is given here in utf16
361   // characters. 0xd83c, 0xdf0e: UTF16 encoding for the "Earth Globe Americas"
362   // character, ��.
363   std::array<uint16_t, 10> msg{
364       {'H', 'e', 'l', 'l', 'o', ',', ' ', 0xd83c, 0xdf0e, '.'}};
365   std::vector<uint8_t> encoded;
366   EncodeString16(span<uint16_t>(msg.data(), msg.size()), &encoded);
367   // This will be encoded as BYTE_STRING of length 20, so the 20 is encoded in
368   // the additional info part of the initial byte. Payload is two bytes for each
369   // UTF16 character.
370   uint8_t initial_byte = /*major type=*/2 << 5 | /*additional info=*/20;
371   std::array<uint8_t, 21> encoded_expected = {
372       {initial_byte, 'H', 0,   'e', 0,    'l',  0,    'l',  0,   'o', 0,
373        ',',          0,   ' ', 0,   0x3c, 0xd8, 0x0e, 0xdf, '.', 0}};
374   EXPECT_THAT(encoded, ElementsAreArray(encoded_expected));
375 
376   // Now decode to complete the roundtrip.
377   CBORTokenizer tokenizer(SpanFrom(encoded));
378   EXPECT_EQ(CBORTokenTag::STRING16, tokenizer.TokenTag());
379   std::vector<uint16_t> decoded =
380       String16WireRepToHost(tokenizer.GetString16WireRep());
381   EXPECT_THAT(decoded, ElementsAreArray(msg));
382   tokenizer.Next();
383   EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
384 
385   // For bonus points, we look at the decoded message in UTF8 as well so we can
386   // easily see it on the terminal screen.
387   std::string utf8_decoded = UTF16ToUTF8(SpanFrom(decoded));
388   EXPECT_EQ("Hello, ��.", utf8_decoded);
389 }
390 
TEST(EncodeDecodeString16Test,Roundtrips500)391 TEST(EncodeDecodeString16Test, Roundtrips500) {
392   // We roundtrip a message that has 250 16 bit values. Each of these are just
393   // set to their index. 250 is interesting because the cbor spec uses a
394   // BYTE_STRING of length 500 for one of their examples of how to encode the
395   // start of it (section 2.1) so it's easy for us to look at the first three
396   // bytes closely.
397   std::vector<uint16_t> two_fifty;
398   for (uint16_t ii = 0; ii < 250; ++ii)
399     two_fifty.push_back(ii);
400   std::vector<uint8_t> encoded;
401   EncodeString16(span<uint16_t>(two_fifty.data(), two_fifty.size()), &encoded);
402   EXPECT_EQ(3u + 250u * 2, encoded.size());
403   // Now check the first three bytes:
404   // Major type: 2 (BYTE_STRING)
405   // Additional information: 25, indicating size is represented by 2 bytes.
406   // Bytes 1 and 2 encode 500 (0x01f4).
407   EXPECT_EQ(2 << 5 | 25, encoded[0]);
408   EXPECT_EQ(0x01, encoded[1]);
409   EXPECT_EQ(0xf4, encoded[2]);
410 
411   // Now decode to complete the roundtrip.
412   CBORTokenizer tokenizer(SpanFrom(encoded));
413   EXPECT_EQ(CBORTokenTag::STRING16, tokenizer.TokenTag());
414   std::vector<uint16_t> decoded =
415       String16WireRepToHost(tokenizer.GetString16WireRep());
416   EXPECT_THAT(decoded, ElementsAreArray(two_fifty));
417   tokenizer.Next();
418   EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
419 }
420 
TEST(EncodeDecodeString16Test,ErrorCases)421 TEST(EncodeDecodeString16Test, ErrorCases) {
422   struct TestCase {
423     std::vector<uint8_t> data;
424     std::string msg;
425   };
426   std::vector<TestCase> tests{
427       {TestCase{{2 << 5 | 1, 'a'},
428                 "length must be divisible by 2 (but it's 1)"},
429        TestCase{{2 << 5 | 29}, "additional info = 29 isn't recognized"},
430        TestCase{{2 << 5 | 9, 1, 2, 3, 4, 5, 6, 7, 8},
431                 "length (9) points just past the end of the test case"},
432        TestCase{{2 << 5 | 27, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
433                  'a', 'b', 'c'},
434                 "large length pointing past the end of the test case"}}};
435   for (const TestCase& test : tests) {
436     SCOPED_TRACE(test.msg);
437     CBORTokenizer tokenizer(SpanFrom(test.data));
438     EXPECT_EQ(CBORTokenTag::ERROR_VALUE, tokenizer.TokenTag());
439     EXPECT_EQ(Error::CBOR_INVALID_STRING16, tokenizer.Status().error);
440   }
441 }
442 
443 //
444 // EncodeString8 / CBORTokenTag::STRING8
445 //
TEST(EncodeDecodeString8Test,RoundtripsHelloWorld)446 TEST(EncodeDecodeString8Test, RoundtripsHelloWorld) {
447   // This roundtrips the hello world message which is given here in utf8
448   // characters. �� is a four byte utf8 character.
449   std::string utf8_msg = "Hello, ��.";
450   std::vector<uint8_t> msg(utf8_msg.begin(), utf8_msg.end());
451   std::vector<uint8_t> encoded;
452   EncodeString8(SpanFrom(utf8_msg), &encoded);
453   // This will be encoded as STRING of length 12, so the 12 is encoded in
454   // the additional info part of the initial byte. Payload is one byte per
455   // utf8 byte.
456   uint8_t initial_byte = /*major type=*/3 << 5 | /*additional info=*/12;
457   std::array<uint8_t, 13> encoded_expected = {{initial_byte, 'H', 'e', 'l', 'l',
458                                                'o', ',', ' ', 0xF0, 0x9f, 0x8c,
459                                                0x8e, '.'}};
460   EXPECT_THAT(encoded, ElementsAreArray(encoded_expected));
461 
462   // Now decode to complete the roundtrip.
463   CBORTokenizer tokenizer(SpanFrom(encoded));
464   EXPECT_EQ(CBORTokenTag::STRING8, tokenizer.TokenTag());
465   std::vector<uint8_t> decoded(tokenizer.GetString8().begin(),
466                                tokenizer.GetString8().end());
467   EXPECT_THAT(decoded, ElementsAreArray(msg));
468   tokenizer.Next();
469   EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
470 }
471 
TEST(EncodeDecodeString8Test,ErrorCases)472 TEST(EncodeDecodeString8Test, ErrorCases) {
473   struct TestCase {
474     std::vector<uint8_t> data;
475     std::string msg;
476   };
477   std::vector<TestCase> tests{
478       {TestCase{{3 << 5 | 29}, "additional info = 29 isn't recognized"},
479        TestCase{{3 << 5 | 9, 1, 2, 3, 4, 5, 6, 7, 8},
480                 "length (9) points just past the end of the test case"},
481        TestCase{{3 << 5 | 27, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
482                  'a', 'b', 'c'},
483                 "large length pointing past the end of the test case"}}};
484   for (const TestCase& test : tests) {
485     SCOPED_TRACE(test.msg);
486     CBORTokenizer tokenizer(SpanFrom(test.data));
487     EXPECT_EQ(CBORTokenTag::ERROR_VALUE, tokenizer.TokenTag());
488     EXPECT_EQ(Error::CBOR_INVALID_STRING8, tokenizer.Status().error);
489   }
490 }
491 
TEST(EncodeFromLatin1Test,ConvertsToUTF8IfNeeded)492 TEST(EncodeFromLatin1Test, ConvertsToUTF8IfNeeded) {
493   std::vector<std::pair<std::string, std::string>> examples = {
494       {"Hello, world.", "Hello, world."},
495       {"Above: \xDC"
496        "ber",
497        "Above: Über"},
498       {"\xA5 500 are about \xA3 3.50; a y with umlaut is \xFF",
499        "¥ 500 are about £ 3.50; a y with umlaut is ÿ"}};
500 
501   for (const auto& example : examples) {
502     const std::string& latin1 = example.first;
503     const std::string& expected_utf8 = example.second;
504     std::vector<uint8_t> encoded;
505     EncodeFromLatin1(SpanFrom(latin1), &encoded);
506     CBORTokenizer tokenizer(SpanFrom(encoded));
507     EXPECT_EQ(CBORTokenTag::STRING8, tokenizer.TokenTag());
508     std::vector<uint8_t> decoded(tokenizer.GetString8().begin(),
509                                  tokenizer.GetString8().end());
510     std::string decoded_str(decoded.begin(), decoded.end());
511     EXPECT_THAT(decoded_str, testing::Eq(expected_utf8));
512   }
513 }
514 
TEST(EncodeFromUTF16Test,ConvertsToUTF8IfEasy)515 TEST(EncodeFromUTF16Test, ConvertsToUTF8IfEasy) {
516   std::vector<uint16_t> ascii = {'e', 'a', 's', 'y'};
517   std::vector<uint8_t> encoded;
518   EncodeFromUTF16(span<uint16_t>(ascii.data(), ascii.size()), &encoded);
519 
520   CBORTokenizer tokenizer(SpanFrom(encoded));
521   EXPECT_EQ(CBORTokenTag::STRING8, tokenizer.TokenTag());
522   std::vector<uint8_t> decoded(tokenizer.GetString8().begin(),
523                                tokenizer.GetString8().end());
524   std::string decoded_str(decoded.begin(), decoded.end());
525   EXPECT_THAT(decoded_str, testing::Eq("easy"));
526 }
527 
TEST(EncodeFromUTF16Test,EncodesAsString16IfNeeded)528 TEST(EncodeFromUTF16Test, EncodesAsString16IfNeeded) {
529   // Since this message contains non-ASCII characters, the routine is
530   // forced to encode as UTF16. We see this below by checking that the
531   // token tag is STRING16.
532   std::vector<uint16_t> msg = {'H', 'e', 'l',    'l',    'o',
533                                ',', ' ', 0xd83c, 0xdf0e, '.'};
534   std::vector<uint8_t> encoded;
535   EncodeFromUTF16(span<uint16_t>(msg.data(), msg.size()), &encoded);
536 
537   CBORTokenizer tokenizer(SpanFrom(encoded));
538   EXPECT_EQ(CBORTokenTag::STRING16, tokenizer.TokenTag());
539   std::vector<uint16_t> decoded =
540       String16WireRepToHost(tokenizer.GetString16WireRep());
541   std::string utf8_decoded = UTF16ToUTF8(SpanFrom(decoded));
542   EXPECT_EQ("Hello, ��.", utf8_decoded);
543 }
544 
545 //
546 // EncodeBinary / CBORTokenTag::BINARY
547 //
TEST(EncodeDecodeBinaryTest,RoundtripsHelloWorld)548 TEST(EncodeDecodeBinaryTest, RoundtripsHelloWorld) {
549   std::vector<uint8_t> binary = {'H', 'e', 'l', 'l', 'o', ',', ' ',
550                                  'w', 'o', 'r', 'l', 'd', '.'};
551   std::vector<uint8_t> encoded;
552   EncodeBinary(span<uint8_t>(binary.data(), binary.size()), &encoded);
553   // So, on the wire we see that the binary blob travels unmodified.
554   EXPECT_THAT(
555       encoded,
556       ElementsAreArray(std::array<uint8_t, 15>{
557           {(6 << 5 | 22),  // tag 22 indicating base64 interpretation in JSON
558            (2 << 5 | 13),  // BYTE_STRING (type 2) of length 13
559            'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '.'}}));
560   std::vector<uint8_t> decoded;
561   CBORTokenizer tokenizer(SpanFrom(encoded));
562   EXPECT_EQ(CBORTokenTag::BINARY, tokenizer.TokenTag());
563   EXPECT_EQ(0, static_cast<int>(tokenizer.Status().error));
564   decoded = std::vector<uint8_t>(tokenizer.GetBinary().begin(),
565                                  tokenizer.GetBinary().end());
566   EXPECT_THAT(decoded, ElementsAreArray(binary));
567   tokenizer.Next();
568   EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
569 }
570 
TEST(EncodeDecodeBinaryTest,ErrorCases)571 TEST(EncodeDecodeBinaryTest, ErrorCases) {
572   struct TestCase {
573     std::vector<uint8_t> data;
574     std::string msg;
575   };
576   std::vector<TestCase> tests{{TestCase{
577       {6 << 5 | 22,  // tag 22 indicating base64 interpretation in JSON
578        2 << 5 | 27,  // BYTE_STRING (type 2), followed by 8 bytes length
579        0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
580       "large length pointing past the end of the test case"}}};
581   for (const TestCase& test : tests) {
582     SCOPED_TRACE(test.msg);
583     CBORTokenizer tokenizer(SpanFrom(test.data));
584     EXPECT_EQ(CBORTokenTag::ERROR_VALUE, tokenizer.TokenTag());
585     EXPECT_EQ(Error::CBOR_INVALID_BINARY, tokenizer.Status().error);
586   }
587 }
588 
589 //
590 // EncodeDouble / CBORTokenTag::DOUBLE
591 //
TEST(EncodeDecodeDoubleTest,RoundtripsWikipediaExample)592 TEST(EncodeDecodeDoubleTest, RoundtripsWikipediaExample) {
593   // https://en.wikipedia.org/wiki/Double-precision_floating-point_format
594   // provides the example of a hex representation 3FD5 5555 5555 5555, which
595   // approximates 1/3.
596 
597   const double kOriginalValue = 1.0 / 3;
598   std::vector<uint8_t> encoded;
599   EncodeDouble(kOriginalValue, &encoded);
600   // first three bits: major type = 7; remaining five bits: additional info =
601   // value 27. This is followed by 8 bytes of payload (which match Wikipedia).
602   EXPECT_THAT(
603       encoded,
604       ElementsAreArray(std::array<uint8_t, 9>{
605           {7 << 5 | 27, 0x3f, 0xd5, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55}}));
606 
607   // Reverse direction: decode and compare with original value.
608   CBORTokenizer tokenizer(SpanFrom(encoded));
609   EXPECT_EQ(CBORTokenTag::DOUBLE, tokenizer.TokenTag());
610   EXPECT_THAT(tokenizer.GetDouble(), testing::DoubleEq(kOriginalValue));
611   tokenizer.Next();
612   EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
613 }
614 
TEST(EncodeDecodeDoubleTest,RoundtripsAdditionalExamples)615 TEST(EncodeDecodeDoubleTest, RoundtripsAdditionalExamples) {
616   std::vector<double> examples = {0.0,
617                                   1.0,
618                                   -1.0,
619                                   3.1415,
620                                   std::numeric_limits<double>::min(),
621                                   std::numeric_limits<double>::max(),
622                                   std::numeric_limits<double>::infinity(),
623                                   std::numeric_limits<double>::quiet_NaN()};
624   for (double example : examples) {
625     SCOPED_TRACE(std::string("example ") + std::to_string(example));
626     std::vector<uint8_t> encoded;
627     EncodeDouble(example, &encoded);
628     CBORTokenizer tokenizer(SpanFrom(encoded));
629     EXPECT_EQ(CBORTokenTag::DOUBLE, tokenizer.TokenTag());
630     if (std::isnan(example))
631       EXPECT_TRUE(std::isnan(tokenizer.GetDouble()));
632     else
633       EXPECT_THAT(tokenizer.GetDouble(), testing::DoubleEq(example));
634     tokenizer.Next();
635     EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag());
636   }
637 }
638 
639 // =============================================================================
640 // cbor::NewCBOREncoder - for encoding from a streaming parser
641 // =============================================================================
642 
EncodeUTF8ForTest(const std::string & key,std::vector<uint8_t> * out)643 void EncodeUTF8ForTest(const std::string& key, std::vector<uint8_t>* out) {
644   EncodeString8(SpanFrom(key), out);
645 }
TEST(JSONToCBOREncoderTest,SevenBitStrings)646 TEST(JSONToCBOREncoderTest, SevenBitStrings) {
647   // When a string can be represented as 7 bit ASCII, the encoder will use the
648   // STRING (major Type 3) type, so the actual characters end up as bytes on the
649   // wire.
650   std::vector<uint8_t> encoded;
651   Status status;
652   std::unique_ptr<StreamingParserHandler> encoder =
653       NewCBOREncoder(&encoded, &status);
654   std::vector<uint16_t> utf16 = {'f', 'o', 'o'};
655   encoder->HandleString16(span<uint16_t>(utf16.data(), utf16.size()));
656   EXPECT_EQ(Error::OK, status.error);
657   // Here we assert that indeed, seven bit strings are represented as
658   // bytes on the wire, "foo" is just "foo".
659   EXPECT_THAT(encoded,
660               ElementsAreArray(std::array<uint8_t, 4>{
661                   {/*major type 3*/ 3 << 5 | /*length*/ 3, 'f', 'o', 'o'}}));
662 }
663 
TEST(JsonCborRoundtrip,EncodingDecoding)664 TEST(JsonCborRoundtrip, EncodingDecoding) {
665   // Hits all the cases except binary and error in StreamingParserHandler, first
666   // parsing a JSON message into CBOR, then parsing it back from CBOR into JSON.
667   std::string json =
668       "{"
669       "\"string\":\"Hello, \\ud83c\\udf0e.\","
670       "\"double\":3.1415,"
671       "\"int\":1,"
672       "\"negative int\":-1,"
673       "\"bool\":true,"
674       "\"null\":null,"
675       "\"array\":[1,2,3]"
676       "}";
677   std::vector<uint8_t> encoded;
678   Status status;
679   std::unique_ptr<StreamingParserHandler> encoder =
680       NewCBOREncoder(&encoded, &status);
681   span<uint8_t> ascii_in = SpanFrom(json);
682   json::ParseJSON(GetTestPlatform(), ascii_in, encoder.get());
683   std::vector<uint8_t> expected = {
684       0xd8,            // envelope
685       0x5a,            // byte string with 32 bit length
686       0,    0, 0, 94,  // length is 94 bytes
687   };
688   expected.push_back(0xbf);  // indef length map start
689   EncodeString8(SpanFrom("string"), &expected);
690   // This is followed by the encoded string for "Hello, ��."
691   // So, it's the same bytes that we tested above in
692   // EncodeDecodeString16Test.RoundtripsHelloWorld.
693   expected.push_back(/*major type=*/2 << 5 | /*additional info=*/20);
694   for (uint8_t ch : std::array<uint8_t, 20>{
695            {'H', 0, 'e', 0, 'l',  0,    'l',  0,    'o', 0,
696             ',', 0, ' ', 0, 0x3c, 0xd8, 0x0e, 0xdf, '.', 0}})
697     expected.push_back(ch);
698   EncodeString8(SpanFrom("double"), &expected);
699   EncodeDouble(3.1415, &expected);
700   EncodeString8(SpanFrom("int"), &expected);
701   EncodeInt32(1, &expected);
702   EncodeString8(SpanFrom("negative int"), &expected);
703   EncodeInt32(-1, &expected);
704   EncodeString8(SpanFrom("bool"), &expected);
705   expected.push_back(7 << 5 | 21);  // RFC 7049 Section 2.3, Table 2: true
706   EncodeString8(SpanFrom("null"), &expected);
707   expected.push_back(7 << 5 | 22);  // RFC 7049 Section 2.3, Table 2: null
708   EncodeString8(SpanFrom("array"), &expected);
709   expected.push_back(0xd8);  // envelope
710   expected.push_back(0x5a);  // byte string with 32 bit length
711   // the length is 5 bytes (that's up to end indef length array below).
712   for (uint8_t ch : std::array<uint8_t, 4>{{0, 0, 0, 5}})
713     expected.push_back(ch);
714   expected.push_back(0x9f);  // RFC 7049 Section 2.2.1, indef length array start
715   expected.push_back(1);     // Three UNSIGNED values (easy since Major Type 0)
716   expected.push_back(2);
717   expected.push_back(3);
718   expected.push_back(0xff);  // End indef length array
719   expected.push_back(0xff);  // End indef length map
720   EXPECT_TRUE(status.ok());
721   EXPECT_THAT(encoded, ElementsAreArray(expected));
722 
723   // And now we roundtrip, decoding the message we just encoded.
724   std::string decoded;
725   std::unique_ptr<StreamingParserHandler> json_encoder =
726       NewJSONEncoder(&GetTestPlatform(), &decoded, &status);
727   ParseCBOR(span<uint8_t>(encoded.data(), encoded.size()), json_encoder.get());
728   EXPECT_EQ(Error::OK, status.error);
729   EXPECT_EQ(json, decoded);
730 }
731 
TEST(JsonCborRoundtrip,MoreRoundtripExamples)732 TEST(JsonCborRoundtrip, MoreRoundtripExamples) {
733   std::vector<std::string> examples = {
734       // Tests that after closing a nested objects, additional key/value pairs
735       // are considered.
736       "{\"foo\":{\"bar\":1},\"baz\":2}", "{\"foo\":[1,2,3],\"baz\":2}"};
737   for (const std::string& json : examples) {
738     SCOPED_TRACE(std::string("example: ") + json);
739     std::vector<uint8_t> encoded;
740     Status status;
741     std::unique_ptr<StreamingParserHandler> encoder =
742         NewCBOREncoder(&encoded, &status);
743     span<uint8_t> ascii_in = SpanFrom(json);
744     ParseJSON(GetTestPlatform(), ascii_in, encoder.get());
745     std::string decoded;
746     std::unique_ptr<StreamingParserHandler> json_writer =
747         NewJSONEncoder(&GetTestPlatform(), &decoded, &status);
748     ParseCBOR(span<uint8_t>(encoded.data(), encoded.size()), json_writer.get());
749     EXPECT_EQ(Error::OK, status.error);
750     EXPECT_EQ(json, decoded);
751   }
752 }
753 
TEST(JSONToCBOREncoderTest,HelloWorldBinary_WithTripToJson)754 TEST(JSONToCBOREncoderTest, HelloWorldBinary_WithTripToJson) {
755   // The StreamingParserHandler::HandleBinary is a special case: The JSON parser
756   // will never call this method, because JSON does not natively support the
757   // binary type. So, we can't fully roundtrip. However, the other direction
758   // works: binary will be rendered in JSON, as a base64 string. So, we make
759   // calls to the encoder directly here, to construct a message, and one of
760   // these calls is ::HandleBinary, to which we pass a "binary" string
761   // containing "Hello, world.".
762   std::vector<uint8_t> encoded;
763   Status status;
764   std::unique_ptr<StreamingParserHandler> encoder =
765       NewCBOREncoder(&encoded, &status);
766   encoder->HandleMapBegin();
767   // Emit a key.
768   std::vector<uint16_t> key = {'f', 'o', 'o'};
769   encoder->HandleString16(SpanFrom(key));
770   // Emit the binary payload, an arbitrary array of bytes that happens to
771   // be the ascii message "Hello, world.".
772   encoder->HandleBinary(SpanFrom(std::vector<uint8_t>{
773       'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '.'}));
774   encoder->HandleMapEnd();
775   EXPECT_EQ(Error::OK, status.error);
776 
777   // Now drive the json writer via the CBOR decoder.
778   std::string decoded;
779   std::unique_ptr<StreamingParserHandler> json_writer =
780       NewJSONEncoder(&GetTestPlatform(), &decoded, &status);
781   ParseCBOR(SpanFrom(encoded), json_writer.get());
782   EXPECT_EQ(Error::OK, status.error);
783   EXPECT_EQ(Status::npos(), status.pos);
784   // "Hello, world." in base64 is "SGVsbG8sIHdvcmxkLg==".
785   EXPECT_EQ("{\"foo\":\"SGVsbG8sIHdvcmxkLg==\"}", decoded);
786 }
787 
788 // =============================================================================
789 // cbor::ParseCBOR - for receiving streaming parser events for CBOR messages
790 // =============================================================================
791 
TEST(ParseCBORTest,ParseEmptyCBORMessage)792 TEST(ParseCBORTest, ParseEmptyCBORMessage) {
793   // An envelope starting with 0xd8, 0x5a, with the byte length
794   // of 2, containing a map that's empty (0xbf for map
795   // start, and 0xff for map end).
796   std::vector<uint8_t> in = {0xd8, 0x5a, 0, 0, 0, 2, 0xbf, 0xff};
797   std::string out;
798   Status status;
799   std::unique_ptr<StreamingParserHandler> json_writer =
800       NewJSONEncoder(&GetTestPlatform(), &out, &status);
801   ParseCBOR(span<uint8_t>(in.data(), in.size()), json_writer.get());
802   EXPECT_EQ(Error::OK, status.error);
803   EXPECT_EQ("{}", out);
804 }
805 
TEST(ParseCBORTest,ParseCBORHelloWorld)806 TEST(ParseCBORTest, ParseCBORHelloWorld) {
807   const uint8_t kPayloadLen = 27;
808   std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen};
809   bytes.push_back(0xbf);                            // start indef length map.
810   EncodeString8(SpanFrom("msg"), &bytes);           // key: msg
811   // Now write the value, the familiar "Hello, ��." where the globe is expressed
812   // as two utf16 chars.
813   bytes.push_back(/*major type=*/2 << 5 | /*additional info=*/20);
814   for (uint8_t ch : std::array<uint8_t, 20>{
815            {'H', 0, 'e', 0, 'l',  0,    'l',  0,    'o', 0,
816             ',', 0, ' ', 0, 0x3c, 0xd8, 0x0e, 0xdf, '.', 0}})
817     bytes.push_back(ch);
818   bytes.push_back(0xff);  // stop byte
819   EXPECT_EQ(kPayloadLen, bytes.size() - 6);
820 
821   std::string out;
822   Status status;
823   std::unique_ptr<StreamingParserHandler> json_writer =
824       NewJSONEncoder(&GetTestPlatform(), &out, &status);
825   ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
826   EXPECT_EQ(Error::OK, status.error);
827   EXPECT_EQ("{\"msg\":\"Hello, \\ud83c\\udf0e.\"}", out);
828 }
829 
TEST(ParseCBORTest,UTF8IsSupportedInKeys)830 TEST(ParseCBORTest, UTF8IsSupportedInKeys) {
831   const uint8_t kPayloadLen = 11;
832   std::vector<uint8_t> bytes = {cbor::InitialByteForEnvelope(),
833                                 cbor::InitialByteFor32BitLengthByteString(),
834                                 0,
835                                 0,
836                                 0,
837                                 kPayloadLen};
838   bytes.push_back(cbor::EncodeIndefiniteLengthMapStart());
839   // Two UTF16 chars.
840   EncodeString8(SpanFrom("��"), &bytes);
841   // Can be encoded as a single UTF16 char.
842   EncodeString8(SpanFrom("☾"), &bytes);
843   bytes.push_back(cbor::EncodeStop());
844   EXPECT_EQ(kPayloadLen, bytes.size() - 6);
845 
846   std::string out;
847   Status status;
848   std::unique_ptr<StreamingParserHandler> json_writer =
849       NewJSONEncoder(&GetTestPlatform(), &out, &status);
850   ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
851   EXPECT_EQ(Error::OK, status.error);
852   EXPECT_EQ("{\"\\ud83c\\udf0e\":\"\\u263e\"}", out);
853 }
854 
TEST(ParseCBORTest,NoInputError)855 TEST(ParseCBORTest, NoInputError) {
856   std::vector<uint8_t> in = {};
857   std::string out;
858   Status status;
859   std::unique_ptr<StreamingParserHandler> json_writer =
860       NewJSONEncoder(&GetTestPlatform(), &out, &status);
861   ParseCBOR(span<uint8_t>(in.data(), in.size()), json_writer.get());
862   EXPECT_EQ(Error::CBOR_NO_INPUT, status.error);
863   EXPECT_EQ("", out);
864 }
865 
TEST(ParseCBORTest,InvalidStartByteError)866 TEST(ParseCBORTest, InvalidStartByteError) {
867   // Here we test that some actual json, which usually starts with {,
868   // is not considered CBOR. CBOR messages must start with 0x5a, the
869   // envelope start byte.
870   std::string json = "{\"msg\": \"Hello, world.\"}";
871   std::string out;
872   Status status;
873   std::unique_ptr<StreamingParserHandler> json_writer =
874       NewJSONEncoder(&GetTestPlatform(), &out, &status);
875   ParseCBOR(SpanFrom(json), json_writer.get());
876   EXPECT_EQ(Error::CBOR_INVALID_START_BYTE, status.error);
877   EXPECT_EQ("", out);
878 }
879 
TEST(ParseCBORTest,UnexpectedEofExpectedValueError)880 TEST(ParseCBORTest, UnexpectedEofExpectedValueError) {
881   constexpr uint8_t kPayloadLen = 5;
882   std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen,  // envelope
883                                 0xbf};                             // map start
884   // A key; so value would be next.
885   EncodeString8(SpanFrom("key"), &bytes);
886   EXPECT_EQ(kPayloadLen, bytes.size() - 6);
887   std::string out;
888   Status status;
889   std::unique_ptr<StreamingParserHandler> json_writer =
890       NewJSONEncoder(&GetTestPlatform(), &out, &status);
891   ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
892   EXPECT_EQ(Error::CBOR_UNEXPECTED_EOF_EXPECTED_VALUE, status.error);
893   EXPECT_EQ(bytes.size(), status.pos);
894   EXPECT_EQ("", out);
895 }
896 
TEST(ParseCBORTest,UnexpectedEofInArrayError)897 TEST(ParseCBORTest, UnexpectedEofInArrayError) {
898   constexpr uint8_t kPayloadLen = 8;
899   std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen,  // envelope
900                                 0xbf};  // The byte for starting a map.
901   // A key; so value would be next.
902   EncodeString8(SpanFrom("array"), &bytes);
903   bytes.push_back(0x9f);  // byte for indefinite length array start.
904   EXPECT_EQ(kPayloadLen, bytes.size() - 6);
905   std::string out;
906   Status status;
907   std::unique_ptr<StreamingParserHandler> json_writer =
908       NewJSONEncoder(&GetTestPlatform(), &out, &status);
909   ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
910   EXPECT_EQ(Error::CBOR_UNEXPECTED_EOF_IN_ARRAY, status.error);
911   EXPECT_EQ(bytes.size(), status.pos);
912   EXPECT_EQ("", out);
913 }
914 
TEST(ParseCBORTest,UnexpectedEofInMapError)915 TEST(ParseCBORTest, UnexpectedEofInMapError) {
916   constexpr uint8_t kPayloadLen = 1;
917   std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen,  // envelope
918                                 0xbf};  // The byte for starting a map.
919   EXPECT_EQ(kPayloadLen, bytes.size() - 6);
920   std::string out;
921   Status status;
922   std::unique_ptr<StreamingParserHandler> json_writer =
923       NewJSONEncoder(&GetTestPlatform(), &out, &status);
924   ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
925   EXPECT_EQ(Error::CBOR_UNEXPECTED_EOF_IN_MAP, status.error);
926   EXPECT_EQ(7u, status.pos);
927   EXPECT_EQ("", out);
928 }
929 
TEST(ParseCBORTest,InvalidMapKeyError)930 TEST(ParseCBORTest, InvalidMapKeyError) {
931   constexpr uint8_t kPayloadLen = 2;
932   std::vector<uint8_t> bytes = {0xd8,       0x5a, 0,
933                                 0,          0,    kPayloadLen,  // envelope
934                                 0xbf,                           // map start
935                                 7 << 5 | 22};  // null (not a valid map key)
936   EXPECT_EQ(kPayloadLen, bytes.size() - 6);
937   std::string out;
938   Status status;
939   std::unique_ptr<StreamingParserHandler> json_writer =
940       NewJSONEncoder(&GetTestPlatform(), &out, &status);
941   ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
942   EXPECT_EQ(Error::CBOR_INVALID_MAP_KEY, status.error);
943   EXPECT_EQ(7u, status.pos);
944   EXPECT_EQ("", out);
945 }
946 
MakeNestedCBOR(int depth)947 std::vector<uint8_t> MakeNestedCBOR(int depth) {
948   std::vector<uint8_t> bytes;
949   std::vector<EnvelopeEncoder> envelopes;
950   for (int ii = 0; ii < depth; ++ii) {
951     envelopes.emplace_back();
952     envelopes.back().EncodeStart(&bytes);
953     bytes.push_back(0xbf);  // indef length map start
954     EncodeString8(SpanFrom("key"), &bytes);
955   }
956   EncodeString8(SpanFrom("innermost_value"), &bytes);
957   for (int ii = 0; ii < depth; ++ii) {
958     bytes.push_back(0xff);  // stop byte, finishes map.
959     envelopes.back().EncodeStop(&bytes);
960     envelopes.pop_back();
961   }
962   return bytes;
963 }
964 
TEST(ParseCBORTest,StackLimitExceededError)965 TEST(ParseCBORTest, StackLimitExceededError) {
966   {  // Depth 3: no stack limit exceeded error and is easy to inspect.
967     std::vector<uint8_t> bytes = MakeNestedCBOR(3);
968     std::string out;
969     Status status;
970     std::unique_ptr<StreamingParserHandler> json_writer =
971         NewJSONEncoder(&GetTestPlatform(), &out, &status);
972     ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
973     EXPECT_EQ(Error::OK, status.error);
974     EXPECT_EQ(Status::npos(), status.pos);
975     EXPECT_EQ("{\"key\":{\"key\":{\"key\":\"innermost_value\"}}}", out);
976   }
977   {  // Depth 300: no stack limit exceeded.
978     std::vector<uint8_t> bytes = MakeNestedCBOR(300);
979     std::string out;
980     Status status;
981     std::unique_ptr<StreamingParserHandler> json_writer =
982         NewJSONEncoder(&GetTestPlatform(), &out, &status);
983     ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
984     EXPECT_EQ(Error::OK, status.error);
985     EXPECT_EQ(Status::npos(), status.pos);
986   }
987 
988   // We just want to know the length of one opening map so we can compute
989   // where the error is encountered. So we look at a small example and find
990   // the second envelope start.
991   std::vector<uint8_t> small_example = MakeNestedCBOR(3);
992   size_t opening_segment_size = 1;  // Start after the first envelope start.
993   while (opening_segment_size < small_example.size() &&
994          small_example[opening_segment_size] != 0xd8)
995     opening_segment_size++;
996 
997   {  // Depth 301: limit exceeded.
998     std::vector<uint8_t> bytes = MakeNestedCBOR(301);
999     std::string out;
1000     Status status;
1001     std::unique_ptr<StreamingParserHandler> json_writer =
1002         NewJSONEncoder(&GetTestPlatform(), &out, &status);
1003     ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
1004     EXPECT_EQ(Error::CBOR_STACK_LIMIT_EXCEEDED, status.error);
1005     EXPECT_EQ(opening_segment_size * 301, status.pos);
1006   }
1007   {  // Depth 320: still limit exceeded, and at the same pos as for 1001
1008     std::vector<uint8_t> bytes = MakeNestedCBOR(320);
1009     std::string out;
1010     Status status;
1011     std::unique_ptr<StreamingParserHandler> json_writer =
1012         NewJSONEncoder(&GetTestPlatform(), &out, &status);
1013     ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
1014     EXPECT_EQ(Error::CBOR_STACK_LIMIT_EXCEEDED, status.error);
1015     EXPECT_EQ(opening_segment_size * 301, status.pos);
1016   }
1017 }
1018 
TEST(ParseCBORTest,UnsupportedValueError)1019 TEST(ParseCBORTest, UnsupportedValueError) {
1020   constexpr uint8_t kPayloadLen = 6;
1021   std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen,  // envelope
1022                                 0xbf};                             // map start
1023   EncodeString8(SpanFrom("key"), &bytes);
1024   size_t error_pos = bytes.size();
1025   bytes.push_back(6 << 5 | 5);  // tags aren't supported yet.
1026   EXPECT_EQ(kPayloadLen, bytes.size() - 6);
1027 
1028   std::string out;
1029   Status status;
1030   std::unique_ptr<StreamingParserHandler> json_writer =
1031       NewJSONEncoder(&GetTestPlatform(), &out, &status);
1032   ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
1033   EXPECT_EQ(Error::CBOR_UNSUPPORTED_VALUE, status.error);
1034   EXPECT_EQ(error_pos, status.pos);
1035   EXPECT_EQ("", out);
1036 }
1037 
TEST(ParseCBORTest,InvalidString16Error)1038 TEST(ParseCBORTest, InvalidString16Error) {
1039   constexpr uint8_t kPayloadLen = 11;
1040   std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen,  // envelope
1041                                 0xbf};                             // map start
1042   EncodeString8(SpanFrom("key"), &bytes);
1043   size_t error_pos = bytes.size();
1044   // a BYTE_STRING of length 5 as value; since we interpret these as string16,
1045   // it's going to be invalid as each character would need two bytes, but
1046   // 5 isn't divisible by 2.
1047   bytes.push_back(2 << 5 | 5);
1048   for (int ii = 0; ii < 5; ++ii)
1049     bytes.push_back(' ');
1050   EXPECT_EQ(kPayloadLen, bytes.size() - 6);
1051   std::string out;
1052   Status status;
1053   std::unique_ptr<StreamingParserHandler> json_writer =
1054       NewJSONEncoder(&GetTestPlatform(), &out, &status);
1055   ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
1056   EXPECT_EQ(Error::CBOR_INVALID_STRING16, status.error);
1057   EXPECT_EQ(error_pos, status.pos);
1058   EXPECT_EQ("", out);
1059 }
1060 
TEST(ParseCBORTest,InvalidString8Error)1061 TEST(ParseCBORTest, InvalidString8Error) {
1062   constexpr uint8_t kPayloadLen = 6;
1063   std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen,  // envelope
1064                                 0xbf};                             // map start
1065   EncodeString8(SpanFrom("key"), &bytes);
1066   size_t error_pos = bytes.size();
1067   // a STRING of length 5 as value, but we're at the end of the bytes array
1068   // so it can't be decoded successfully.
1069   bytes.push_back(3 << 5 | 5);
1070   EXPECT_EQ(kPayloadLen, bytes.size() - 6);
1071   std::string out;
1072   Status status;
1073   std::unique_ptr<StreamingParserHandler> json_writer =
1074       NewJSONEncoder(&GetTestPlatform(), &out, &status);
1075   ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
1076   EXPECT_EQ(Error::CBOR_INVALID_STRING8, status.error);
1077   EXPECT_EQ(error_pos, status.pos);
1078   EXPECT_EQ("", out);
1079 }
1080 
TEST(ParseCBORTest,InvalidBinaryError)1081 TEST(ParseCBORTest, InvalidBinaryError) {
1082   constexpr uint8_t kPayloadLen = 9;
1083   std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen,  // envelope
1084                                 0xbf};                             // map start
1085   EncodeString8(SpanFrom("key"), &bytes);
1086   size_t error_pos = bytes.size();
1087   bytes.push_back(6 << 5 | 22);  // base64 hint for JSON; indicates binary
1088   bytes.push_back(2 << 5 | 10);  // BYTE_STRING (major type 2) of length 10
1089   // Just two garbage bytes, not enough for the binary.
1090   bytes.push_back(0x31);
1091   bytes.push_back(0x23);
1092   EXPECT_EQ(kPayloadLen, bytes.size() - 6);
1093   std::string out;
1094   Status status;
1095   std::unique_ptr<StreamingParserHandler> json_writer =
1096       NewJSONEncoder(&GetTestPlatform(), &out, &status);
1097   ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
1098   EXPECT_EQ(Error::CBOR_INVALID_BINARY, status.error);
1099   EXPECT_EQ(error_pos, status.pos);
1100   EXPECT_EQ("", out);
1101 }
1102 
TEST(ParseCBORTest,InvalidDoubleError)1103 TEST(ParseCBORTest, InvalidDoubleError) {
1104   constexpr uint8_t kPayloadLen = 8;
1105   std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen,  // envelope
1106                                 0xbf};                             // map start
1107   EncodeString8(SpanFrom("key"), &bytes);
1108   size_t error_pos = bytes.size();
1109   bytes.push_back(7 << 5 | 27);  // initial byte for double
1110   // Just two garbage bytes, not enough to represent an actual double.
1111   bytes.push_back(0x31);
1112   bytes.push_back(0x23);
1113   EXPECT_EQ(kPayloadLen, bytes.size() - 6);
1114   std::string out;
1115   Status status;
1116   std::unique_ptr<StreamingParserHandler> json_writer =
1117       NewJSONEncoder(&GetTestPlatform(), &out, &status);
1118   ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
1119   EXPECT_EQ(Error::CBOR_INVALID_DOUBLE, status.error);
1120   EXPECT_EQ(error_pos, status.pos);
1121   EXPECT_EQ("", out);
1122 }
1123 
TEST(ParseCBORTest,InvalidSignedError)1124 TEST(ParseCBORTest, InvalidSignedError) {
1125   constexpr uint8_t kPayloadLen = 14;
1126   std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen,  // envelope
1127                                 0xbf};                             // map start
1128   EncodeString8(SpanFrom("key"), &bytes);
1129   size_t error_pos = bytes.size();
1130   // uint64_t max is a perfectly fine value to encode as CBOR unsigned,
1131   // but we don't support this since we only cover the int32_t range.
1132   internals::WriteTokenStart(MajorType::UNSIGNED,
1133                              std::numeric_limits<uint64_t>::max(), &bytes);
1134   EXPECT_EQ(kPayloadLen, bytes.size() - 6);
1135   std::string out;
1136   Status status;
1137   std::unique_ptr<StreamingParserHandler> json_writer =
1138       NewJSONEncoder(&GetTestPlatform(), &out, &status);
1139   ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
1140   EXPECT_EQ(Error::CBOR_INVALID_INT32, status.error);
1141   EXPECT_EQ(error_pos, status.pos);
1142   EXPECT_EQ("", out);
1143 }
1144 
TEST(ParseCBORTest,TrailingJunk)1145 TEST(ParseCBORTest, TrailingJunk) {
1146   constexpr uint8_t kPayloadLen = 35;
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   size_t error_pos = bytes.size();
1153   EncodeString8(SpanFrom("trailing junk"), &bytes);
1154 
1155   internals::WriteTokenStart(MajorType::UNSIGNED,
1156                              std::numeric_limits<uint64_t>::max(), &bytes);
1157   EXPECT_EQ(kPayloadLen, bytes.size() - 6);
1158   std::string out;
1159   Status status;
1160   std::unique_ptr<StreamingParserHandler> json_writer =
1161       NewJSONEncoder(&GetTestPlatform(), &out, &status);
1162   ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get());
1163   EXPECT_EQ(Error::CBOR_TRAILING_JUNK, status.error);
1164   EXPECT_EQ(error_pos, status.pos);
1165   EXPECT_EQ("", out);
1166 }
1167 
1168 // =============================================================================
1169 // cbor::AppendString8EntryToMap - for limited in-place editing of messages
1170 // =============================================================================
1171 
1172 template <typename T>
1173 class AppendString8EntryToMapTest : public ::testing::Test {};
1174 
1175 using ContainerTestTypes = ::testing::Types<std::vector<uint8_t>, std::string>;
1176 TYPED_TEST_SUITE(AppendString8EntryToMapTest, ContainerTestTypes);
1177 
TYPED_TEST(AppendString8EntryToMapTest,AppendsEntrySuccessfully)1178 TYPED_TEST(AppendString8EntryToMapTest, AppendsEntrySuccessfully) {
1179   constexpr uint8_t kPayloadLen = 12;
1180   std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen,  // envelope
1181                                 0xbf};                             // map start
1182   size_t pos_before_payload = bytes.size() - 1;
1183   EncodeString8(SpanFrom("key"), &bytes);
1184   EncodeString8(SpanFrom("value"), &bytes);
1185   bytes.push_back(0xff);  // A perfectly fine cbor message.
1186   EXPECT_EQ(kPayloadLen, bytes.size() - pos_before_payload);
1187 
1188   TypeParam msg(bytes.begin(), bytes.end());
1189 
1190   Status status =
1191       AppendString8EntryToCBORMap(SpanFrom("foo"), SpanFrom("bar"), &msg);
1192   EXPECT_EQ(Error::OK, status.error);
1193   EXPECT_EQ(Status::npos(), status.pos);
1194   std::string out;
1195   std::unique_ptr<StreamingParserHandler> json_writer =
1196       NewJSONEncoder(&GetTestPlatform(), &out, &status);
1197   ParseCBOR(SpanFrom(msg), json_writer.get());
1198   EXPECT_EQ("{\"key\":\"value\",\"foo\":\"bar\"}", out);
1199   EXPECT_EQ(Error::OK, status.error);
1200   EXPECT_EQ(Status::npos(), status.pos);
1201 }
1202 
TYPED_TEST(AppendString8EntryToMapTest,AppendThreeEntries)1203 TYPED_TEST(AppendString8EntryToMapTest, AppendThreeEntries) {
1204   std::vector<uint8_t> encoded = {
1205       0xd8, 0x5a, 0, 0, 0, 2, EncodeIndefiniteLengthMapStart(), EncodeStop()};
1206   EXPECT_EQ(Error::OK, AppendString8EntryToCBORMap(SpanFrom("key"),
1207                                                    SpanFrom("value"), &encoded)
1208                            .error);
1209   EXPECT_EQ(Error::OK, AppendString8EntryToCBORMap(SpanFrom("key1"),
1210                                                    SpanFrom("value1"), &encoded)
1211                            .error);
1212   EXPECT_EQ(Error::OK, AppendString8EntryToCBORMap(SpanFrom("key2"),
1213                                                    SpanFrom("value2"), &encoded)
1214                            .error);
1215   TypeParam msg(encoded.begin(), encoded.end());
1216   std::string out;
1217   Status status;
1218   std::unique_ptr<StreamingParserHandler> json_writer =
1219       NewJSONEncoder(&GetTestPlatform(), &out, &status);
1220   ParseCBOR(SpanFrom(msg), json_writer.get());
1221   EXPECT_EQ("{\"key\":\"value\",\"key1\":\"value1\",\"key2\":\"value2\"}", out);
1222   EXPECT_EQ(Error::OK, status.error);
1223   EXPECT_EQ(Status::npos(), status.pos);
1224 }
1225 
TYPED_TEST(AppendString8EntryToMapTest,MapStartExpected_Error)1226 TYPED_TEST(AppendString8EntryToMapTest, MapStartExpected_Error) {
1227   std::vector<uint8_t> bytes = {
1228       0xd8, 0x5a, 0, 0, 0, 1, EncodeIndefiniteLengthArrayStart()};
1229   TypeParam msg(bytes.begin(), bytes.end());
1230   Status status =
1231       AppendString8EntryToCBORMap(SpanFrom("key"), SpanFrom("value"), &msg);
1232   EXPECT_EQ(Error::CBOR_MAP_START_EXPECTED, status.error);
1233   EXPECT_EQ(6u, status.pos);
1234 }
1235 
TYPED_TEST(AppendString8EntryToMapTest,MapStopExpected_Error)1236 TYPED_TEST(AppendString8EntryToMapTest, MapStopExpected_Error) {
1237   std::vector<uint8_t> bytes = {
1238       0xd8, 0x5a, 0, 0, 0, 2, EncodeIndefiniteLengthMapStart(), 42};
1239   TypeParam msg(bytes.begin(), bytes.end());
1240   Status status =
1241       AppendString8EntryToCBORMap(SpanFrom("key"), SpanFrom("value"), &msg);
1242   EXPECT_EQ(Error::CBOR_MAP_STOP_EXPECTED, status.error);
1243   EXPECT_EQ(7u, status.pos);
1244 }
1245 
TYPED_TEST(AppendString8EntryToMapTest,InvalidEnvelope_Error)1246 TYPED_TEST(AppendString8EntryToMapTest, InvalidEnvelope_Error) {
1247   {  // Second byte is wrong.
1248     std::vector<uint8_t> bytes = {
1249         0x5a, 0, 0, 0, 2, EncodeIndefiniteLengthMapStart(), EncodeStop(), 0};
1250     TypeParam msg(bytes.begin(), bytes.end());
1251     Status status =
1252         AppendString8EntryToCBORMap(SpanFrom("key"), SpanFrom("value"), &msg);
1253     EXPECT_EQ(Error::CBOR_INVALID_ENVELOPE, status.error);
1254     EXPECT_EQ(0u, status.pos);
1255   }
1256   {  // Second byte is wrong.
1257     std::vector<uint8_t> bytes = {
1258         0xd8, 0x7a, 0, 0, 0, 2, EncodeIndefiniteLengthMapStart(), EncodeStop()};
1259     TypeParam msg(bytes.begin(), bytes.end());
1260     Status status =
1261         AppendString8EntryToCBORMap(SpanFrom("key"), SpanFrom("value"), &msg);
1262     EXPECT_EQ(Error::CBOR_INVALID_ENVELOPE, status.error);
1263     EXPECT_EQ(0u, status.pos);
1264   }
1265   {  // Invalid envelope size example.
1266     std::vector<uint8_t> bytes = {
1267         0xd8, 0x5a, 0, 0, 0, 3, EncodeIndefiniteLengthMapStart(), EncodeStop(),
1268     };
1269     TypeParam msg(bytes.begin(), bytes.end());
1270     Status status =
1271         AppendString8EntryToCBORMap(SpanFrom("key"), SpanFrom("value"), &msg);
1272     EXPECT_EQ(Error::CBOR_INVALID_ENVELOPE, status.error);
1273     EXPECT_EQ(0u, status.pos);
1274   }
1275   {  // Invalid envelope size example.
1276     std::vector<uint8_t> bytes = {
1277         0xd8, 0x5a, 0, 0, 0, 1, EncodeIndefiniteLengthMapStart(), EncodeStop(),
1278     };
1279     TypeParam msg(bytes.begin(), bytes.end());
1280     Status status =
1281         AppendString8EntryToCBORMap(SpanFrom("key"), SpanFrom("value"), &msg);
1282     EXPECT_EQ(Error::CBOR_INVALID_ENVELOPE, status.error);
1283     EXPECT_EQ(0u, status.pos);
1284   }
1285 }
1286 }  // namespace cbor
1287 
1288 namespace json {
1289 
1290 // =============================================================================
1291 // json::NewJSONEncoder - for encoding streaming parser events as JSON
1292 // =============================================================================
1293 
WriteUTF8AsUTF16(StreamingParserHandler * writer,const std::string & utf8)1294 void WriteUTF8AsUTF16(StreamingParserHandler* writer, const std::string& utf8) {
1295   writer->HandleString16(SpanFrom(UTF8ToUTF16(SpanFrom(utf8))));
1296 }
1297 
TEST(JsonStdStringWriterTest,HelloWorld)1298 TEST(JsonStdStringWriterTest, HelloWorld) {
1299   std::string out;
1300   Status status;
1301   std::unique_ptr<StreamingParserHandler> writer =
1302       NewJSONEncoder(&GetTestPlatform(), &out, &status);
1303   writer->HandleMapBegin();
1304   WriteUTF8AsUTF16(writer.get(), "msg1");
1305   WriteUTF8AsUTF16(writer.get(), "Hello, ��.");
1306   std::string key = "msg1-as-utf8";
1307   std::string value = "Hello, ��.";
1308   writer->HandleString8(SpanFrom(key));
1309   writer->HandleString8(SpanFrom(value));
1310   WriteUTF8AsUTF16(writer.get(), "msg2");
1311   WriteUTF8AsUTF16(writer.get(), "\\\b\r\n\t\f\"");
1312   WriteUTF8AsUTF16(writer.get(), "nested");
1313   writer->HandleMapBegin();
1314   WriteUTF8AsUTF16(writer.get(), "double");
1315   writer->HandleDouble(3.1415);
1316   WriteUTF8AsUTF16(writer.get(), "int");
1317   writer->HandleInt32(-42);
1318   WriteUTF8AsUTF16(writer.get(), "bool");
1319   writer->HandleBool(false);
1320   WriteUTF8AsUTF16(writer.get(), "null");
1321   writer->HandleNull();
1322   writer->HandleMapEnd();
1323   WriteUTF8AsUTF16(writer.get(), "array");
1324   writer->HandleArrayBegin();
1325   writer->HandleInt32(1);
1326   writer->HandleInt32(2);
1327   writer->HandleInt32(3);
1328   writer->HandleArrayEnd();
1329   writer->HandleMapEnd();
1330   EXPECT_TRUE(status.ok());
1331   EXPECT_EQ(
1332       "{\"msg1\":\"Hello, \\ud83c\\udf0e.\","
1333       "\"msg1-as-utf8\":\"Hello, \\ud83c\\udf0e.\","
1334       "\"msg2\":\"\\\\\\b\\r\\n\\t\\f\\\"\","
1335       "\"nested\":{\"double\":3.1415,\"int\":-42,"
1336       "\"bool\":false,\"null\":null},\"array\":[1,2,3]}",
1337       out);
1338 }
1339 
TEST(JsonStdStringWriterTest,RepresentingNonFiniteValuesAsNull)1340 TEST(JsonStdStringWriterTest, RepresentingNonFiniteValuesAsNull) {
1341   // JSON can't represent +Infinity, -Infinity, or NaN.
1342   // So in practice it's mapped to null.
1343   std::string out;
1344   Status status;
1345   std::unique_ptr<StreamingParserHandler> writer =
1346       NewJSONEncoder(&GetTestPlatform(), &out, &status);
1347   writer->HandleMapBegin();
1348   writer->HandleString8(SpanFrom("Infinity"));
1349   writer->HandleDouble(std::numeric_limits<double>::infinity());
1350   writer->HandleString8(SpanFrom("-Infinity"));
1351   writer->HandleDouble(-std::numeric_limits<double>::infinity());
1352   writer->HandleString8(SpanFrom("NaN"));
1353   writer->HandleDouble(std::numeric_limits<double>::quiet_NaN());
1354   writer->HandleMapEnd();
1355   EXPECT_TRUE(status.ok());
1356   EXPECT_EQ("{\"Infinity\":null,\"-Infinity\":null,\"NaN\":null}", out);
1357 }
1358 
TEST(JsonStdStringWriterTest,BinaryEncodedAsJsonString)1359 TEST(JsonStdStringWriterTest, BinaryEncodedAsJsonString) {
1360   // The encoder emits binary submitted to StreamingParserHandler::HandleBinary
1361   // as base64. The following three examples are taken from
1362   // https://en.wikipedia.org/wiki/Base64.
1363   {
1364     std::string out;
1365     Status status;
1366     std::unique_ptr<StreamingParserHandler> writer =
1367         NewJSONEncoder(&GetTestPlatform(), &out, &status);
1368     writer->HandleBinary(SpanFrom(std::vector<uint8_t>({'M', 'a', 'n'})));
1369     EXPECT_TRUE(status.ok());
1370     EXPECT_EQ("\"TWFu\"", out);
1371   }
1372   {
1373     std::string out;
1374     Status status;
1375     std::unique_ptr<StreamingParserHandler> writer =
1376         NewJSONEncoder(&GetTestPlatform(), &out, &status);
1377     writer->HandleBinary(SpanFrom(std::vector<uint8_t>({'M', 'a'})));
1378     EXPECT_TRUE(status.ok());
1379     EXPECT_EQ("\"TWE=\"", out);
1380   }
1381   {
1382     std::string out;
1383     Status status;
1384     std::unique_ptr<StreamingParserHandler> writer =
1385         NewJSONEncoder(&GetTestPlatform(), &out, &status);
1386     writer->HandleBinary(SpanFrom(std::vector<uint8_t>({'M'})));
1387     EXPECT_TRUE(status.ok());
1388     EXPECT_EQ("\"TQ==\"", out);
1389   }
1390   {  // "Hello, world.", verified with base64decode.org.
1391     std::string out;
1392     Status status;
1393     std::unique_ptr<StreamingParserHandler> writer =
1394         NewJSONEncoder(&GetTestPlatform(), &out, &status);
1395     writer->HandleBinary(SpanFrom(std::vector<uint8_t>(
1396         {'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '.'})));
1397     EXPECT_TRUE(status.ok());
1398     EXPECT_EQ("\"SGVsbG8sIHdvcmxkLg==\"", out);
1399   }
1400 }
1401 
TEST(JsonStdStringWriterTest,HandlesErrors)1402 TEST(JsonStdStringWriterTest, HandlesErrors) {
1403   // When an error is sent via HandleError, it saves it in the provided
1404   // status and clears the output.
1405   std::string out;
1406   Status status;
1407   std::unique_ptr<StreamingParserHandler> writer =
1408       NewJSONEncoder(&GetTestPlatform(), &out, &status);
1409   writer->HandleMapBegin();
1410   WriteUTF8AsUTF16(writer.get(), "msg1");
1411   writer->HandleError(Status{Error::JSON_PARSER_VALUE_EXPECTED, 42});
1412   EXPECT_EQ(Error::JSON_PARSER_VALUE_EXPECTED, status.error);
1413   EXPECT_EQ(42u, status.pos);
1414   EXPECT_EQ("", out);
1415 }
1416 
1417 // We'd use Gmock but unfortunately it only handles copyable return types.
1418 class MockPlatform : public Platform {
1419  public:
1420   // Not implemented.
StrToD(const char * str,double * result) const1421   bool StrToD(const char* str, double* result) const override { return false; }
1422 
1423   // A map with pre-registered responses for DToSTr.
1424   std::map<double, std::string> dtostr_responses_;
1425 
DToStr(double value) const1426   std::unique_ptr<char[]> DToStr(double value) const override {
1427     auto it = dtostr_responses_.find(value);
1428     CHECK(it != dtostr_responses_.end());
1429     const std::string& str = it->second;
1430     std::unique_ptr<char[]> response(new char[str.size() + 1]);
1431     memcpy(response.get(), str.c_str(), str.size() + 1);
1432     return response;
1433   }
1434 };
1435 
TEST(JsonStdStringWriterTest,DoubleToString)1436 TEST(JsonStdStringWriterTest, DoubleToString) {
1437   // This "broken" platform responds without the leading 0 before the
1438   // decimal dot, so it'd be invalid JSON.
1439   MockPlatform platform;
1440   platform.dtostr_responses_[.1] = ".1";
1441   platform.dtostr_responses_[-.7] = "-.7";
1442 
1443   std::string out;
1444   Status status;
1445   std::unique_ptr<StreamingParserHandler> writer =
1446       NewJSONEncoder(&platform, &out, &status);
1447   writer->HandleArrayBegin();
1448   writer->HandleDouble(.1);
1449   writer->HandleDouble(-.7);
1450   writer->HandleArrayEnd();
1451   EXPECT_EQ("[0.1,-0.7]", out);
1452 }
1453 
1454 // =============================================================================
1455 // json::ParseJSON - for receiving streaming parser events for JSON
1456 // =============================================================================
1457 
1458 class Log : public StreamingParserHandler {
1459  public:
HandleMapBegin()1460   void HandleMapBegin() override { log_ << "map begin\n"; }
1461 
HandleMapEnd()1462   void HandleMapEnd() override { log_ << "map end\n"; }
1463 
HandleArrayBegin()1464   void HandleArrayBegin() override { log_ << "array begin\n"; }
1465 
HandleArrayEnd()1466   void HandleArrayEnd() override { log_ << "array end\n"; }
1467 
HandleString8(span<uint8_t> chars)1468   void HandleString8(span<uint8_t> chars) override {
1469     log_ << "string8: " << std::string(chars.begin(), chars.end()) << "\n";
1470   }
1471 
HandleString16(span<uint16_t> chars)1472   void HandleString16(span<uint16_t> chars) override {
1473     log_ << "string16: " << UTF16ToUTF8(chars) << "\n";
1474   }
1475 
HandleBinary(span<uint8_t> bytes)1476   void HandleBinary(span<uint8_t> bytes) override {
1477     // JSON doesn't have native support for arbitrary bytes, so our parser will
1478     // never call this.
1479     CHECK(false);
1480   }
1481 
HandleDouble(double value)1482   void HandleDouble(double value) override {
1483     log_ << "double: " << value << "\n";
1484   }
1485 
HandleInt32(int32_t value)1486   void HandleInt32(int32_t value) override { log_ << "int: " << value << "\n"; }
1487 
HandleBool(bool value)1488   void HandleBool(bool value) override { log_ << "bool: " << value << "\n"; }
1489 
HandleNull()1490   void HandleNull() override { log_ << "null\n"; }
1491 
HandleError(Status status)1492   void HandleError(Status status) override { status_ = status; }
1493 
str() const1494   std::string str() const { return status_.ok() ? log_.str() : ""; }
1495 
status() const1496   Status status() const { return status_; }
1497 
1498  private:
1499   std::ostringstream log_;
1500   Status status_;
1501 };
1502 
1503 class JsonParserTest : public ::testing::Test {
1504  protected:
1505   Log log_;
1506 };
1507 
TEST_F(JsonParserTest,SimpleDictionary)1508 TEST_F(JsonParserTest, SimpleDictionary) {
1509   std::string json = "{\"foo\": 42}";
1510   ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
1511   EXPECT_TRUE(log_.status().ok());
1512   EXPECT_EQ(
1513       "map begin\n"
1514       "string16: foo\n"
1515       "int: 42\n"
1516       "map end\n",
1517       log_.str());
1518 }
1519 
TEST_F(JsonParserTest,Whitespace)1520 TEST_F(JsonParserTest, Whitespace) {
1521   std::string json = "\n  {\n\"msg\"\n: \v\"Hello, world.\"\t\r}\t";
1522   ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
1523   EXPECT_TRUE(log_.status().ok());
1524   EXPECT_EQ(
1525       "map begin\n"
1526       "string16: msg\n"
1527       "string16: Hello, world.\n"
1528       "map end\n",
1529       log_.str());
1530 }
1531 
TEST_F(JsonParserTest,NestedDictionary)1532 TEST_F(JsonParserTest, NestedDictionary) {
1533   std::string json = "{\"foo\": {\"bar\": {\"baz\": 1}, \"bar2\": 2}}";
1534   ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
1535   EXPECT_TRUE(log_.status().ok());
1536   EXPECT_EQ(
1537       "map begin\n"
1538       "string16: foo\n"
1539       "map begin\n"
1540       "string16: bar\n"
1541       "map begin\n"
1542       "string16: baz\n"
1543       "int: 1\n"
1544       "map end\n"
1545       "string16: bar2\n"
1546       "int: 2\n"
1547       "map end\n"
1548       "map end\n",
1549       log_.str());
1550 }
1551 
TEST_F(JsonParserTest,Doubles)1552 TEST_F(JsonParserTest, Doubles) {
1553   std::string json = "{\"foo\": 3.1415, \"bar\": 31415e-4}";
1554   ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
1555   EXPECT_TRUE(log_.status().ok());
1556   EXPECT_EQ(
1557       "map begin\n"
1558       "string16: foo\n"
1559       "double: 3.1415\n"
1560       "string16: bar\n"
1561       "double: 3.1415\n"
1562       "map end\n",
1563       log_.str());
1564 }
1565 
TEST_F(JsonParserTest,Unicode)1566 TEST_F(JsonParserTest, Unicode) {
1567   // Globe character. 0xF0 0x9F 0x8C 0x8E in utf8, 0xD83C 0xDF0E in utf16.
1568   std::string json = "{\"msg\": \"Hello, \\uD83C\\uDF0E.\"}";
1569   ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
1570   EXPECT_TRUE(log_.status().ok());
1571   EXPECT_EQ(
1572       "map begin\n"
1573       "string16: msg\n"
1574       "string16: Hello, ��.\n"
1575       "map end\n",
1576       log_.str());
1577 }
1578 
TEST_F(JsonParserTest,Unicode_ParseUtf16)1579 TEST_F(JsonParserTest, Unicode_ParseUtf16) {
1580   // Globe character. utf8: 0xF0 0x9F 0x8C 0x8E; utf16: 0xD83C 0xDF0E.
1581   // Crescent moon character. utf8: 0xF0 0x9F 0x8C 0x99; utf16: 0xD83C 0xDF19.
1582 
1583   // We provide the moon with json escape, but the earth as utf16 input.
1584   // Either way they arrive as utf8 (after decoding in log_.str()).
1585   std::vector<uint16_t> json =
1586       UTF8ToUTF16(SpanFrom("{\"space\": \"�� \\uD83C\\uDF19.\"}"));
1587   ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
1588   EXPECT_TRUE(log_.status().ok());
1589   EXPECT_EQ(
1590       "map begin\n"
1591       "string16: space\n"
1592       "string16: �� ��.\n"
1593       "map end\n",
1594       log_.str());
1595 }
1596 
TEST_F(JsonParserTest,Unicode_ParseUtf8)1597 TEST_F(JsonParserTest, Unicode_ParseUtf8) {
1598   // Used below:
1599   // гласность - example for 2 byte utf8, Russian word "glasnost"
1600   // 屋 - example for 3 byte utf8, Chinese word for "house"
1601   // �� - example for 4 byte utf8: 0xF0 0x9F 0x8C 0x8E; utf16: 0xD83C 0xDF0E.
1602   // �� - example for escapes: utf8: 0xF0 0x9F 0x8C 0x99; utf16: 0xD83C 0xDF19.
1603 
1604   // We provide the moon with json escape, but the earth as utf8 input.
1605   // Either way they arrive as utf8 (after decoding in log_.str()).
1606   std::string json =
1607       "{"
1608       "\"escapes\": \"\\uD83C\\uDF19\","
1609       "\"2 byte\":\"гласность\","
1610       "\"3 byte\":\"屋\","
1611       "\"4 byte\":\"��\""
1612       "}";
1613   ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
1614   EXPECT_TRUE(log_.status().ok());
1615   EXPECT_EQ(
1616       "map begin\n"
1617       "string16: escapes\n"
1618       "string16: ��\n"
1619       "string16: 2 byte\n"
1620       "string16: гласность\n"
1621       "string16: 3 byte\n"
1622       "string16: 屋\n"
1623       "string16: 4 byte\n"
1624       "string16: ��\n"
1625       "map end\n",
1626       log_.str());
1627 }
1628 
TEST_F(JsonParserTest,UnprocessedInputRemainsError)1629 TEST_F(JsonParserTest, UnprocessedInputRemainsError) {
1630   // Trailing junk after the valid JSON.
1631   std::string json = "{\"foo\": 3.1415} junk";
1632   size_t junk_idx = json.find("junk");
1633   EXPECT_NE(junk_idx, std::string::npos);
1634   ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
1635   EXPECT_EQ(Error::JSON_PARSER_UNPROCESSED_INPUT_REMAINS, log_.status().error);
1636   EXPECT_EQ(junk_idx, log_.status().pos);
1637   EXPECT_EQ("", log_.str());
1638 }
1639 
MakeNestedJson(int depth)1640 std::string MakeNestedJson(int depth) {
1641   std::string json;
1642   for (int ii = 0; ii < depth; ++ii)
1643     json += "{\"foo\":";
1644   json += "42";
1645   for (int ii = 0; ii < depth; ++ii)
1646     json += "}";
1647   return json;
1648 }
1649 
TEST_F(JsonParserTest,StackLimitExceededError_BelowLimit)1650 TEST_F(JsonParserTest, StackLimitExceededError_BelowLimit) {
1651   // kStackLimit is 300 (see json_parser.cc). First let's
1652   // try with a small nested example.
1653   std::string json_3 = MakeNestedJson(3);
1654   ParseJSON(GetTestPlatform(), SpanFrom(json_3), &log_);
1655   EXPECT_TRUE(log_.status().ok());
1656   EXPECT_EQ(
1657       "map begin\n"
1658       "string16: foo\n"
1659       "map begin\n"
1660       "string16: foo\n"
1661       "map begin\n"
1662       "string16: foo\n"
1663       "int: 42\n"
1664       "map end\n"
1665       "map end\n"
1666       "map end\n",
1667       log_.str());
1668 }
1669 
TEST_F(JsonParserTest,StackLimitExceededError_AtLimit)1670 TEST_F(JsonParserTest, StackLimitExceededError_AtLimit) {
1671   // Now with kStackLimit (300).
1672   std::string json_limit = MakeNestedJson(300);
1673   ParseJSON(GetTestPlatform(),
1674             span<uint8_t>(reinterpret_cast<const uint8_t*>(json_limit.data()),
1675                           json_limit.size()),
1676             &log_);
1677   EXPECT_TRUE(log_.status().ok());
1678 }
1679 
TEST_F(JsonParserTest,StackLimitExceededError_AboveLimit)1680 TEST_F(JsonParserTest, StackLimitExceededError_AboveLimit) {
1681   // Now with kStackLimit + 1 (301) - it exceeds in the innermost instance.
1682   std::string exceeded = MakeNestedJson(301);
1683   ParseJSON(GetTestPlatform(), SpanFrom(exceeded), &log_);
1684   EXPECT_EQ(Error::JSON_PARSER_STACK_LIMIT_EXCEEDED, log_.status().error);
1685   EXPECT_EQ(strlen("{\"foo\":") * 301, log_.status().pos);
1686 }
1687 
TEST_F(JsonParserTest,StackLimitExceededError_WayAboveLimit)1688 TEST_F(JsonParserTest, StackLimitExceededError_WayAboveLimit) {
1689   // Now way past the limit. Still, the point of exceeding is 301.
1690   std::string far_out = MakeNestedJson(320);
1691   ParseJSON(GetTestPlatform(), SpanFrom(far_out), &log_);
1692   EXPECT_EQ(Error::JSON_PARSER_STACK_LIMIT_EXCEEDED, log_.status().error);
1693   EXPECT_EQ(strlen("{\"foo\":") * 301, log_.status().pos);
1694 }
1695 
TEST_F(JsonParserTest,NoInputError)1696 TEST_F(JsonParserTest, NoInputError) {
1697   std::string json = "";
1698   ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
1699   EXPECT_EQ(Error::JSON_PARSER_NO_INPUT, log_.status().error);
1700   EXPECT_EQ(0u, log_.status().pos);
1701   EXPECT_EQ("", log_.str());
1702 }
1703 
TEST_F(JsonParserTest,InvalidTokenError)1704 TEST_F(JsonParserTest, InvalidTokenError) {
1705   std::string json = "|";
1706   ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
1707   EXPECT_EQ(Error::JSON_PARSER_INVALID_TOKEN, log_.status().error);
1708   EXPECT_EQ(0u, log_.status().pos);
1709   EXPECT_EQ("", log_.str());
1710 }
1711 
TEST_F(JsonParserTest,InvalidNumberError)1712 TEST_F(JsonParserTest, InvalidNumberError) {
1713   // Mantissa exceeds max (the constant used here is int64_t max).
1714   std::string json = "1E9223372036854775807";
1715   ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
1716   EXPECT_EQ(Error::JSON_PARSER_INVALID_NUMBER, log_.status().error);
1717   EXPECT_EQ(0u, log_.status().pos);
1718   EXPECT_EQ("", log_.str());
1719 }
1720 
TEST_F(JsonParserTest,InvalidStringError)1721 TEST_F(JsonParserTest, InvalidStringError) {
1722   // \x22 is an unsupported escape sequence
1723   std::string json = "\"foo\\x22\"";
1724   ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
1725   EXPECT_EQ(Error::JSON_PARSER_INVALID_STRING, log_.status().error);
1726   EXPECT_EQ(0u, log_.status().pos);
1727   EXPECT_EQ("", log_.str());
1728 }
1729 
TEST_F(JsonParserTest,UnexpectedArrayEndError)1730 TEST_F(JsonParserTest, UnexpectedArrayEndError) {
1731   std::string json = "[1,2,]";
1732   ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
1733   EXPECT_EQ(Error::JSON_PARSER_UNEXPECTED_ARRAY_END, log_.status().error);
1734   EXPECT_EQ(5u, log_.status().pos);
1735   EXPECT_EQ("", log_.str());
1736 }
1737 
TEST_F(JsonParserTest,CommaOrArrayEndExpectedError)1738 TEST_F(JsonParserTest, CommaOrArrayEndExpectedError) {
1739   std::string json = "[1,2 2";
1740   ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
1741   EXPECT_EQ(Error::JSON_PARSER_COMMA_OR_ARRAY_END_EXPECTED,
1742             log_.status().error);
1743   EXPECT_EQ(5u, log_.status().pos);
1744   EXPECT_EQ("", log_.str());
1745 }
1746 
TEST_F(JsonParserTest,StringLiteralExpectedError)1747 TEST_F(JsonParserTest, StringLiteralExpectedError) {
1748   // There's an error because the key bar, a string, is not terminated.
1749   std::string json = "{\"foo\": 3.1415, \"bar: 31415e-4}";
1750   ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
1751   EXPECT_EQ(Error::JSON_PARSER_STRING_LITERAL_EXPECTED, log_.status().error);
1752   EXPECT_EQ(16u, log_.status().pos);
1753   EXPECT_EQ("", log_.str());
1754 }
1755 
TEST_F(JsonParserTest,ColonExpectedError)1756 TEST_F(JsonParserTest, ColonExpectedError) {
1757   std::string json = "{\"foo\", 42}";
1758   ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
1759   EXPECT_EQ(Error::JSON_PARSER_COLON_EXPECTED, log_.status().error);
1760   EXPECT_EQ(6u, log_.status().pos);
1761   EXPECT_EQ("", log_.str());
1762 }
1763 
TEST_F(JsonParserTest,UnexpectedMapEndError)1764 TEST_F(JsonParserTest, UnexpectedMapEndError) {
1765   std::string json = "{\"foo\": 42, }";
1766   ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
1767   EXPECT_EQ(Error::JSON_PARSER_UNEXPECTED_MAP_END, log_.status().error);
1768   EXPECT_EQ(12u, log_.status().pos);
1769   EXPECT_EQ("", log_.str());
1770 }
1771 
TEST_F(JsonParserTest,CommaOrMapEndExpectedError)1772 TEST_F(JsonParserTest, CommaOrMapEndExpectedError) {
1773   // The second separator should be a comma.
1774   std::string json = "{\"foo\": 3.1415: \"bar\": 0}";
1775   ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
1776   EXPECT_EQ(Error::JSON_PARSER_COMMA_OR_MAP_END_EXPECTED, log_.status().error);
1777   EXPECT_EQ(14u, log_.status().pos);
1778   EXPECT_EQ("", log_.str());
1779 }
1780 
TEST_F(JsonParserTest,ValueExpectedError)1781 TEST_F(JsonParserTest, ValueExpectedError) {
1782   std::string json = "}";
1783   ParseJSON(GetTestPlatform(), SpanFrom(json), &log_);
1784   EXPECT_EQ(Error::JSON_PARSER_VALUE_EXPECTED, log_.status().error);
1785   EXPECT_EQ(0u, log_.status().pos);
1786   EXPECT_EQ("", log_.str());
1787 }
1788 
1789 template <typename T>
1790 class ConvertJSONToCBORTest : public ::testing::Test {};
1791 
1792 using ContainerTestTypes = ::testing::Types<std::vector<uint8_t>, std::string>;
1793 TYPED_TEST_SUITE(ConvertJSONToCBORTest, ContainerTestTypes);
1794 
TYPED_TEST(ConvertJSONToCBORTest,RoundTripValidJson)1795 TYPED_TEST(ConvertJSONToCBORTest, RoundTripValidJson) {
1796   std::string json_in = "{\"msg\":\"Hello, world.\",\"lst\":[1,2,3]}";
1797   TypeParam json(json_in.begin(), json_in.end());
1798   TypeParam cbor;
1799   {
1800     Status status = ConvertJSONToCBOR(GetTestPlatform(), SpanFrom(json), &cbor);
1801     EXPECT_EQ(Error::OK, status.error);
1802     EXPECT_EQ(Status::npos(), status.pos);
1803   }
1804   TypeParam roundtrip_json;
1805   {
1806     Status status =
1807         ConvertCBORToJSON(GetTestPlatform(), SpanFrom(cbor), &roundtrip_json);
1808     EXPECT_EQ(Error::OK, status.error);
1809     EXPECT_EQ(Status::npos(), status.pos);
1810   }
1811   EXPECT_EQ(json, roundtrip_json);
1812 }
1813 
TYPED_TEST(ConvertJSONToCBORTest,RoundTripValidJson16)1814 TYPED_TEST(ConvertJSONToCBORTest, RoundTripValidJson16) {
1815   std::vector<uint16_t> json16 = {
1816       '{', '"', 'm', 's',    'g',    '"', ':', '"', 'H', 'e', 'l', 'l',
1817       'o', ',', ' ', 0xd83c, 0xdf0e, '.', '"', ',', '"', 'l', 's', 't',
1818       '"', ':', '[', '1',    ',',    '2', ',', '3', ']', '}'};
1819   TypeParam cbor;
1820   {
1821     Status status = ConvertJSONToCBOR(
1822         GetTestPlatform(), span<uint16_t>(json16.data(), json16.size()), &cbor);
1823     EXPECT_EQ(Error::OK, status.error);
1824     EXPECT_EQ(Status::npos(), status.pos);
1825   }
1826   TypeParam roundtrip_json;
1827   {
1828     Status status =
1829         ConvertCBORToJSON(GetTestPlatform(), SpanFrom(cbor), &roundtrip_json);
1830     EXPECT_EQ(Error::OK, status.error);
1831     EXPECT_EQ(Status::npos(), status.pos);
1832   }
1833   std::string json = "{\"msg\":\"Hello, \\ud83c\\udf0e.\",\"lst\":[1,2,3]}";
1834   TypeParam expected_json(json.begin(), json.end());
1835   EXPECT_EQ(expected_json, roundtrip_json);
1836 }
1837 }  // namespace json
1838 }  // namespace v8_inspector_protocol_encoding
1839