1 // -*- c-basic-offset: 4 -*-
3 * jsontest.{cc,hh} -- regression tests for Json
6 * Copyright (c) 2012-2014 Eddie Kohler
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, subject to the conditions
11 * listed in the Click LICENSE file. These conditions include: you must
12 * preserve this copyright notice, and you cannot mention the copyright
13 * holders in advertising related to the Software without their permission.
14 * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
15 * notice is a summary of the Click LICENSE file; the license in that file is
20 #include <unordered_map>
23 #define CHECK(x) do { if (!(x)) { std::cerr << __FILE__ << ":" << __LINE__ << ": test '" << #x << "' failed\n"; exit(1); } } while (0)
24 #define CHECK_JUP(x, str) do { if ((x).unparse() != (str)) { std::cerr << __FILE__ << ":" << __LINE__ << ": '" #x "' is '" << (x) << "', not '" << (str) << "'\n"; exit(1); } } while (0)
28 template <typename T> void incr(T& x) __attribute__((noinline));
35 void benchmark_parse() {
36 std::vector<String> parse_examples;
37 parse_examples.push_back("{}");
38 parse_examples.push_back("{\"foo\":\"bar\",\"baz\":\"flim\"}");
39 parse_examples.push_back("[1,2,3,4,5]");
40 parse_examples.push_back("[]");
41 parse_examples.push_back("[{},{\"b\":[]}]");
44 for (int i = 0; i < 10000000; ++i)
45 j.assign_parse(parse_examples[rand() % parse_examples.size()]);
48 Json::streaming_parser jsp;
49 for (int i = 0; i < 10000000; ++i) {
51 swap(jsp.result(), j);
52 const String& str = parse_examples[rand() % parse_examples.size()];
53 jsp.consume(str.begin(), str.end(), str, true);
59 int main(int argc, char** argv) {
60 (void) argc, (void) argv;
67 j = Json::make_object();
73 CHECK(j["foo"].to_s() == "bar");
78 CHECK(j.unparse() == "{\"foo\":\"bar\",\"baz\":\"flim\"}");
86 j.assign_parse("null");
89 j.assign_parse("\"a\"");
92 j.assign_parse("[1,2]");
93 CHECK(j.unparse() == "[1,2]");
95 j.assign_parse("[[[]],{\"a\":{}}]");
96 CHECK(j.unparse() == "[[[]],{\"a\":{}}]");
98 j = Json::parse("{\"x22\":{\n\
99 \"git-revision\":\"ebbd3d4767847300f552b181a10bda57a926f554M\",\n\
100 \"time\":\"Tue Feb 7 20:20:33 2012\",\n\
101 \"machine\":\"rtshanks-laptop\",\n\
103 \"runs\":[\"x22\\/rw2\\/mb\\/0\"]\n\
106 \"git-revision\":\"ebbd3d4767847300f552b181a10bda57a926f554M\",\n\
107 \"time\":\"Tue Feb 7 20:31:05 2012\",\n\
108 \"machine\":\"rtshanks-laptop\",\n\
110 \"runs\":[\"x23\\/rw2\\/mb\\/0\",\"x23\\/rw1\\/mb\\/0\",\"x23\\/rw3\\/mb\\/0\"]\n\
113 \"git-revision\":\"62e9970ca8ae9c6eebf2d71b7065ea694fb25282M\",\n\
114 \"time\":\"Sat Feb 11 15:54:01 2012\",\n\
115 \"machine\":\"rtshanks-laptop\",\n\
117 \"runs\":[\"x24\\/rw1\\/b\\/0\"]\n\
118 },\"b\":\"c\",\"c\":\"d\"}");
119 CHECK(j["x22"]["time"] == "Tue Feb 7 20:20:33 2012");
120 CHECK(j["x22"]["cores"] == 2);
122 Json::object_iterator it = j.obegin();
123 CHECK(it.key() == "x22");
125 CHECK(it.key() == "x23");
127 CHECK(it.key() == "x24");
129 CHECK(it.key() == "b");
131 CHECK(it.key() == "c");
136 CHECK(j.size() == 5);
138 for (Json::iterator it = jcopy.begin(); it != jcopy.end(); ++it) {
142 CHECK(!jcopy["x22"]);
143 CHECK(j["x22"]["cores"] == 2);
144 CHECK(count == jcopy.size());
148 CHECK(j.size() == 5);
149 CHECK(!j["x49"]["45"][2]["a"]);
150 CHECK(j.size() == 5);
151 j["x49"]["45"][2]["a"] = 1;
152 CHECK(j.size() == 6);
153 CHECK(j["x22"].is_object() && j.get("x22").is_object());
154 CHECK(j["x23"].is_object() && j.get("x23").is_object());
155 CHECK(j["b"].is_string() && j.get("b").is_string());
156 CHECK(j["x49"].is_object() && j.get("x49").is_object());
157 CHECK(j["x49"]["45"].is_array());
158 CHECK(j["x49"]["45"].size() == 3 && j["x49"]["45"][2].is_object());
160 j = Json::make_object();
162 CHECK(j.size() == 1);
163 CHECK(j["a"].is_null());
164 CHECK(j.count("a") == 1);
166 Json k = Json::make_array();
168 CHECK(k.size() == 0);
169 Json::array_iterator it = k.abegin();
172 j = Json::make_object();
174 CHECK(j.size() == 1);
175 CHECK(k.size() == 0);
176 CHECK(j["a"].is_null());
177 CHECK(j.count("a") == 1);
180 CHECK(j.get("a").is_null());
182 j.assign_parse("{\"a\":1,\"b\":true,\"c\":\"\"}");
187 CHECK(j.get("a", i));
189 CHECK(j.get("a", i).get("b", b));
191 CHECK(!j.get("a", s).status());
192 CHECK(!j.get("a", s).status(b));
194 CHECK(j.get("a", k));
196 CHECK(!j.get("cc", k));
201 j["b"] = Json::parse("[]");
204 Json j1 = Json::make_object(), j2 = Json::make_object();
205 j1.set("a", j2); // stores a COPY of j2 in j1
207 CHECK(j1.unparse() == "{\"a\":{}}");
208 CHECK(j2.unparse() == "{\"b\":1}");
212 Json j = Json::parse("{\"a\":true}");
215 CHECK(j.unparse() == "{\"a\":true}");
216 j["foo"]["bar"] = true;
217 CHECK(j.unparse() == "{\"a\":true,\"foo\":{\"bar\":true}}");
219 CHECK(j.unparse() == "{\"a\":{\"2\":false},\"foo\":{\"bar\":true}}");
221 CHECK(j.unparse() == "{\"a\":{\"2\":false},\"foo\":{\"bar\":true},\"3\":true}");
222 CHECK(j[3] == Json(true));
223 j = Json::parse("[1,2,3,4]");
224 CHECK(j["2"] == Json(3));
225 CHECK(j.unparse() == "[1,2,3,4]");
227 CHECK(j.unparse() == "{\"0\":1,\"1\":2,\"2\":3,\"3\":4,\"a\":true}");
228 CHECK(j["2"] == Json(3));
232 Json j = Json::parse("{}");
233 j.set("foo", String::make_out_of_memory()).set(String::make_out_of_memory(), 2);
234 CHECK(j.unparse() == "{\"foo\":\"\360\237\222\243ENOMEM\360\237\222\243\",\"\360\237\222\243ENOMEM\360\237\222\243\":2}");
236 CHECK(j.unparse() == "{}");
237 CHECK(j.get("foo") == Json());
241 Json j = Json::array(1, 2, 3, 4, 5, 6, 7, 8);
242 CHECK(j.unparse() == "[1,2,3,4,5,6,7,8]");
244 CHECK(j.unparse() == "[1,2,3,4,5,6,7,8]");
245 CHECK(jcopy.unparse() == "[1,2,3,4,5,6,7,8]");
247 CHECK(j.unparse() == "[1,2,3,4,5,6,7,8,9]");
248 CHECK(jcopy.unparse() == "[1,2,3,4,5,6,7,8]");
250 CHECK(j.unparse() == "[1,2,3,4,5,6,7,8,9]");
251 CHECK(jcopy.unparse() == "[1,2,3,4,5,6,7,8,10]");
255 unsigned long s = 77;
256 Json j = Json::array(0, 0, 0);
257 Json k = Json::array(0, s, "foo");
266 Json j = Json::array(1, 2, 3);
267 //int j[3] = {1, 2, 3};
268 for (int i = 0; i < 1000000; ++i)
270 std::cout << j << "\n";
275 Json::streaming_parser jsp;
276 const uint8_t* x = reinterpret_cast<const uint8_t*>("\"abcdef\"");
278 const uint8_t* r = jsp.consume(x, x + 8, String());
280 CHECK(jsp.success());
281 CHECK(jsp.result().unparse() == "\"abcdef\"");
283 x = reinterpret_cast<const uint8_t*>("\"\\\"\\\\fartbox\" amksdnsndfa");
285 r = jsp.consume(x, x + 9, String());
288 r = jsp.consume(x + 9, x + 17, String());
290 CHECK(jsp.success());
291 CHECK(jsp.result().unparse() == "\"\\\"\\\\fartbox\"");
294 r = jsp.consume(x, x + 3, String());
296 r = jsp.consume(x + 3, x + 6, String());
298 r = jsp.consume(x + 6, x + 9, String());
300 r = jsp.consume(x + 9, x + 13, String());
302 CHECK(jsp.success());
303 CHECK(jsp.result().unparse() == "\"\\\"\\\\fartbox\"");
306 x = reinterpret_cast<const uint8_t*>("\"\\uD834\\uDD1E\"f");
307 r = jsp.consume(x, x + 15, String());
309 CHECK(jsp.success());
310 CHECK(jsp.result().unparse() == "\"\xF0\x9D\x84\x9E\"");
313 r = jsp.consume(x, x + 2, String());
315 r = jsp.consume(x + 2, x + 4, String());
317 r = jsp.consume(x + 4, x + 6, String());
319 r = jsp.consume(x + 6, x + 8, String());
321 r = jsp.consume(x + 8, x + 10, String());
323 r = jsp.consume(x + 10, x + 15, String());
325 CHECK(jsp.success());
326 CHECK(jsp.result().unparse() == "\"\xF0\x9D\x84\x9E\"");
328 x = reinterpret_cast<const uint8_t*>("\"\xF0\x9D\x84\x9E\" fart");
330 r = jsp.consume(x, x + 3, String());
332 r = jsp.consume(x + 5, x + 7, String());
337 r = jsp.consume(x, x + 7, String());
339 CHECK(jsp.success());
340 CHECK(jsp.result().unparse() == "\"\xF0\x9D\x84\x9E\"");
343 r = jsp.consume(x, x + 2, String());
345 r = jsp.consume(x + 2, x + 4, String());
347 r = jsp.consume(x + 4, x + 7, String());
349 CHECK(jsp.success());
350 CHECK(jsp.result().unparse() == "\"\xF0\x9D\x84\x9E\"");
353 x = reinterpret_cast<const uint8_t*>("{}");
354 r = jsp.consume(x, x + 2, String());
356 CHECK(jsp.success());
357 CHECK(jsp.result().unparse() == "{}");
360 x = reinterpret_cast<const uint8_t*>("\"ab cde\" ");
361 r = jsp.consume(x, x + 9, String());
363 CHECK(jsp.success());
364 CHECK(jsp.result().unparse() == "\"ab cde\"");
367 x = reinterpret_cast<const uint8_t*>("{\"a\":\"b\"}");
368 r = jsp.consume(x, x + 9, String());
370 CHECK(jsp.success());
371 CHECK(jsp.result().unparse() == "{\"a\":\"b\"}");
374 x = reinterpret_cast<const uint8_t*>("[]");
375 r = jsp.consume(x, x + 2, String());
377 CHECK(jsp.success());
378 CHECK(jsp.result().unparse() == "[]");
381 x = reinterpret_cast<const uint8_t*>("[\"a\",\"b\"]");
382 r = jsp.consume(x, x + 9, String());
384 CHECK(jsp.success());
385 CHECK(jsp.result().unparse() == "[\"a\",\"b\"]");
388 x = reinterpret_cast<const uint8_t*>("[[\"a\"],[[\"b\"]]]");
389 r = jsp.consume(x, x + 15, String());
391 CHECK(jsp.success());
392 CHECK(jsp.result().unparse() == "[[\"a\"],[[\"b\"]]]");
395 x = reinterpret_cast<const uint8_t*>("[[],[[]]]");
396 r = jsp.consume(x, x + 9, String());
398 CHECK(jsp.success());
399 CHECK(jsp.result().unparse() == "[[],[[]]]");
402 x = reinterpret_cast<const uint8_t*>("{\"abc\":\"def\"}");
403 r = jsp.consume(x, x + 3, String());
405 r = jsp.consume(x + 3, x + 6, String());
407 r = jsp.consume(x + 6, x + 9, String());
409 r = jsp.consume(x + 9, x + 12, String());
411 r = jsp.consume(x + 12, x + 13, String());
413 CHECK(jsp.success());
414 CHECK(jsp.result().unparse() == "{\"abc\":\"def\"}");
417 x = reinterpret_cast<const uint8_t*>("{\"abc\":true }");
418 r = jsp.consume(x, x + 3, String());
420 r = jsp.consume(x + 3, x + 6, String());
422 r = jsp.consume(x + 6, x + 9, String());
424 r = jsp.consume(x + 9, x + 12, String());
426 r = jsp.consume(x + 12, x + 13, String());
428 CHECK(jsp.success());
429 CHECK(jsp.result().unparse() == "{\"abc\":true}");
432 x = reinterpret_cast<const uint8_t*>("{\"abc\": null}");
433 r = jsp.consume(x, x + 3, String());
435 r = jsp.consume(x + 3, x + 6, String());
437 r = jsp.consume(x + 6, x + 9, String());
439 r = jsp.consume(x + 9, x + 12, String());
441 r = jsp.consume(x + 12, x + 13, String());
443 CHECK(jsp.success());
444 CHECK(jsp.result().unparse() == "{\"abc\":null}");
447 x = reinterpret_cast<const uint8_t*>("{\"abc\":false}");
448 r = jsp.consume(x, x + 3, String());
450 r = jsp.consume(x + 3, x + 6, String());
452 r = jsp.consume(x + 6, x + 9, String());
454 r = jsp.consume(x + 9, x + 12, String());
456 r = jsp.consume(x + 12, x + 13, String());
458 CHECK(jsp.success());
459 CHECK(jsp.result().unparse() == "{\"abc\":false}");
462 x = reinterpret_cast<const uint8_t*>("{\"abc\": -13 }");
463 r = jsp.consume(x, x + 3, String());
465 r = jsp.consume(x + 3, x + 6, String());
467 r = jsp.consume(x + 6, x + 9, String());
469 r = jsp.consume(x + 9, x + 12, String());
471 r = jsp.consume(x + 12, x + 13, String());
473 CHECK(jsp.success());
474 CHECK(jsp.result().unparse() == "{\"abc\":-13}");
477 x = reinterpret_cast<const uint8_t*>("{\"abc\":0 }");
478 r = jsp.consume(x, x + 3, String());
480 r = jsp.consume(x + 3, x + 6, String());
482 r = jsp.consume(x + 6, x + 9, String());
484 r = jsp.consume(x + 9, x + 12, String());
486 r = jsp.consume(x + 12, x + 13, String());
488 CHECK(jsp.success());
489 CHECK(jsp.result().unparse() == "{\"abc\":0}");
492 x = reinterpret_cast<const uint8_t*>("[0,1,2,3,4e5,10.2]");
493 r = jsp.consume(x, x + 3, String());
495 r = jsp.consume(x + 3, x + 6, String());
497 r = jsp.consume(x + 6, x + 9, String());
499 r = jsp.consume(x + 9, x + 12, String());
501 r = jsp.consume(x + 12, x + 18, String());
503 CHECK(jsp.success());
504 CHECK(jsp.result().unparse() == "[0,1,2,3,400000,10.2]");
508 unsigned long s = 77;
509 Json j = Json::array(0, s, "foo");
515 j = Json::array((uint64_t) -1, (int64_t) -1,
516 (uint64_t) 1, (int64_t) 1,
517 (uint64_t) 2, (int64_t) 2);
523 CHECK_JUP(j, "[18446744073709551615,-1,1,1,2,2]");
527 std::vector<int> v = {1, 2, 3, 4, 5};
528 Json j(v.begin(), v.end());
529 CHECK(j.unparse() == "[1,2,3,4,5]");
533 std::unordered_map<String, String> h;
537 Json j(h.begin(), h.end());
539 CHECK(j.size() == 3);
540 CHECK(j["a"] == "b");
541 CHECK(j["c"] == "d");
542 CHECK(j["x"] == "e");
546 Json j = Json::array(1, 2, 3, 4, 5, 6, 7, 8);
547 CHECK(j.unparse() == "[1,2,3,4,5,6,7,8]");
549 CHECK(j.unparse() == "[1,2,3,4,5,6,7,8]");
550 CHECK(jcopy.unparse() == "[1,2,3,4,5,6,7,8]");
551 auto it = j.erase(j.abegin() + 4);
552 CHECK_JUP(j, "[1,2,3,4,6,7,8]");
553 CHECK_JUP(jcopy, "[1,2,3,4,5,6,7,8]");
554 CHECK(it == j.abegin() + 4);
555 it = j.erase(j.aend(), j.aend());
556 CHECK_JUP(j, "[1,2,3,4,6,7,8]");
557 CHECK(it == j.aend());
558 it = j.erase(j.abegin(), j.abegin());
559 CHECK_JUP(j, "[1,2,3,4,6,7,8]");
560 CHECK(it == j.abegin());
561 it = j.erase(j.abegin(), j.abegin() + 3);
562 CHECK_JUP(j, "[4,6,7,8]");
563 CHECK(it == j.abegin());
567 Json j((uint64_t) 1 << 63);
569 CHECK(j.unparse() == "9223372036854775808");
570 j = Json::parse("9223372036854775808");
572 CHECK(j.to_u() == (uint64_t) 1 << 63);
576 Json j = Json::object("a", 1, "b", Json(2), "c", "9137471");
577 CHECK(j.unparse() == "{\"a\":1,\"b\":2,\"c\":\"9137471\"}");
581 Json a = Json::parse("[{\"a\":1},{\"b\":2},{\"c\":3},{\"d\":4}]");
582 Json b = Json::array(a[1], a[3], a[2], a[0]);
583 CHECK(&a[0]["a"].cvalue() == &b[3]["a"].cvalue());
585 CHECK(b[4] == Json());
586 CHECK(a.size() == 4);
587 b = Json::object("a5", a[5], "a3", a[3]);
588 CHECK(b.unparse() == "{\"a5\":null,\"a3\":{\"d\":4}}");
589 CHECK(a.size() == 4);
590 b.set_list("a6", a[6], "a2", a[2]);
591 CHECK(b.unparse() == "{\"a5\":null,\"a3\":{\"d\":4},\"a6\":null,\"a2\":{\"c\":3}}");
592 CHECK(a.size() == 4);
596 Json a = Json::parse("[{\"a\":\"\\\"\\\\\\/\"}]");
597 CHECK(a[0]["a"] == "\"\\/");
598 CHECK(a.unparse() == "[{\"a\":\"\\\"\\\\\\/\"}]");
601 std::cout << "All tests pass!\n";