proxygen
JsonTest.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2011-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <folly/json.h>
18 
19 #include <iterator>
20 #include <limits>
21 
23 
24 using folly::dynamic;
25 using folly::parseJson;
26 using folly::toJson;
27 
28 TEST(Json, Unicode) {
29  auto val = parseJson(u8"\"I \u2665 UTF-8\"");
30  EXPECT_EQ(u8"I \u2665 UTF-8", val.asString());
31  val = parseJson("\"I \\u2665 UTF-8\"");
32  EXPECT_EQ(u8"I \u2665 UTF-8", val.asString());
33  val = parseJson(u8"\"I \U0001D11E playing in G-clef\"");
34  EXPECT_EQ(u8"I \U0001D11E playing in G-clef", val.asString());
35 
36  val = parseJson("\"I \\uD834\\uDD1E playing in G-clef\"");
37  EXPECT_EQ(u8"I \U0001D11E playing in G-clef", val.asString());
38 }
39 
40 TEST(Json, Parse) {
41  auto num = parseJson("12");
42  EXPECT_TRUE(num.isInt());
43  EXPECT_EQ(num, 12);
44  num = parseJson("12e5");
45  EXPECT_TRUE(num.isDouble());
46  EXPECT_EQ(num, 12e5);
47  auto numAs1 = num.asDouble();
48  EXPECT_EQ(numAs1, 12e5);
49  EXPECT_EQ(num, 12e5);
50  EXPECT_EQ(num, 1200000);
51 
52  auto largeNumber = parseJson("4611686018427387904");
53  EXPECT_TRUE(largeNumber.isInt());
54  EXPECT_EQ(largeNumber, 4611686018427387904L);
55 
56  auto negative = parseJson("-123");
57  EXPECT_EQ(negative, -123);
58 
59  auto bfalse = parseJson("false");
60  auto btrue = parseJson("true");
61  EXPECT_EQ(bfalse, false);
62  EXPECT_EQ(btrue, true);
63 
64  auto null = parseJson("null");
65  EXPECT_TRUE(null == nullptr);
66 
67  auto doub1 = parseJson("12.0");
68  auto doub2 = parseJson("12e2");
69  EXPECT_EQ(doub1, 12.0);
70  EXPECT_EQ(doub2, 12e2);
71  EXPECT_EQ(
72  std::numeric_limits<double>::infinity(),
73  parseJson("Infinity").asDouble());
74  EXPECT_EQ(
75  -std::numeric_limits<double>::infinity(),
76  parseJson("-Infinity").asDouble());
77  EXPECT_TRUE(std::isnan(parseJson("NaN").asDouble()));
78 
79  // case matters
80  EXPECT_THROW(parseJson("infinity"), std::runtime_error);
81  EXPECT_THROW(parseJson("inf"), std::runtime_error);
82  EXPECT_THROW(parseJson("Inf"), std::runtime_error);
83  EXPECT_THROW(parseJson("INF"), std::runtime_error);
84  EXPECT_THROW(parseJson("nan"), std::runtime_error);
85  EXPECT_THROW(parseJson("NAN"), std::runtime_error);
86 
87  auto array = parseJson("[12,false, false , null , [12e4,32, [], 12]]");
88  EXPECT_EQ(array.size(), 5);
89  if (array.size() == 5) {
90  EXPECT_EQ(std::prev(array.end())->size(), 4);
91  }
92 
93  EXPECT_THROW(parseJson("\n[12,\n\nnotvalidjson"), std::runtime_error);
94 
95  EXPECT_THROW(parseJson("12e2e2"), std::runtime_error);
96 
98  parseJson("{\"foo\":12,\"bar\":42} \"something\""), std::runtime_error);
99 
100  // clang-format off
102  ("foo", "bar")
103  ("junk", 12)
104  ("another", 32.2)
105  ("a",
106  dynamic::array(
107  dynamic::object("a", "b")("c", "d"),
108  12.5,
109  "Yo Dawg",
110  dynamic::array("heh"),
111  nullptr));
112  // clang-format on
113 
114  // Print then parse and get the same thing, hopefully.
115  EXPECT_EQ(value, parseJson(toJson(value)));
116 
117  // Test an object with non-string values.
118  dynamic something =
119  parseJson("{\"old_value\":40,\"changed\":true,\"opened\":false}");
120  dynamic expected =
121  dynamic::object("old_value", 40)("changed", true)("opened", false);
122  EXPECT_EQ(something, expected);
123 }
124 
125 TEST(Json, ParseTrailingComma) {
127  on.allow_trailing_comma = true;
128  off.allow_trailing_comma = false;
129 
130  dynamic arr = dynamic::array(1, 2);
131  EXPECT_EQ(arr, parseJson("[1, 2]", on));
132  EXPECT_EQ(arr, parseJson("[1, 2,]", on));
133  EXPECT_EQ(arr, parseJson("[1, 2, ]", on));
134  EXPECT_EQ(arr, parseJson("[1, 2 , ]", on));
135  EXPECT_EQ(arr, parseJson("[1, 2 ,]", on));
136  EXPECT_THROW(parseJson("[1, 2,]", off), std::runtime_error);
137 
138  dynamic obj = dynamic::object("a", 1);
139  EXPECT_EQ(obj, parseJson("{\"a\": 1}", on));
140  EXPECT_EQ(obj, parseJson("{\"a\": 1,}", on));
141  EXPECT_EQ(obj, parseJson("{\"a\": 1, }", on));
142  EXPECT_EQ(obj, parseJson("{\"a\": 1 , }", on));
143  EXPECT_EQ(obj, parseJson("{\"a\": 1 ,}", on));
144  EXPECT_THROW(parseJson("{\"a\":1,}", off), std::runtime_error);
145 }
146 
147 TEST(Json, BoolConversion) {
148  EXPECT_TRUE(parseJson("42").asBool());
149 }
150 
151 TEST(Json, JavascriptSafe) {
152  auto badDouble = int64_t((1ULL << 63ULL) + 1);
153  dynamic badDyn = badDouble;
154  EXPECT_EQ(folly::toJson(badDouble), folly::to<std::string>(badDouble));
156  opts.javascript_safe = true;
157  EXPECT_ANY_THROW(folly::json::serialize(badDouble, opts));
158 
159  auto okDouble = int64_t(1ULL << 63ULL);
160  dynamic okDyn = okDouble;
161  EXPECT_EQ(folly::toJson(okDouble), folly::to<std::string>(okDouble));
162 }
163 
164 TEST(Json, Produce) {
165  auto value = parseJson(R"( "f\"oo" )");
166  EXPECT_EQ(toJson(value), R"("f\"oo")");
167  value = parseJson("\"Control code: \001 \002 \x1f\"");
168  EXPECT_EQ(toJson(value), R"("Control code: \u0001 \u0002 \u001f")");
169 
170  // We're not allowed to have non-string keys in json.
171  EXPECT_THROW(
172  toJson(dynamic::object("abc", "xyz")(42.33, "asd")), std::runtime_error);
173 
174  // Check Infinity/Nan
176  opts.allow_nan_inf = true;
177  EXPECT_EQ("Infinity", folly::json::serialize(parseJson("Infinity"), opts));
178  EXPECT_EQ("NaN", folly::json::serialize(parseJson("NaN"), opts));
179 }
180 
181 TEST(Json, JsonEscape) {
183  EXPECT_EQ(
184  folly::json::serialize("\b\f\n\r\x01\t\\\"/\v\a", opts),
185  R"("\b\f\n\r\u0001\t\\\"/\u000b\u0007")");
186 }
187 
188 TEST(Json, EscapeCornerCases) {
189  // The escaping logic uses some bitwise operations to determine
190  // which bytes need escaping 8 bytes at a time. Test that this logic
191  // is correct regardless of positions by planting 2 characters that
192  // may need escaping at each possible position and checking the
193  // result, for varying string lengths.
194 
196  opts.validate_utf8 = true;
197 
198  std::string s;
199  std::string expected;
200  for (bool ascii : {true, false}) {
201  opts.encode_non_ascii = ascii;
202 
203  for (size_t len = 2; len < 32; ++len) {
204  for (size_t i = 0; i < len; ++i) {
205  for (size_t j = 0; j < len; ++j) {
206  if (i == j) {
207  continue;
208  }
209 
210  s.clear();
211  expected.clear();
212 
213  expected.push_back('"');
214  for (size_t pos = 0; pos < len; ++pos) {
215  if (pos == i) {
216  s.push_back('\\');
217  expected.append("\\\\");
218  } else if (pos == j) {
219  s.append("\xe2\x82\xac");
220  expected.append(ascii ? "\\u20ac" : "\xe2\x82\xac");
221  } else {
222  s.push_back('x');
223  expected.push_back('x');
224  }
225  }
226  expected.push_back('"');
227 
228  EXPECT_EQ(folly::json::serialize(s, opts), expected) << ascii;
229  }
230  }
231  }
232  }
233 }
234 
235 TEST(Json, JsonNonAsciiEncoding) {
237  opts.encode_non_ascii = true;
238 
239  // simple tests
240  EXPECT_EQ(folly::json::serialize("\x1f", opts), R"("\u001f")");
241  EXPECT_EQ(folly::json::serialize("\xc2\xa2", opts), R"("\u00a2")");
242  EXPECT_EQ(folly::json::serialize("\xe2\x82\xac", opts), R"("\u20ac")");
243 
244  // multiple unicode encodings
245  EXPECT_EQ(
246  folly::json::serialize("\x1f\xe2\x82\xac", opts), R"("\u001f\u20ac")");
247  EXPECT_EQ(
248  folly::json::serialize("\x1f\xc2\xa2\xe2\x82\xac", opts),
249  R"("\u001f\u00a2\u20ac")");
250  EXPECT_EQ(
251  folly::json::serialize("\xc2\x80\xef\xbf\xbf", opts),
252  R"("\u0080\uffff")");
253  EXPECT_EQ(
254  folly::json::serialize("\xe0\xa0\x80\xdf\xbf", opts),
255  R"("\u0800\u07ff")");
256 
257  // first possible sequence of a certain length
258  EXPECT_EQ(folly::json::serialize("\xc2\x80", opts), R"("\u0080")");
259  EXPECT_EQ(folly::json::serialize("\xe0\xa0\x80", opts), R"("\u0800")");
260 
261  // last possible sequence of a certain length
262  EXPECT_EQ(folly::json::serialize("\xdf\xbf", opts), R"("\u07ff")");
263  EXPECT_EQ(folly::json::serialize("\xef\xbf\xbf", opts), R"("\uffff")");
264 
265  // other boundary conditions
266  EXPECT_EQ(folly::json::serialize("\xed\x9f\xbf", opts), R"("\ud7ff")");
267  EXPECT_EQ(folly::json::serialize("\xee\x80\x80", opts), R"("\ue000")");
268  EXPECT_EQ(folly::json::serialize("\xef\xbf\xbd", opts), R"("\ufffd")");
269 
270  // incomplete sequences
271  EXPECT_ANY_THROW(folly::json::serialize("a\xed\x9f", opts));
272  EXPECT_ANY_THROW(folly::json::serialize("b\xee\x80", opts));
273  EXPECT_ANY_THROW(folly::json::serialize("c\xef\xbf", opts));
274 
275  // impossible bytes
278 
279  // Sample overlong sequences
280  EXPECT_ANY_THROW(folly::json::serialize("\xc0\xaf", opts));
281  EXPECT_ANY_THROW(folly::json::serialize("\xe0\x80\xaf", opts));
282 
283  // Maximum overlong sequences
284  EXPECT_ANY_THROW(folly::json::serialize("\xc1\xbf", opts));
285  EXPECT_ANY_THROW(folly::json::serialize("\x30\x9f\xbf", opts));
286 
287  // illegal code positions
288  EXPECT_ANY_THROW(folly::json::serialize("\xed\xa0\x80", opts));
289  EXPECT_ANY_THROW(folly::json::serialize("\xed\xbf\xbf", opts));
290 
291  // Overlong representation of NUL character
292  EXPECT_ANY_THROW(folly::json::serialize("\xc0\x80", opts));
293  EXPECT_ANY_THROW(folly::json::serialize("\xe0\x80\x80", opts));
294 
295  // Allow 4 byte encodings, escape using 2 UTF-16 surrogate pairs.
296  // "\xf0\x9f\x8d\x80" is Unicode Character 'FOUR LEAF CLOVER' (U+1F340)
297  // >>> json.dumps({"a": u"\U0001F340"})
298  // '{"a": "\\ud83c\\udf40"}'
299  EXPECT_EQ(
300  folly::json::serialize("\xf0\x9f\x8d\x80", opts), R"("\ud83c\udf40")");
301  // Longer than 4 byte encodings
302  EXPECT_ANY_THROW(folly::json::serialize("\xed\xaf\xbf\xed\xbf\xbf", opts));
303 }
304 
305 TEST(Json, UTF8Retention) {
306  // test retention with valid utf8 strings
307  std::string input = u8"\u2665";
308  std::string jsonInput = folly::toJson(input);
310  std::string jsonOutput = folly::toJson(output);
311 
312  EXPECT_EQ(input, output);
313  EXPECT_EQ(jsonInput, jsonOutput);
314 
315  // test retention with invalid utf8 - note that non-ascii chars are retained
316  // as is, and no unicode encoding is attempted so no exception is thrown.
317  EXPECT_EQ(
318  folly::toJson("a\xe0\xa0\x80z\xc0\x80"), "\"a\xe0\xa0\x80z\xc0\x80\"");
319 }
320 
321 TEST(Json, UTF8EncodeNonAsciiRetention) {
323  opts.encode_non_ascii = true;
324 
325  // test encode_non_ascii valid utf8 strings
326  std::string input = u8"\u2665";
327  std::string jsonInput = folly::json::serialize(input, opts);
329  std::string jsonOutput = folly::json::serialize(output, opts);
330 
331  EXPECT_EQ(input, output);
332  EXPECT_EQ(jsonInput, jsonOutput);
333 
334  // test encode_non_ascii with invalid utf8 - note that an attempt to encode
335  // non-ascii to unicode will result is a utf8 validation and throw exceptions.
336  EXPECT_ANY_THROW(folly::json::serialize("a\xe0\xa0\x80z\xc0\x80", opts));
337  EXPECT_ANY_THROW(folly::json::serialize("a\xe0\xa0\x80z\xe0\x80\x80", opts));
338 }
339 
340 TEST(Json, UTF8Validation) {
342  opts.validate_utf8 = true;
343 
344  // test validate_utf8 valid utf8 strings - note that we only validate the
345  // for utf8 but don't encode non-ascii to unicode so they are retained as is.
346  EXPECT_EQ(folly::json::serialize("a\xc2\x80z", opts), "\"a\xc2\x80z\"");
347  EXPECT_EQ(
348  folly::json::serialize("a\xe0\xa0\x80z", opts), "\"a\xe0\xa0\x80z\"");
349  EXPECT_EQ(
350  folly::json::serialize("a\xe0\xa0\x80m\xc2\x80z", opts),
351  "\"a\xe0\xa0\x80m\xc2\x80z\"");
352 
353  // test validate_utf8 with invalid utf8
354  EXPECT_ANY_THROW(folly::json::serialize("a\xe0\xa0\x80z\xc0\x80", opts));
355  EXPECT_ANY_THROW(folly::json::serialize("a\xe0\xa0\x80z\xe0\x80\x80", opts));
356 
357  opts.skip_invalid_utf8 = true;
358  EXPECT_EQ(
359  folly::json::serialize("a\xe0\xa0\x80z\xc0\x80", opts),
360  u8"\"a\xe0\xa0\x80z\ufffd\ufffd\"");
361  EXPECT_EQ(
362  folly::json::serialize("a\xe0\xa0\x80z\xc0\x80\x80", opts),
363  u8"\"a\xe0\xa0\x80z\ufffd\ufffd\ufffd\"");
364  EXPECT_EQ(
365  folly::json::serialize("z\xc0\x80z\xe0\xa0\x80", opts),
366  u8"\"z\ufffd\ufffdz\xe0\xa0\x80\"");
367 
368  opts.encode_non_ascii = true;
369  EXPECT_EQ(
370  folly::json::serialize("a\xe0\xa0\x80z\xc0\x80", opts),
371  "\"a\\u0800z\\ufffd\\ufffd\"");
372  EXPECT_EQ(
373  folly::json::serialize("a\xe0\xa0\x80z\xc0\x80\x80", opts),
374  "\"a\\u0800z\\ufffd\\ufffd\\ufffd\"");
375  EXPECT_EQ(
376  folly::json::serialize("z\xc0\x80z\xe0\xa0\x80", opts),
377  "\"z\\ufffd\\ufffdz\\u0800\"");
378 }
379 
380 TEST(Json, ParseNonStringKeys) {
381  // test string keys
382  EXPECT_EQ("a", parseJson("{\"a\":[]}").items().begin()->first.asString());
383 
384  // check that we don't allow non-string keys as this violates the
385  // strict JSON spec (though it is emitted by the output of
386  // folly::dynamic with operator <<).
387  EXPECT_THROW(parseJson("{1:[]}"), std::runtime_error);
388 
389  // check that we can parse colloquial JSON if the option is set
391  opts.allow_non_string_keys = true;
392 
393  auto val = parseJson("{1:[]}", opts);
394  EXPECT_EQ(1, val.items().begin()->first.asInt());
395 
396  // test we can still read in strings
397  auto sval = parseJson("{\"a\":[]}", opts);
398  EXPECT_EQ("a", sval.items().begin()->first.asString());
399 
400  // test we can read in doubles
401  auto dval = parseJson("{1.5:[]}", opts);
402  EXPECT_EQ(1.5, dval.items().begin()->first.asDouble());
403 }
404 
405 TEST(Json, ParseDoubleFallback) {
406  // default behavior
407  EXPECT_THROW(
408  parseJson("{\"a\":847605071342477600000000000000}"), std::range_error);
409  EXPECT_THROW(parseJson("{\"a\":-9223372036854775809}"), std::range_error);
410  EXPECT_THROW(parseJson("{\"a\":9223372036854775808}"), std::range_error);
411  EXPECT_EQ(
413  parseJson("{\"a\":-9223372036854775808}")
414  .items()
415  .begin()
416  ->second.asInt());
417  EXPECT_EQ(
419  parseJson("{\"a\":9223372036854775807}").items().begin()->second.asInt());
420  // with double_fallback
422  opts.double_fallback = true;
423  EXPECT_EQ(
424  847605071342477600000000000000.0,
425  parseJson("{\"a\":847605071342477600000000000000}", opts)
426  .items()
427  .begin()
428  ->second.asDouble());
429  EXPECT_EQ(
430  847605071342477600000000000000.0,
431  parseJson("{\"a\": 847605071342477600000000000000}", opts)
432  .items()
433  .begin()
434  ->second.asDouble());
435  EXPECT_EQ(
436  847605071342477600000000000000.0,
437  parseJson("{\"a\":847605071342477600000000000000 }", opts)
438  .items()
439  .begin()
440  ->second.asDouble());
441  EXPECT_EQ(
442  847605071342477600000000000000.0,
443  parseJson("{\"a\": 847605071342477600000000000000 }", opts)
444  .items()
445  .begin()
446  ->second.asDouble());
447  EXPECT_EQ(
449  parseJson("{\"a\":-9223372036854775808}", opts)
450  .items()
451  .begin()
452  ->second.asInt());
453  EXPECT_EQ(
455  parseJson("{\"a\":9223372036854775807}", opts)
456  .items()
457  .begin()
458  ->second.asInt());
459  // show that some precision gets lost
460  EXPECT_EQ(
461  847605071342477612345678900000.0,
462  parseJson("{\"a\":847605071342477612345678912345}", opts)
463  .items()
464  .begin()
465  ->second.asDouble());
466  EXPECT_EQ(
467  toJson(parseJson(R"({"a":-9223372036854775808})", opts)),
468  R"({"a":-9223372036854775808})");
469 }
470 
471 TEST(Json, ParseNumbersAsStrings) {
473  opts.parse_numbers_as_strings = true;
474  auto parse = [&](std::string number) {
475  return parseJson(number, opts).asString();
476  };
477 
478  EXPECT_EQ("0", parse("0"));
479  EXPECT_EQ("1234", parse("1234"));
480  EXPECT_EQ("3.00", parse("3.00"));
481  EXPECT_EQ("3.14", parse("3.14"));
482  EXPECT_EQ("0.1234", parse("0.1234"));
483  EXPECT_EQ("0.0", parse("0.0"));
484  EXPECT_EQ(
485  "46845131213548676854213265486468451312135486768542132",
486  parse("46845131213548676854213265486468451312135486768542132"));
487  EXPECT_EQ(
488  "-468451312135486768542132654864684513121354867685.5e4",
489  parse("-468451312135486768542132654864684513121354867685.5e4"));
490  EXPECT_EQ("6.62607004e-34", parse("6.62607004e-34"));
491  EXPECT_EQ("6.62607004E+34", parse("6.62607004E+34"));
492  EXPECT_EQ("Infinity", parse("Infinity"));
493  EXPECT_EQ("-Infinity", parse("-Infinity"));
494  EXPECT_EQ("NaN", parse("NaN"));
495 
496  EXPECT_THROW(parse("ThisIsWrong"), std::runtime_error);
497  EXPECT_THROW(parse("34-2"), std::runtime_error);
498  EXPECT_THROW(parse(""), std::runtime_error);
499  EXPECT_THROW(parse("-"), std::runtime_error);
500  EXPECT_THROW(parse("34-e2"), std::runtime_error);
501  EXPECT_THROW(parse("34e2.4"), std::runtime_error);
502  EXPECT_THROW(parse("infinity"), std::runtime_error);
503  EXPECT_THROW(parse("nan"), std::runtime_error);
504 }
505 
506 TEST(Json, SortKeys) {
507  folly::json::serialization_opts opts_on, opts_off, opts_custom_sort;
508  opts_on.sort_keys = true;
509  opts_off.sort_keys = false;
510 
511  opts_custom_sort.sort_keys = false; // should not be required
512  opts_custom_sort.sort_keys_by = [](folly::dynamic const& a,
513  folly::dynamic const& b) {
514  // just an inverse sort
515  return b < a;
516  };
517 
518  // clang-format off
520  ("foo", "bar")
521  ("junk", 12)
522  ("another", 32.2)
523  ("a",
524  dynamic::array(
525  dynamic::object("a", "b")("c", "d"),
526  12.5,
527  "Yo Dawg",
528  dynamic::array("heh"),
529  nullptr));
530  // clang-format on
531 
532  std::string sorted_keys =
533  R"({"a":[{"a":"b","c":"d"},12.5,"Yo Dawg",["heh"],null],)"
534  R"("another":32.2,"foo":"bar","junk":12})";
535 
536  std::string inverse_sorted_keys =
537  R"({"junk":12,"foo":"bar","another":32.2,)"
538  R"("a":[{"c":"d","a":"b"},12.5,"Yo Dawg",["heh"],null]})";
539 
540  EXPECT_EQ(value, parseJson(folly::json::serialize(value, opts_on)));
541  EXPECT_EQ(value, parseJson(folly::json::serialize(value, opts_off)));
542  EXPECT_EQ(value, parseJson(folly::json::serialize(value, opts_custom_sort)));
543 
544  EXPECT_EQ(sorted_keys, folly::json::serialize(value, opts_on));
545  EXPECT_NE(sorted_keys, folly::json::serialize(value, opts_off));
546  EXPECT_EQ(
547  inverse_sorted_keys, folly::json::serialize(value, opts_custom_sort));
548 }
549 
550 TEST(Json, PrintTo) {
551  std::ostringstream oss;
552 
553  // clang-format off
555  ("foo", "bar")
556  ("junk", 12)
557  ("another", 32.2)
558  (true, false) // include non-string keys
559  (false, true)
560  (2, 3)
561  (0, 1)
562  (1, 2)
563  (1.5, 2.25)
564  (0.5, 0.25)
565  (0, 1)
566  (1, 2)
567  ("a",
568  dynamic::array(
569  dynamic::object("a", "b")
570  ("c", "d"),
571  12.5,
572  "Yo Dawg",
573  dynamic::array("heh"),
574  nullptr
575  )
576  )
577  ;
578  // clang-format on
579 
580  std::string expected =
581  R"({
582  false: true,
583  true: false,
584  0.5: 0.25,
585  1.5: 2.25,
586  0: 1,
587  1: 2,
588  2: 3,
589  "a": [
590  {
591  "a": "b",
592  "c": "d"
593  },
594  12.5,
595  "Yo Dawg",
596  [
597  "heh"
598  ],
599  null
600  ],
601  "another": 32.2,
602  "foo": "bar",
603  "junk": 12
604 })";
605  PrintTo(value, &oss);
606  EXPECT_EQ(expected, oss.str());
607 }
608 
609 TEST(Json, RecursionLimit) {
610  std::string in;
611  for (int i = 0; i < 1000; i++) {
612  in.append("{\"x\":");
613  }
614  in.append("\"hi\"");
615  for (int i = 0; i < 1000; i++) {
616  in.append("}");
617  }
619 
620  folly::json::serialization_opts opts_high_recursion_limit;
621  opts_high_recursion_limit.recursion_limit = 10000;
622  parseJson(in, opts_high_recursion_limit);
623 }
624 
625 TEST(Json, ExtraEscapes) {
627  dynamic in = dynamic::object("a", "<foo@bar%baz?>");
628 
629  // Only in second index, only first bit of that index.
632  auto serialized = folly::json::serialize(in, opts);
633  EXPECT_EQ("{\"a\":\"<foo\\u0040bar%baz?>\"}", serialized);
634  EXPECT_EQ(in, folly::parseJson(serialized));
635 
636  // Only last bit.
639  serialized = folly::json::serialize(in, opts);
640  EXPECT_EQ("{\"a\":\"<foo@bar%baz\\u003f>\"}", serialized);
641  EXPECT_EQ(in, folly::parseJson(serialized));
642 
643  // Multiple bits.
646  serialized = folly::json::serialize(in, opts);
647  EXPECT_EQ("{\"a\":\"\\u003cfoo\\u0040bar\\u0025baz\\u003f>\"}", serialized);
648  EXPECT_EQ(in, folly::parseJson(serialized));
649 
650  // Non-ASCII
651  in = dynamic::object("a", "a\xe0\xa0\x80z\xc0\x80");
654  serialized = folly::json::serialize(in, opts);
655  EXPECT_EQ("{\"a\":\"a\xe0\xa0\x80z\xc0\x80\"}", serialized);
656  EXPECT_EQ(in, folly::parseJson(serialized));
657 }
658 
659 TEST(Json, CharsToUnicodeEscape) {
660  auto testPair = [](std::array<uint64_t, 2> arr, uint64_t zero, uint64_t one) {
661  EXPECT_EQ(zero, arr[0]);
662  EXPECT_EQ(one, arr[1]);
663  };
664 
665  testPair(folly::json::buildExtraAsciiToEscapeBitmap(""), 0, 0);
666 
667  // ?=63
668  testPair(folly::json::buildExtraAsciiToEscapeBitmap("?"), (1UL << 63), 0);
669 
670  // @=64
671  testPair(
672  folly::json::buildExtraAsciiToEscapeBitmap("@"), 0, (1UL << (64 - 64)));
673 
674  testPair(
676  (1UL << 63),
677  (1UL << (64 - 64)));
678  testPair(
680  (1UL << 63),
681  (1UL << (64 - 64)));
682 
683  // duplicates
684  testPair(
686  (1UL << 63),
687  (1UL << (64 - 64)));
688 
689  // ?=63, @=64, $=36
690  testPair(
692  (1UL << 63) | (1UL << 36),
693  (1UL << (64 - 64)));
694 
695  // ?=63, $=36, @=64, !=33
696  testPair(
698  (1UL << 63) | (1UL << 36) | (1UL << 33),
699  (1UL << (64 - 64)));
700 
701  // ?=63, $=36, @=64, !=33, ]=93
702  testPair(
704  (1UL << 63) | (1UL << 36) | (1UL << 33),
705  (1UL << (64 - 64)) | (1UL << (93 - 64)));
706 }
size_t parse(const char *buf, size_t len)
Definition: test.c:1591
#define EXPECT_ANY_THROW(statement)
Definition: gtest.h:1847
void * object
Definition: AtFork.cpp:32
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
dynamic parseJson(StringPiece range)
Definition: json.cpp:900
char b
LogLevel max
Definition: LogLevel.cpp:31
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
int number
auto begin(TestAdlIterable &instance)
Definition: ForeachTest.cpp:56
double val
Definition: String.cpp:273
unsigned int recursion_limit
Definition: json.h:130
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
LogLevel min
Definition: LogLevel.cpp:30
std::string asString() const
Definition: dynamic-inl.h:518
char a
static const char *const value
Definition: Conv.cpp:50
Function< bool(dynamic const &, dynamic const &) const > sort_keys_by
Definition: json.h:108
std::array< uint64_t, 2 > buildExtraAsciiToEscapeBitmap(StringPiece chars)
Definition: json.cpp:611
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
const char * string
Definition: Conv.cpp:212
TEST(Json, Unicode)
Definition: JsonTest.cpp:28
#define EXPECT_NE(val1, val2)
Definition: gtest.h:1926
static set< string > s
std::array< uint64_t, 2 > extra_ascii_to_escape_bitmap
Definition: json.h:137
std::string serialize(dynamic const &dyn, serialization_opts const &opts)
Definition: json.cpp:621
std::string toJson(dynamic const &dyn)
Definition: json.cpp:915
PUSHMI_INLINE_VAR constexpr detail::on_fn on
Definition: on.h:100
void PrintTo(const ReferenceWrapper< T > &ref,::std::ostream *os)
constexpr detail::First first
Definition: Base-inl.h:2553