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