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