Fix SimpleBarrier
[folly.git] / folly / test / JsonTest.cpp
1 /*
2  * Copyright 2016 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 #include <limits>
17
18 #include <boost/next_prior.hpp>
19
20 #include <folly/json.h>
21 #include <folly/portability/GTest.h>
22
23 using folly::dynamic;
24 using folly::parseJson;
25 using folly::toJson;
26
27 TEST(Json, Unicode) {
28   auto val = parseJson(u8"\"I \u2665 UTF-8\"");
29   EXPECT_EQ(u8"I \u2665 UTF-8", val.asString());
30   val = parseJson("\"I \\u2665 UTF-8\"");
31   EXPECT_EQ(u8"I \u2665 UTF-8", val.asString());
32   val = parseJson(u8"\"I \U0001D11E playing in G-clef\"");
33   EXPECT_EQ(u8"I \U0001D11E playing in G-clef", val.asString());
34
35   val = parseJson("\"I \\uD834\\uDD1E playing in G-clef\"");
36   EXPECT_EQ(u8"I \U0001D11E playing in G-clef", val.asString());
37 }
38
39 TEST(Json, Parse) {
40   auto num = parseJson("12");
41   EXPECT_TRUE(num.isInt());
42   EXPECT_EQ(num, 12);
43   num = parseJson("12e5");
44   EXPECT_TRUE(num.isDouble());
45   EXPECT_EQ(num, 12e5);
46   auto numAs1 = num.asDouble();
47   EXPECT_EQ(numAs1, 12e5);
48   EXPECT_EQ(num, 12e5);
49   EXPECT_EQ(num, 1200000);
50
51   auto largeNumber = parseJson("4611686018427387904");
52   EXPECT_TRUE(largeNumber.isInt());
53   EXPECT_EQ(largeNumber, 4611686018427387904L);
54
55   auto negative = parseJson("-123");
56   EXPECT_EQ(negative, -123);
57
58   auto bfalse = parseJson("false");
59   auto btrue = parseJson("true");
60   EXPECT_EQ(bfalse, false);
61   EXPECT_EQ(btrue, true);
62
63   auto null = parseJson("null");
64   EXPECT_TRUE(null == nullptr);
65
66   auto doub1 = parseJson("12.0");
67   auto doub2 = parseJson("12e2");
68   EXPECT_EQ(doub1, 12.0);
69   EXPECT_EQ(doub2, 12e2);
70   EXPECT_EQ(std::numeric_limits<double>::infinity(),
71             parseJson("Infinity").asDouble());
72   EXPECT_EQ(-std::numeric_limits<double>::infinity(),
73             parseJson("-Infinity").asDouble());
74   EXPECT_TRUE(std::isnan(parseJson("NaN").asDouble()));
75
76   // case matters
77   EXPECT_THROW(parseJson("infinity"), std::runtime_error);
78   EXPECT_THROW(parseJson("inf"), std::runtime_error);
79   EXPECT_THROW(parseJson("Inf"), std::runtime_error);
80   EXPECT_THROW(parseJson("INF"), std::runtime_error);
81   EXPECT_THROW(parseJson("nan"), std::runtime_error);
82   EXPECT_THROW(parseJson("NAN"), std::runtime_error);
83
84   auto array = parseJson(
85     "[12,false, false  , null , [12e4,32, [], 12]]");
86   EXPECT_EQ(array.size(), 5);
87   if (array.size() == 5) {
88     EXPECT_EQ(boost::prior(array.end())->size(), 4);
89   }
90
91   EXPECT_THROW(parseJson("\n[12,\n\nnotvalidjson"),
92                std::runtime_error);
93
94   EXPECT_THROW(parseJson("12e2e2"),
95                std::runtime_error);
96
97   EXPECT_THROW(parseJson("{\"foo\":12,\"bar\":42} \"something\""),
98                std::runtime_error);
99
100   dynamic value = dynamic::object
101     ("foo", "bar")
102     ("junk", 12)
103     ("another", 32.2)
104     ("a",
105       dynamic::array(
106         dynamic::object("a", "b")
107                        ("c", "d"),
108         12.5,
109         "Yo Dawg",
110         dynamic::array("heh"),
111         nullptr
112       )
113     )
114     ;
115
116   // Print then parse and get the same thing, hopefully.
117   EXPECT_EQ(value, parseJson(toJson(value)));
118
119
120   // Test an object with non-string values.
121   dynamic something = parseJson(
122     "{\"old_value\":40,\"changed\":true,\"opened\":false}");
123   dynamic expected = dynamic::object
124     ("old_value", 40)
125     ("changed", true)
126     ("opened", false);
127   EXPECT_EQ(something, expected);
128 }
129
130 TEST(Json, ParseTrailingComma) {
131   folly::json::serialization_opts on, off;
132   on.allow_trailing_comma = true;
133   off.allow_trailing_comma = false;
134
135   dynamic arr = dynamic::array(1, 2);
136   EXPECT_EQ(arr, parseJson("[1, 2]", on));
137   EXPECT_EQ(arr, parseJson("[1, 2,]", on));
138   EXPECT_EQ(arr, parseJson("[1, 2, ]", on));
139   EXPECT_EQ(arr, parseJson("[1, 2 , ]", on));
140   EXPECT_EQ(arr, parseJson("[1, 2 ,]", on));
141   EXPECT_THROW(parseJson("[1, 2,]", off), std::runtime_error);
142
143   dynamic obj = dynamic::object("a", 1);
144   EXPECT_EQ(obj, parseJson("{\"a\": 1}", on));
145   EXPECT_EQ(obj, parseJson("{\"a\": 1,}", on));
146   EXPECT_EQ(obj, parseJson("{\"a\": 1, }", on));
147   EXPECT_EQ(obj, parseJson("{\"a\": 1 , }", on));
148   EXPECT_EQ(obj, parseJson("{\"a\": 1 ,}", on));
149   EXPECT_THROW(parseJson("{\"a\":1,}", off), std::runtime_error);
150 }
151
152 TEST(Json, BoolConversion) {
153   EXPECT_TRUE(parseJson("42").asBool());
154 }
155
156 TEST(Json, JavascriptSafe) {
157   auto badDouble = (1ll << 63ll) + 1;
158   dynamic badDyn = badDouble;
159   EXPECT_EQ(folly::toJson(badDouble), folly::to<std::string>(badDouble));
160   folly::json::serialization_opts opts;
161   opts.javascript_safe = true;
162   EXPECT_ANY_THROW(folly::json::serialize(badDouble, opts));
163
164   auto okDouble = 1ll << 63ll;
165   dynamic okDyn = okDouble;
166   EXPECT_EQ(folly::toJson(okDouble), folly::to<std::string>(okDouble));
167 }
168
169 TEST(Json, Produce) {
170   auto value = parseJson(R"( "f\"oo" )");
171   EXPECT_EQ(toJson(value), R"("f\"oo")");
172   value = parseJson("\"Control code: \001 \002 \x1f\"");
173   EXPECT_EQ(toJson(value), R"("Control code: \u0001 \u0002 \u001f")");
174
175   // We're not allowed to have non-string keys in json.
176   EXPECT_THROW(toJson(dynamic::object("abc", "xyz")(42.33, "asd")),
177                std::runtime_error);
178
179   // Check Infinity/Nan
180   folly::json::serialization_opts opts;
181   opts.allow_nan_inf = true;
182   EXPECT_EQ("Infinity", folly::json::serialize(parseJson("Infinity"), opts));
183   EXPECT_EQ("NaN", folly::json::serialize(parseJson("NaN"), opts));
184 }
185
186 TEST(Json, JsonEscape) {
187   folly::json::serialization_opts opts;
188   EXPECT_EQ(
189     folly::json::serialize("\b\f\n\r\x01\t\\\"/\v\a", opts),
190     R"("\b\f\n\r\u0001\t\\\"/\u000b\u0007")");
191 }
192
193 TEST(Json, JsonNonAsciiEncoding) {
194   folly::json::serialization_opts opts;
195   opts.encode_non_ascii = true;
196
197   // simple tests
198   EXPECT_EQ(folly::json::serialize("\x1f", opts), R"("\u001f")");
199   EXPECT_EQ(folly::json::serialize("\xc2\xa2", opts), R"("\u00a2")");
200   EXPECT_EQ(folly::json::serialize("\xe2\x82\xac", opts), R"("\u20ac")");
201
202   // multiple unicode encodings
203   EXPECT_EQ(
204     folly::json::serialize("\x1f\xe2\x82\xac", opts),
205     R"("\u001f\u20ac")");
206   EXPECT_EQ(
207     folly::json::serialize("\x1f\xc2\xa2\xe2\x82\xac", opts),
208     R"("\u001f\u00a2\u20ac")");
209   EXPECT_EQ(
210     folly::json::serialize("\xc2\x80\xef\xbf\xbf", opts),
211     R"("\u0080\uffff")");
212   EXPECT_EQ(
213     folly::json::serialize("\xe0\xa0\x80\xdf\xbf", opts),
214     R"("\u0800\u07ff")");
215
216   // first possible sequence of a certain length
217   EXPECT_EQ(folly::json::serialize("\xc2\x80", opts), R"("\u0080")");
218   EXPECT_EQ(folly::json::serialize("\xe0\xa0\x80", opts), R"("\u0800")");
219
220   // last possible sequence of a certain length
221   EXPECT_EQ(folly::json::serialize("\xdf\xbf", opts), R"("\u07ff")");
222   EXPECT_EQ(folly::json::serialize("\xef\xbf\xbf", opts), R"("\uffff")");
223
224   // other boundary conditions
225   EXPECT_EQ(folly::json::serialize("\xed\x9f\xbf", opts), R"("\ud7ff")");
226   EXPECT_EQ(folly::json::serialize("\xee\x80\x80", opts), R"("\ue000")");
227   EXPECT_EQ(folly::json::serialize("\xef\xbf\xbd", opts), R"("\ufffd")");
228
229   // incomplete sequences
230   EXPECT_ANY_THROW(folly::json::serialize("a\xed\x9f", opts));
231   EXPECT_ANY_THROW(folly::json::serialize("b\xee\x80", opts));
232   EXPECT_ANY_THROW(folly::json::serialize("c\xef\xbf", opts));
233
234   // impossible bytes
235   EXPECT_ANY_THROW(folly::json::serialize("\xfe", opts));
236   EXPECT_ANY_THROW(folly::json::serialize("\xff", opts));
237
238   // Sample overlong sequences
239   EXPECT_ANY_THROW(folly::json::serialize("\xc0\xaf", opts));
240   EXPECT_ANY_THROW(folly::json::serialize("\xe0\x80\xaf", opts));
241
242   // Maximum overlong sequences
243   EXPECT_ANY_THROW(folly::json::serialize("\xc1\xbf", opts));
244   EXPECT_ANY_THROW(folly::json::serialize("\x30\x9f\xbf", opts));
245
246   // illegal code positions
247   EXPECT_ANY_THROW(folly::json::serialize("\xed\xa0\x80", opts));
248   EXPECT_ANY_THROW(folly::json::serialize("\xed\xbf\xbf", opts));
249
250   // Overlong representation of NUL character
251   EXPECT_ANY_THROW(folly::json::serialize("\xc0\x80", opts));
252   EXPECT_ANY_THROW(folly::json::serialize("\xe0\x80\x80", opts));
253
254   // Longer than 3 byte encodings
255   EXPECT_ANY_THROW(folly::json::serialize("\xf4\x8f\xbf\xbf", opts));
256   EXPECT_ANY_THROW(folly::json::serialize("\xed\xaf\xbf\xed\xbf\xbf", opts));
257 }
258
259 TEST(Json, UTF8Retention) {
260
261   // test retention with valid utf8 strings
262   std::string input = u8"\u2665";
263   std::string jsonInput = folly::toJson(input);
264   std::string output = folly::parseJson(jsonInput).asString();
265   std::string jsonOutput = folly::toJson(output);
266
267   EXPECT_EQ(input, output);
268   EXPECT_EQ(jsonInput, jsonOutput);
269
270   // test retention with invalid utf8 - note that non-ascii chars are retained
271   // as is, and no unicode encoding is attempted so no exception is thrown.
272   EXPECT_EQ(
273     folly::toJson("a\xe0\xa0\x80z\xc0\x80"),
274     "\"a\xe0\xa0\x80z\xc0\x80\""
275   );
276 }
277
278 TEST(Json, UTF8EncodeNonAsciiRetention) {
279
280   folly::json::serialization_opts opts;
281   opts.encode_non_ascii = true;
282
283   // test encode_non_ascii valid utf8 strings
284   std::string input = u8"\u2665";
285   std::string jsonInput = folly::json::serialize(input, opts);
286   std::string output = folly::parseJson(jsonInput).asString();
287   std::string jsonOutput = folly::json::serialize(output, opts);
288
289   EXPECT_EQ(input, output);
290   EXPECT_EQ(jsonInput, jsonOutput);
291
292   // test encode_non_ascii with invalid utf8 - note that an attempt to encode
293   // non-ascii to unicode will result is a utf8 validation and throw exceptions.
294   EXPECT_ANY_THROW(folly::json::serialize("a\xe0\xa0\x80z\xc0\x80", opts));
295   EXPECT_ANY_THROW(folly::json::serialize("a\xe0\xa0\x80z\xe0\x80\x80", opts));
296 }
297
298 TEST(Json, UTF8Validation) {
299   folly::json::serialization_opts opts;
300   opts.validate_utf8 = true;
301
302   // test validate_utf8 valid utf8 strings - note that we only validate the
303   // for utf8 but don't encode non-ascii to unicode so they are retained as is.
304   EXPECT_EQ(folly::json::serialize("a\xc2\x80z", opts), "\"a\xc2\x80z\"");
305   EXPECT_EQ(
306     folly::json::serialize("a\xe0\xa0\x80z", opts),
307     "\"a\xe0\xa0\x80z\"");
308   EXPECT_EQ(
309     folly::json::serialize("a\xe0\xa0\x80m\xc2\x80z", opts),
310     "\"a\xe0\xa0\x80m\xc2\x80z\"");
311
312   // test validate_utf8 with invalid utf8
313   EXPECT_ANY_THROW(folly::json::serialize("a\xe0\xa0\x80z\xc0\x80", opts));
314   EXPECT_ANY_THROW(folly::json::serialize("a\xe0\xa0\x80z\xe0\x80\x80", opts));
315
316   opts.skip_invalid_utf8 = true;
317   EXPECT_EQ(
318       folly::json::serialize("a\xe0\xa0\x80z\xc0\x80", opts),
319       u8"\"a\xe0\xa0\x80z\ufffd\ufffd\"");
320   EXPECT_EQ(
321       folly::json::serialize("a\xe0\xa0\x80z\xc0\x80\x80", opts),
322       u8"\"a\xe0\xa0\x80z\ufffd\ufffd\ufffd\"");
323   EXPECT_EQ(
324       folly::json::serialize("z\xc0\x80z\xe0\xa0\x80", opts),
325       u8"\"z\ufffd\ufffdz\xe0\xa0\x80\"");
326
327   opts.encode_non_ascii = true;
328   EXPECT_EQ(folly::json::serialize("a\xe0\xa0\x80z\xc0\x80", opts),
329             "\"a\\u0800z\\ufffd\\ufffd\"");
330   EXPECT_EQ(folly::json::serialize("a\xe0\xa0\x80z\xc0\x80\x80", opts),
331             "\"a\\u0800z\\ufffd\\ufffd\\ufffd\"");
332   EXPECT_EQ(folly::json::serialize("z\xc0\x80z\xe0\xa0\x80", opts),
333             "\"z\\ufffd\\ufffdz\\u0800\"");
334
335 }
336
337
338 TEST(Json, ParseNonStringKeys) {
339   // test string keys
340   EXPECT_EQ("a", parseJson("{\"a\":[]}").items().begin()->first.asString());
341
342   // check that we don't allow non-string keys as this violates the
343   // strict JSON spec (though it is emitted by the output of
344   // folly::dynamic with operator <<).
345   EXPECT_THROW(parseJson("{1:[]}"), std::runtime_error);
346
347   // check that we can parse colloquial JSON if the option is set
348   folly::json::serialization_opts opts;
349   opts.allow_non_string_keys = true;
350
351   auto val = parseJson("{1:[]}", opts);
352   EXPECT_EQ(1, val.items().begin()->first.asInt());
353
354
355   // test we can still read in strings
356   auto sval = parseJson("{\"a\":[]}", opts);
357   EXPECT_EQ("a", sval.items().begin()->first.asString());
358
359   // test we can read in doubles
360   auto dval = parseJson("{1.5:[]}", opts);
361   EXPECT_EQ(1.5, dval.items().begin()->first.asDouble());
362 }
363
364 TEST(Json, ParseDoubleFallback) {
365   // default behavior
366   EXPECT_THROW(parseJson("{\"a\":847605071342477600000000000000}"),
367       std::range_error);
368   EXPECT_THROW(parseJson("{\"a\":-9223372036854775809}"),
369       std::range_error);
370   EXPECT_THROW(parseJson("{\"a\":9223372036854775808}"),
371       std::range_error);
372   EXPECT_EQ(std::numeric_limits<int64_t>::min(),
373       parseJson("{\"a\":-9223372036854775808}").items().begin()
374         ->second.asInt());
375   EXPECT_EQ(std::numeric_limits<int64_t>::max(),
376       parseJson("{\"a\":9223372036854775807}").items().begin()->second.asInt());
377   // with double_fallback
378   folly::json::serialization_opts opts;
379   opts.double_fallback = true;
380   EXPECT_EQ(847605071342477600000000000000.0,
381       parseJson("{\"a\":847605071342477600000000000000}",
382         opts).items().begin()->second.asDouble());
383   EXPECT_EQ(847605071342477600000000000000.0,
384       parseJson("{\"a\": 847605071342477600000000000000}",
385         opts).items().begin()->second.asDouble());
386   EXPECT_EQ(847605071342477600000000000000.0,
387       parseJson("{\"a\":847605071342477600000000000000 }",
388         opts).items().begin()->second.asDouble());
389   EXPECT_EQ(847605071342477600000000000000.0,
390       parseJson("{\"a\": 847605071342477600000000000000 }",
391         opts).items().begin()->second.asDouble());
392   EXPECT_EQ(std::numeric_limits<int64_t>::min(),
393       parseJson("{\"a\":-9223372036854775808}",
394         opts).items().begin()->second.asInt());
395   EXPECT_EQ(std::numeric_limits<int64_t>::max(),
396       parseJson("{\"a\":9223372036854775807}",
397         opts).items().begin()->second.asInt());
398   // show that some precision gets lost
399   EXPECT_EQ(847605071342477612345678900000.0,
400       parseJson("{\"a\":847605071342477612345678912345}",
401         opts).items().begin()->second.asDouble());
402   EXPECT_EQ(
403       toJson(parseJson(R"({"a":-9223372036854775808})", opts)),
404       R"({"a":-9223372036854775808})");
405 }
406
407 TEST(Json, ParseNumbersAsStrings) {
408   folly::json::serialization_opts opts;
409   opts.parse_numbers_as_strings = true;
410   auto parse = [&](std::string number) {
411     return parseJson(number, opts).asString();
412   };
413
414   EXPECT_EQ("0", parse("0"));
415   EXPECT_EQ("1234", parse("1234"));
416   EXPECT_EQ("3.00", parse("3.00"));
417   EXPECT_EQ("3.14", parse("3.14"));
418   EXPECT_EQ("0.1234", parse("0.1234"));
419   EXPECT_EQ("0.0", parse("0.0"));
420   EXPECT_EQ("46845131213548676854213265486468451312135486768542132",
421       parse("46845131213548676854213265486468451312135486768542132"));
422   EXPECT_EQ("-468451312135486768542132654864684513121354867685.5e4",
423       parse("-468451312135486768542132654864684513121354867685.5e4"));
424   EXPECT_EQ("6.62607004e-34", parse("6.62607004e-34"));
425   EXPECT_EQ("6.62607004E+34", parse("6.62607004E+34"));
426   EXPECT_EQ("Infinity", parse("Infinity"));
427   EXPECT_EQ("-Infinity", parse("-Infinity"));
428   EXPECT_EQ("NaN", parse("NaN"));
429
430   EXPECT_THROW(parse("ThisIsWrong"), std::runtime_error);
431   EXPECT_THROW(parse("34-2"), std::runtime_error);
432   EXPECT_THROW(parse(""), std::runtime_error);
433   EXPECT_THROW(parse("-"), std::runtime_error);
434   EXPECT_THROW(parse("34-e2"), std::runtime_error);
435   EXPECT_THROW(parse("34e2.4"), std::runtime_error);
436   EXPECT_THROW(parse("infinity"), std::runtime_error);
437   EXPECT_THROW(parse("nan"), std::runtime_error);
438 }
439
440 TEST(Json, SortKeys) {
441   folly::json::serialization_opts opts_on, opts_off;
442   opts_on.sort_keys = true;
443   opts_off.sort_keys = false;
444
445   dynamic value = dynamic::object
446     ("foo", "bar")
447     ("junk", 12)
448     ("another", 32.2)
449     ("a",
450       dynamic::array(
451         dynamic::object("a", "b")
452                        ("c", "d"),
453         12.5,
454         "Yo Dawg",
455         dynamic::array("heh"),
456         nullptr
457       )
458     )
459     ;
460
461   std::string sorted_keys =
462     R"({"a":[{"a":"b","c":"d"},12.5,"Yo Dawg",["heh"],null],)"
463     R"("another":32.2,"foo":"bar","junk":12})";
464
465   EXPECT_EQ(value, parseJson(folly::json::serialize(value, opts_on)));
466   EXPECT_EQ(value, parseJson(folly::json::serialize(value, opts_off)));
467
468   EXPECT_EQ(sorted_keys, folly::json::serialize(value, opts_on));
469 }
470
471 TEST(Json, PrintTo) {
472   std::ostringstream oss;
473
474   dynamic value = dynamic::object
475     ("foo", "bar")
476     ("junk", 12)
477     ("another", 32.2)
478     (true, false) // include non-string keys
479     (false, true)
480     (2, 3)
481     (0, 1)
482     (1, 2)
483     (1.5, 2.25)
484     (0.5, 0.25)
485     (0, 1)
486     (1, 2)
487     ("a",
488       dynamic::array(
489         dynamic::object("a", "b")
490                        ("c", "d"),
491         12.5,
492         "Yo Dawg",
493         dynamic::array("heh"),
494         nullptr
495       )
496     )
497     ;
498
499   std::string expected =
500       R"({
501   false : true,
502   true : false,
503   0.5 : 0.25,
504   1.5 : 2.25,
505   0 : 1,
506   1 : 2,
507   2 : 3,
508   "a" : [
509     {
510       "a" : "b",
511       "c" : "d"
512     },
513     12.5,
514     "Yo Dawg",
515     [
516       "heh"
517     ],
518     null
519   ],
520   "another" : 32.2,
521   "foo" : "bar",
522   "junk" : 12
523 })";
524   PrintTo(value, &oss);
525   EXPECT_EQ(expected, oss.str());
526 }
527
528 TEST(Json, RecursionLimit) {
529   std::string in;
530   for (int i = 0; i < 1000; i++) {
531     in.append("{\"x\":");
532   }
533   in.append("\"hi\"");
534   for (int i = 0; i < 1000; i++) {
535     in.append("}");
536   }
537   EXPECT_ANY_THROW(parseJson(in));
538
539   folly::json::serialization_opts opts_high_recursion_limit;
540   opts_high_recursion_limit.recursion_limit = 10000;
541   parseJson(in, opts_high_recursion_limit);
542 }