1#include <boost/property_tree/json_parser/detail/parser.hpp>
2#include <boost/property_tree/json_parser/detail/narrow_encoding.hpp>
3#include <boost/property_tree/json_parser/detail/wide_encoding.hpp>
4#include <boost/property_tree/json_parser/detail/standard_callbacks.hpp>
5#include "prefixing_callbacks.hpp"
6
7#include <boost/core/lightweight_test.hpp>
8
9#include <boost/property_tree/ptree.hpp>
10#include <boost/range/iterator_range.hpp>
11
12#include <cassert>
13#include <sstream>
14#include <vector>
15#include <algorithm>
16
17using namespace boost::property_tree;
18
19template <typename Ch> struct encoding;
20template <> struct encoding<char>
21 : json_parser::detail::utf8_utf8_encoding
22{};
23template <> struct encoding<wchar_t>
24 : json_parser::detail::wide_wide_encoding
25{};
26
27template <typename Callbacks, typename Ch>
28struct test_parser
29{
30 Callbacks callbacks;
31 ::encoding<Ch> encoding;
32 typedef std::basic_string<Ch> string;
33 typedef basic_ptree<string, string> tree;
34 json_parser::detail::parser<Callbacks, ::encoding<Ch>,
35 typename string::const_iterator,
36 typename string::const_iterator>
37 parser;
38
39 test_parser() : parser(callbacks, encoding) {}
40
41 bool parse_null(const string& input, string& output) {
42 parser.set_input("", input);
43 bool result = parser.parse_null();
44 if (result) {
45 parser.finish();
46 output = callbacks.output().data();
47 }
48 return result;
49 }
50
51 bool parse_boolean(const string& input, string& output) {
52 parser.set_input("", input);
53 bool result = parser.parse_boolean();
54 if (result) {
55 parser.finish();
56 output = callbacks.output().data();
57 }
58 return result;
59 }
60
61 bool parse_number(const string& input, string& output) {
62 parser.set_input("", input);
63 bool result = parser.parse_number();
64 if (result) {
65 parser.finish();
66 output = callbacks.output().data();
67 }
68 return result;
69 }
70
71 bool parse_string(const string& input, string& output) {
72 parser.set_input("", input);
73 bool result = parser.parse_string();
74 if (result) {
75 parser.finish();
76 output = callbacks.output().data();
77 }
78 return result;
79 }
80
81 bool parse_array(const string& input, tree& output) {
82 parser.set_input("", input);
83 bool result = parser.parse_array();
84 if (result) {
85 parser.finish();
86 output = callbacks.output();
87 }
88 return result;
89 }
90
91 bool parse_object(const string& input, tree& output) {
92 parser.set_input("", input);
93 bool result = parser.parse_object();
94 if (result) {
95 parser.finish();
96 output = callbacks.output();
97 }
98 return result;
99 }
100
101 void parse_value(const string& input, tree& output) {
102 parser.set_input("", input);
103 parser.parse_value();
104 parser.finish();
105 output = callbacks.output();
106 }
107};
108
109template <typename Ch>
110struct standard_parser
111 : test_parser<
112 json_parser::detail::standard_callbacks<
113 basic_ptree<std::basic_string<Ch>, std::basic_string<Ch> > >,
114 Ch>
115{};
116
117template <typename Ch>
118struct prefixing_parser
119 : test_parser<
120 prefixing_callbacks<
121 basic_ptree<std::basic_string<Ch>, std::basic_string<Ch> > >,
122 Ch>
123{};
124
125#define BOM_N "\xef\xbb\xbf"
126#define BOM_W L"\xfeff"
127
128static void
129test_null_parse_result_is_input()
130{
131 std::string parsed;
132 standard_parser<char> p;
133 BOOST_TEST(p.parse_null("null", parsed));
134 BOOST_TEST_EQ("null", parsed);
135}
136
137static void
138test_uses_traits_from_null()
139{
140 std::string parsed;
141 prefixing_parser<char> p;
142 BOOST_TEST(p.parse_null("null", parsed));
143 BOOST_TEST_EQ("_:null", parsed);
144}
145
146static void
147test_null_parse_skips_bom()
148{
149 std::string parsed;
150 standard_parser<char> p;
151 BOOST_TEST(p.parse_null(BOM_N "null", parsed));
152 BOOST_TEST_EQ("null", parsed);
153}
154
155static void
156test_null_parse_result_is_input_w()
157{
158 std::wstring parsed;
159 standard_parser<wchar_t> p;
160 BOOST_TEST(p.parse_null(L"null", parsed));
161 BOOST_TEST(parsed == L"null");
162}
163
164static void
165test_uses_traits_from_null_w()
166{
167 std::wstring parsed;
168 prefixing_parser<wchar_t> p;
169 BOOST_TEST(p.parse_null(L"null", parsed));
170 BOOST_TEST(parsed == L"_:null");
171}
172
173static void
174test_null_parse_skips_bom_w()
175{
176 std::wstring parsed;
177 standard_parser<wchar_t> p;
178 BOOST_TEST(p.parse_null(BOM_W L"null", parsed));
179 BOOST_TEST(parsed == L"null");
180}
181
182template<std::size_t N>
183static void
184test_boolean_parse_result_is_input_n(const std::string (&param)[N])
185{
186 for(std::size_t i = 0 ; i < N ; ++i)
187 {
188 std::string parsed;
189 standard_parser<char> p;
190 BOOST_TEST(p.parse_boolean(param[i], parsed));
191 BOOST_TEST_EQ(param[i], parsed);
192 }
193}
194
195const std::string
196booleans_n[] = { "true", "false" };
197
198static void
199test_uses_traits_from_boolean_n()
200{
201 std::string parsed;
202 prefixing_parser<char> p;
203 BOOST_TEST(p.parse_boolean("true", parsed));
204 BOOST_TEST_EQ("b:true", parsed);
205}
206
207template<std::size_t N>
208static void
209test_boolean_parse_result_is_input_w(const std::wstring (&param)[N])
210{
211 for(std::size_t i = 0 ; i < N ; ++i)
212 {
213 std::wstring parsed;
214 standard_parser<wchar_t> p;
215 BOOST_TEST(p.parse_boolean(param[i], parsed));
216 BOOST_TEST(param[i] == parsed);
217 }
218}
219
220const std::wstring
221booleans_w[] = { L"true", L"false" };
222
223static void
224test_uses_traits_from_boolean_w()
225{
226 std::wstring parsed;
227 prefixing_parser<wchar_t> p;
228 BOOST_TEST(p.parse_boolean(L"true", parsed));
229 BOOST_TEST(parsed == L"b:true");
230}
231
232template<std::size_t N>
233static void
234test_number_parse_result_is_input_n(std::string const (&param)[N])
235{
236 for(std::size_t i = 0 ; i < N ; ++i)
237 {
238 std::string parsed;
239 standard_parser<char> p;
240 BOOST_TEST(p.parse_number(param[i], parsed));
241 BOOST_TEST_EQ(param[i], parsed);
242 }
243}
244
245std::string const
246numbers_n[] = {
247 "0",
248 "-0",
249 "1824",
250 "-0.1",
251 "123.142",
252 "1e+0",
253 "1E-0",
254 "1.1e134"
255};
256
257static void
258test_uses_traits_from_number_n()
259{
260 std::string parsed;
261 prefixing_parser<char> p;
262 BOOST_TEST(p.parse_number("12345", parsed));
263 BOOST_TEST_EQ("n:12345", parsed);
264}
265
266template<std::size_t N>
267static void
268test_number_parse_result_is_input_w(const std::wstring (&param)[N])
269{
270 for(std::size_t i = 0 ; i < N ; ++i)
271 {
272 std::wstring parsed;
273 standard_parser<wchar_t> p;
274 BOOST_TEST(p.parse_number(param[i], parsed));
275 BOOST_TEST(parsed == param[i]);
276 }
277}
278
279std::wstring const numbers_w[] = {
280 L"0",
281 L"-0",
282 L"1824",
283 L"-0.1",
284 L"123.142",
285 L"1e+0",
286 L"1E-0",
287 L"1.1e134"
288};
289
290static void
291test_uses_traits_from_number_w()
292{
293 std::wstring parsed;
294 prefixing_parser<wchar_t> p;
295 BOOST_TEST(p.parse_number(L"12345", parsed));
296 BOOST_TEST(parsed == L"n:12345");
297}
298
299struct string_input_n {
300 const char* encoded;
301 const char* expected;
302};
303
304template<std::size_t N>
305void test_string_parsed_correctly_n(string_input_n const (&param)[N])
306{
307 for(std::size_t i = 0 ; i < N ; ++i)
308 {
309 std::string parsed;
310 standard_parser<char> p;
311 BOOST_TEST(p.parse_string(param[i].encoded, parsed));
312 BOOST_TEST_EQ(param[i].expected, parsed);
313 }
314}
315
316const string_input_n strings_n[] = {
317 {.encoded: "\"\"", .expected: ""},
318 {.encoded: "\"abc\"", .expected: "abc"},
319 {.encoded: "\"a\\nb\"", .expected: "a\nb"},
320 {.encoded: "\"\\\"\"", .expected: "\""},
321 {.encoded: "\"\\\\\"", .expected: "\\"},
322 {.encoded: "\"\\/\"", .expected: "/"},
323 {.encoded: "\"\\b\"", .expected: "\b"},
324 {.encoded: "\"\\f\"", .expected: "\f"},
325 {.encoded: "\"\\r\"", .expected: "\r"},
326 {.encoded: "\"\\t\"", .expected: "\t"},
327 {.encoded: "\"\\u0001\\u00f2\\u28Ec\"", .expected: "\x01" "\xC3\xB2" "\xE2\xA3\xAC"},
328 {.encoded: "\"\\ud801\\udc37\"", .expected: "\xf0\x90\x90\xb7"}, // U+10437
329 {.encoded: "\xef\xbb\xbf\"\"", .expected: ""} // BOM
330};
331
332static void
333test_uses_string_callbacks()
334{
335 std::string parsed;
336 prefixing_parser<char> p;
337 BOOST_TEST(p.parse_string("\"a\"", parsed));
338 BOOST_TEST_EQ("s:a", parsed);
339}
340
341struct string_input_w {
342 const wchar_t* encoded;
343 const wchar_t* expected;
344};
345
346template<std::size_t N>
347void
348test_string_parsed_correctly_w(string_input_w const (&param)[N])
349{
350 for(std::size_t i = 0 ; i < N ; ++i)
351 {
352 std::wstring parsed;
353 standard_parser<wchar_t> p;
354 if(BOOST_TEST(p.parse_string(param[i].encoded, parsed)))
355 BOOST_TEST(param[i].expected == parsed);
356 }
357}
358
359const string_input_w strings_w[] = {
360 {.encoded: L"\"\"", .expected: L""},
361 {.encoded: L"\"abc\"", .expected: L"abc"},
362 {.encoded: L"\"a\\nb\"", .expected: L"a\nb"},
363 {.encoded: L"\"\\\"\"", .expected: L"\""},
364 {.encoded: L"\"\\\\\"", .expected: L"\\"},
365 {.encoded: L"\"\\/\"", .expected: L"/"},
366 {.encoded: L"\"\\b\"", .expected: L"\b"},
367 {.encoded: L"\"\\f\"", .expected: L"\f"},
368 {.encoded: L"\"\\r\"", .expected: L"\r"},
369 {.encoded: L"\"\\t\"", .expected: L"\t"},
370 {.encoded: L"\"\\u0001\\u00f2\\u28Ec\"", .expected: L"\x0001" L"\x00F2" L"\x28EC"},
371 {.encoded: L"\xfeff\"\"", .expected: L""} // BOM
372};
373
374static void
375test_empty_array()
376{
377 ptree tree;
378 standard_parser<char> p;
379 const char* input = " [ ]";
380 BOOST_TEST(p.parse_array(input, tree));
381 BOOST_TEST_EQ("", tree.data());
382 BOOST_TEST_EQ(0u, tree.size());
383}
384
385static void
386test_array_gets_tagged()
387{
388 wptree tree;
389 prefixing_parser<wchar_t> p;
390 const wchar_t* input = L" [ ]";
391 BOOST_TEST(p.parse_array(input, tree));
392 BOOST_TEST(tree.data() == L"a:");
393 BOOST_TEST_EQ(0u, tree.size());
394}
395
396static void
397test_array_with_values()
398{
399 wptree tree;
400 standard_parser<wchar_t> p;
401 const wchar_t* input = L"[\n"
402L" 123, \"abc\" ,true ,\n"
403L" null\n"
404L" ]";
405 if(!BOOST_TEST(p.parse_array(input, tree)))
406 return;
407 if(!BOOST_TEST_EQ(4u, tree.size()))
408 return;
409 wptree::iterator it = tree.begin();
410 BOOST_TEST(it->first == L"");
411 BOOST_TEST(it->second.data() == L"123");
412 ++it;
413 BOOST_TEST(it->first == L"");
414 BOOST_TEST(it->second.data() == L"abc");
415 ++it;
416 BOOST_TEST(it->first == L"");
417 BOOST_TEST(it->second.data() == L"true");
418 ++it;
419 BOOST_TEST(it->first == L"");
420 BOOST_TEST(it->second.data() == L"null");
421 ++it;
422 BOOST_TEST(tree.end() == it);
423}
424
425static void
426test_array_values_get_tagged()
427{
428 ptree tree;
429 prefixing_parser<char> p;
430 const char* input = "[\n"
431" 123, \"abc\" ,true ,\n"
432" null\n"
433" ]";
434 if(BOOST_TEST(p.parse_array(input, tree)))
435 if(BOOST_TEST_EQ(4u, tree.size()))
436 {
437 BOOST_TEST_EQ("a:", tree.data());
438 ptree::iterator it = tree.begin();
439 BOOST_TEST_EQ("", it->first);
440 BOOST_TEST_EQ("n:123", it->second.data());
441 ++it;
442 BOOST_TEST_EQ("", it->first);
443 BOOST_TEST_EQ("s:abc", it->second.data());
444 ++it;
445 BOOST_TEST_EQ("", it->first);
446 BOOST_TEST_EQ("b:true", it->second.data());
447 ++it;
448 BOOST_TEST_EQ("", it->first);
449 BOOST_TEST_EQ("_:null", it->second.data());
450 ++it;
451 BOOST_TEST(tree.end() == it);
452 }
453}
454
455static void
456test_nested_array()
457{
458 ptree tree;
459 standard_parser<char> p;
460 const char* input = "[[1,2],3,[4,5]]";
461 if(!BOOST_TEST(p.parse_array(input, tree)))
462 return;
463 if(!BOOST_TEST_EQ(3u, tree.size()))
464 return;
465 ptree::iterator it = tree.begin();
466 BOOST_TEST_EQ("", it->first);
467 {
468 ptree& sub = it->second;
469 BOOST_TEST_EQ("", sub.data());
470 if(!BOOST_TEST_EQ(2u, sub.size()))
471 return;
472 ptree::iterator iit = sub.begin();
473 BOOST_TEST_EQ("", iit->first);
474 BOOST_TEST_EQ("1", iit->second.data());
475 ++iit;
476 BOOST_TEST_EQ("", iit->first);
477 BOOST_TEST_EQ("2", iit->second.data());
478 ++iit;
479 BOOST_TEST(sub.end() == iit);
480 }
481 ++it;
482 BOOST_TEST_EQ("", it->first);
483 BOOST_TEST_EQ("3", it->second.data());
484 ++it;
485 BOOST_TEST_EQ("", it->first);
486 {
487 ptree& sub = it->second;
488 BOOST_TEST_EQ("", sub.data());
489 if(!BOOST_TEST_EQ(2u, sub.size()))
490 return;
491 ptree::iterator iit = sub.begin();
492 BOOST_TEST_EQ("", iit->first);
493 BOOST_TEST_EQ("4", iit->second.data());
494 ++iit;
495 BOOST_TEST_EQ("", iit->first);
496 BOOST_TEST_EQ("5", iit->second.data());
497 ++iit;
498 BOOST_TEST(sub.end() == iit);
499 }
500 ++it;
501 BOOST_TEST(tree.end() == it);
502}
503
504static void
505test_empty_object()
506{
507 ptree tree;
508 standard_parser<char> p;
509 const char* input = " { }";
510 if(BOOST_TEST(p.parse_object(input, tree)))
511 {
512 BOOST_TEST_EQ("", tree.data());
513 BOOST_TEST_EQ(0u, tree.size());
514 }
515}
516
517static void
518test_object_gets_tagged()
519{
520 wptree tree;
521 prefixing_parser<wchar_t> p;
522 const wchar_t* input = L" { }";
523 if(BOOST_TEST(p.parse_object(input, tree)))
524 {
525 BOOST_TEST(tree.data() == L"o:");
526 BOOST_TEST_EQ(0u, tree.size());
527 }
528}
529
530static void
531test_object_with_values()
532{
533 wptree tree;
534 standard_parser<wchar_t> p;
535 const wchar_t* input = L"{\n"
536L" \"1\":123, \"2\"\n"
537L" :\"abc\" ,\"3\": true ,\n"
538L" \"4\" : null\n"
539L" }";
540 if(BOOST_TEST(p.parse_object(input, tree)))
541 if(BOOST_TEST_EQ(4u, tree.size()))
542 {
543 wptree::iterator it = tree.begin();
544 BOOST_TEST(it->first == L"1");
545 BOOST_TEST(it->second.data() == L"123");
546 ++it;
547 BOOST_TEST(it->first == L"2");
548 BOOST_TEST(it->second.data() == L"abc");
549 ++it;
550 BOOST_TEST(it->first == L"3");
551 BOOST_TEST(it->second.data() == L"true");
552 ++it;
553 BOOST_TEST(it->first == L"4");
554 BOOST_TEST(it->second.data() == L"null");
555 ++it;
556 BOOST_TEST(tree.end() == it);
557 }
558}
559
560static void
561test_object_values_get_tagged()
562{
563 ptree tree;
564 prefixing_parser<char> p;
565 const char* input = "{\n"
566 "\"1\": 123, \"2\": \"abc\" ,\"3\": true ,\n"
567 "\"4\": null\n"
568 "}";
569 if(BOOST_TEST(p.parse_object(input, tree)))
570 if(BOOST_TEST_EQ(4u, tree.size()))
571 {
572 BOOST_TEST_EQ("o:", tree.data());
573 ptree::iterator it = tree.begin();
574 BOOST_TEST_EQ("1", it->first);
575 BOOST_TEST_EQ("n:123", it->second.data());
576 ++it;
577 BOOST_TEST_EQ("2", it->first);
578 BOOST_TEST_EQ("s:abc", it->second.data());
579 ++it;
580 BOOST_TEST_EQ("3", it->first);
581 BOOST_TEST_EQ("b:true", it->second.data());
582 ++it;
583 BOOST_TEST_EQ("4", it->first);
584 BOOST_TEST_EQ("_:null", it->second.data());
585 ++it;
586 BOOST_TEST(tree.end() == it);
587 }
588}
589
590static void
591test_nested_object()
592{
593 ptree tree;
594 standard_parser<char> p;
595 const char* input = "{\"a\":{\"b\":1,\"c\":2},\"d\":3,\"e\":{\"f\":4,\"g\":5}}";
596 if(!BOOST_TEST(p.parse_object(input, tree)))
597 return;
598 if(!BOOST_TEST_EQ(3u, tree.size()))
599 return;
600 ptree::iterator it = tree.begin();
601 BOOST_TEST_EQ("a", it->first);
602 {
603 ptree& sub = it->second;
604 BOOST_TEST_EQ("", sub.data());
605 if(!BOOST_TEST_EQ(2u, sub.size()))
606 return;
607 ptree::iterator iit = sub.begin();
608 BOOST_TEST_EQ("b", iit->first);
609 BOOST_TEST_EQ("1", iit->second.data());
610 ++iit;
611 BOOST_TEST_EQ("c", iit->first);
612 BOOST_TEST_EQ("2", iit->second.data());
613 ++iit;
614 BOOST_TEST(sub.end() == iit);
615 }
616 ++it;
617 BOOST_TEST_EQ("d", it->first);
618 BOOST_TEST_EQ("3", it->second.data());
619 ++it;
620 BOOST_TEST_EQ("e", it->first);
621 {
622 ptree& sub = it->second;
623 BOOST_TEST_EQ("", sub.data());
624 if(!BOOST_TEST_EQ(2u, sub.size()))
625 return;
626 ptree::iterator iit = sub.begin();
627 BOOST_TEST_EQ("f", iit->first);
628 BOOST_TEST_EQ("4", iit->second.data());
629 ++iit;
630 BOOST_TEST_EQ("g", iit->first);
631 BOOST_TEST_EQ("5", iit->second.data());
632 ++iit;
633 BOOST_TEST(sub.end() == iit);
634 }
635 ++it;
636 BOOST_TEST(tree.end() == it);
637}
638
639static void
640test_array_in_object()
641{
642 ptree tree;
643 standard_parser<char> p;
644 const char* input = "{\"a\":[1,2],\"b\":3,\"c\":[4,5]}";
645 if(!BOOST_TEST(p.parse_object(input, tree)))
646 return;
647 if(!BOOST_TEST_EQ(3u, tree.size()))
648 return;
649 ptree::iterator it = tree.begin();
650 BOOST_TEST_EQ("a", it->first);
651 {
652 ptree& sub = it->second;
653 BOOST_TEST_EQ("", sub.data());
654 if(BOOST_TEST_EQ(2u, sub.size()))
655 {
656 ptree::iterator iit = sub.begin();
657 BOOST_TEST_EQ("", iit->first);
658 BOOST_TEST_EQ("1", iit->second.data());
659 ++iit;
660 BOOST_TEST_EQ("", iit->first);
661 BOOST_TEST_EQ("2", iit->second.data());
662 ++iit;
663 BOOST_TEST(sub.end() == iit);
664 }
665 }
666 ++it;
667 BOOST_TEST_EQ("b", it->first);
668 BOOST_TEST_EQ("3", it->second.data());
669 ++it;
670 BOOST_TEST_EQ("c", it->first);
671 {
672 ptree& sub = it->second;
673 BOOST_TEST_EQ("", sub.data());
674 if(BOOST_TEST_EQ(2u, sub.size()))
675 {
676 ptree::iterator iit = sub.begin();
677 BOOST_TEST_EQ("", iit->first);
678 BOOST_TEST_EQ("4", iit->second.data());
679 ++iit;
680 BOOST_TEST_EQ("", iit->first);
681 BOOST_TEST_EQ("5", iit->second.data());
682 ++iit;
683 BOOST_TEST(sub.end() == iit);
684 }
685 }
686 ++it;
687 BOOST_TEST(tree.end() == it);
688}
689
690static void
691test_object_in_array()
692{
693 ptree tree;
694 standard_parser<char> p;
695 const char* input = "[{\"a\":1,\"b\":2},3,{\"c\":4,\"d\":5}]";
696 if(!BOOST_TEST(p.parse_array(input, tree)))
697 return;
698 if(!BOOST_TEST_EQ(3u, tree.size()))
699 return;
700 ptree::iterator it = tree.begin();
701 BOOST_TEST_EQ("", it->first);
702 {
703 ptree& sub = it->second;
704 BOOST_TEST_EQ("", sub.data());
705 if(BOOST_TEST_EQ(2u, sub.size()))
706 {
707 ptree::iterator iit = sub.begin();
708 BOOST_TEST_EQ("a", iit->first);
709 BOOST_TEST_EQ("1", iit->second.data());
710 ++iit;
711 BOOST_TEST_EQ("b", iit->first);
712 BOOST_TEST_EQ("2", iit->second.data());
713 ++iit;
714 BOOST_TEST(sub.end() == iit);
715 }
716 }
717 ++it;
718 BOOST_TEST_EQ("", it->first);
719 BOOST_TEST_EQ("3", it->second.data());
720 ++it;
721 BOOST_TEST_EQ("", it->first);
722 {
723 ptree& sub = it->second;
724 BOOST_TEST_EQ("", sub.data());
725 if(BOOST_TEST_EQ(2u, sub.size()))
726 {
727 ptree::iterator iit = sub.begin();
728 BOOST_TEST_EQ("c", iit->first);
729 BOOST_TEST_EQ("4", iit->second.data());
730 ++iit;
731 BOOST_TEST_EQ("d", iit->first);
732 BOOST_TEST_EQ("5", iit->second.data());
733 ++iit;
734 BOOST_TEST(sub.end() == iit);
735 }
736 }
737 ++it;
738 BOOST_TEST(tree.end() == it);
739}
740
741static void
742test_parser_works_with_input_iterators()
743{
744 const char* input = " {\n"
745" \"1\":123, \"2\"\n"
746" :\"abc\" ,\"3\": true ,\n"
747" \"4\" : null, \"5\" : [ 1, 23\n"
748" , 456 ]\n"
749" }";
750
751 std::istringstream is(input);
752 typedef std::istreambuf_iterator<char> iterator;
753 json_parser::detail::standard_callbacks<ptree> callbacks;
754 json_parser::detail::utf8_utf8_encoding encoding;
755 json_parser::detail::parser<json_parser::detail::standard_callbacks<ptree>,
756 json_parser::detail::utf8_utf8_encoding,
757 iterator, iterator>
758 p(callbacks, encoding);
759
760 p.set_input(filename: "", r: boost::make_iterator_range(Begin: iterator(is), End: iterator()));
761 p.parse_value();
762
763 const ptree& tree = callbacks.output();
764 if(!BOOST_TEST_EQ(5u, tree.size()))
765 return;
766 ptree::const_iterator it = tree.begin();
767 BOOST_TEST_EQ("1", it->first);
768 BOOST_TEST_EQ("123", it->second.data());
769 ++it;
770 BOOST_TEST_EQ("2", it->first);
771 BOOST_TEST_EQ("abc", it->second.data());
772 ++it;
773 BOOST_TEST_EQ("3", it->first);
774 BOOST_TEST_EQ("true", it->second.data());
775 ++it;
776 BOOST_TEST_EQ("4", it->first);
777 BOOST_TEST_EQ("null", it->second.data());
778 ++it;
779 BOOST_TEST_EQ("5", it->first);
780 {
781 const ptree& sub = it->second;
782 BOOST_TEST_EQ("", sub.data());
783 if(!BOOST_TEST_EQ(3u, sub.size()))
784 return;
785 ptree::const_iterator iit = sub.begin();
786 BOOST_TEST_EQ("", iit->first);
787 BOOST_TEST_EQ("1", iit->second.data());
788 ++iit;
789 BOOST_TEST_EQ("", iit->first);
790 BOOST_TEST_EQ("23", iit->second.data());
791 ++iit;
792 BOOST_TEST_EQ("", iit->first);
793 BOOST_TEST_EQ("456", iit->second.data());
794 ++iit;
795 BOOST_TEST(sub.end() == iit);
796 }
797 ++it;
798 BOOST_TEST(tree.end() == it);
799}
800
801struct bad_parse_n {
802 const char* json;
803 const char* message_substring;
804};
805
806template<std::size_t N>
807void test_parse_error_thrown_with_message_n(bad_parse_n const (&param)[N])
808{
809 for(std::size_t i = 0 ; i < N ; ++i)
810 {
811 try {
812 standard_parser<char> p;
813 ptree dummy;
814 p.parse_value(input: param[i].json, output&: dummy);
815 BOOST_ERROR("expected exception");
816 } catch (json_parser::json_parser_error& e) {
817 std::string message = e.message();
818 if(message.find(param[i].message_substring) ==
819 std::string::npos)
820 {
821 std::ostringstream ss;
822 ss << "bad error message on input '" << param[i].json
823 << "', need: '" << param[i].message_substring
824 << "' but found '" << message << "'";
825 BOOST_ERROR(ss.str().c_str());
826 }
827 }
828 }
829}
830
831const bad_parse_n errors_n[] = {
832 {.json: "", .message_substring: "expected value"},
833 {.json: "(", .message_substring: "expected value"},
834
835 {.json: "n", .message_substring: "expected 'null'"},
836 {.json: "nu", .message_substring: "expected 'null'"},
837 {.json: "nul", .message_substring: "expected 'null'"},
838 {.json: "n ", .message_substring: "expected 'null'"},
839 {.json: "nu ", .message_substring: "expected 'null'"},
840 {.json: "nul ", .message_substring: "expected 'null'"},
841 {.json: "nx", .message_substring: "expected 'null'"},
842 {.json: "nux", .message_substring: "expected 'null'"},
843 {.json: "nulx", .message_substring: "expected 'null'"},
844
845 {.json: "t", .message_substring: "expected 'true'"},
846 {.json: "tr", .message_substring: "expected 'true'"},
847 {.json: "tu", .message_substring: "expected 'true'"},
848 {.json: "t ", .message_substring: "expected 'true'"},
849 {.json: "tr ", .message_substring: "expected 'true'"},
850 {.json: "tru ", .message_substring: "expected 'true'"},
851 {.json: "tx", .message_substring: "expected 'true'"},
852 {.json: "trx", .message_substring: "expected 'true'"},
853 {.json: "trux", .message_substring: "expected 'true'"},
854
855 {.json: "f", .message_substring: "expected 'false'"},
856 {.json: "fa", .message_substring: "expected 'false'"},
857 {.json: "fal", .message_substring: "expected 'false'"},
858 {.json: "fals", .message_substring: "expected 'false'"},
859 {.json: "f ", .message_substring: "expected 'false'"},
860 {.json: "fa ", .message_substring: "expected 'false'"},
861 {.json: "fal ", .message_substring: "expected 'false'"},
862 {.json: "fals ", .message_substring: "expected 'false'"},
863 {.json: "fx", .message_substring: "expected 'false'"},
864 {.json: "fax", .message_substring: "expected 'false'"},
865 {.json: "falx", .message_substring: "expected 'false'"},
866 {.json: "falsx", .message_substring: "expected 'false'"},
867
868 {.json: "-", .message_substring: "expected digits"},
869 {.json: "01", .message_substring: "garbage after data"},
870 {.json: "0.", .message_substring: "need at least one digit after '.'"},
871 {.json: "0e", .message_substring: "need at least one digit in exponent"},
872 {.json: "0e-", .message_substring: "need at least one digit in exponent"},
873
874 {.json: "\"", .message_substring: "unterminated string"},
875 {.json: "\"asd", .message_substring: "unterminated string"},
876 {.json: "\"\n\"", .message_substring: "invalid code sequence"}, // control character
877 {.json: "\"\xff\"", .message_substring: "invalid code sequence"}, // bad lead byte
878 {.json: "\"\x80\"", .message_substring: "invalid code sequence"}, // stray trail byte
879 {.json: "\"\xc0", .message_substring: "invalid code sequence"}, // eos after lead byte
880 {.json: "\"\xc0\"", .message_substring: "invalid code sequence"}, // bad trail byte
881 {.json: "\"\xc0m\"", .message_substring: "invalid code sequence"}, // also bad trail byte
882 {.json: "\"\\", .message_substring: "invalid escape sequence"},
883 {.json: "\"\\p\"", .message_substring: "invalid escape sequence"},
884 {.json: "\"\\u", .message_substring: "invalid escape sequence"},
885 {.json: "\"\\u\"", .message_substring: "invalid escape sequence"},
886 {.json: "\"\\ug\"", .message_substring: "invalid escape sequence"},
887 {.json: "\"\\u1\"", .message_substring: "invalid escape sequence"},
888 {.json: "\"\\u1g\"", .message_substring: "invalid escape sequence"},
889 {.json: "\"\\u11\"", .message_substring: "invalid escape sequence"},
890 {.json: "\"\\u11g\"", .message_substring: "invalid escape sequence"},
891 {.json: "\"\\u111\"", .message_substring: "invalid escape sequence"},
892 {.json: "\"\\u111g\"", .message_substring: "invalid escape sequence"},
893 {.json: "\"\\ude00\"", .message_substring: "stray low surrogate"},
894 {.json: "\"\\ud900", .message_substring: "stray high surrogate"},
895 {.json: "\"\\ud900foo\"", .message_substring: "stray high surrogate"},
896 {.json: "\"\\ud900\\", .message_substring: "expected codepoint reference"},
897 {.json: "\"\\ud900\\n\"", .message_substring: "expected codepoint reference"},
898 {.json: "\"\\ud900\\u1000\"", .message_substring: "expected low surrogate"},
899
900 {.json: "[", .message_substring: "expected value"},
901 {.json: "[1", .message_substring: "expected ']' or ','"},
902 {.json: "[1,", .message_substring: "expected value"},
903 {.json: "[1,]", .message_substring: "expected value"},
904 {.json: "[1}", .message_substring: "expected ']' or ','"},
905
906 {.json: "{", .message_substring: "expected key string"},
907 {.json: "{1:2}", .message_substring: "expected key string"},
908 {.json: "{\"\"", .message_substring: "expected ':'"},
909 {.json: "{\"\"}", .message_substring: "expected ':'"},
910 {.json: "{\"\":", .message_substring: "expected value"},
911 {.json: "{\"\":}", .message_substring: "expected value"},
912 {.json: "{\"\":0", .message_substring: "expected '}' or ','"},
913 {.json: "{\"\":0]", .message_substring: "expected '}' or ','"},
914 {.json: "{\"\":0,", .message_substring: "expected key string"},
915 {.json: "{\"\":0,}", .message_substring: "expected key string"},
916};
917
918struct bad_parse_w {
919 const wchar_t* json;
920 const char* message_substring;
921};
922
923struct do_narrow
924{
925 char operator()(std::wstring::value_type w) const
926 {
927 unsigned long u = static_cast<unsigned long>(w);
928 if (u < 32 || u > 126)
929 return '?';
930 else
931 return static_cast<char>(u);
932 }
933};
934static std::string
935make_narrow(std::wstring const& in)
936{
937 std::string result(in.size(), ' ');
938 std::transform(first: in.begin(), last: in.end(), result: result.begin(), unary_op: do_narrow());
939 return result;
940}
941
942template<std::size_t N>
943void
944test_parse_error_thrown_with_message_w(bad_parse_w const (&param)[N])
945{
946 for(std::size_t i = 0 ; i < N ; ++i)
947 {
948 try {
949 standard_parser<wchar_t> p;
950 wptree dummy;
951 p.parse_value(input: param[i].json, output&: dummy);
952 BOOST_ERROR("expected exception");
953 } catch (json_parser::json_parser_error& e) {
954 std::string message = e.message();
955 if (message.find(param[i].message_substring) ==
956 std::string::npos)
957 {
958 std::ostringstream ss;
959 ss << "bad error message on input '" << make_narrow(param[i].json)
960 << "', need: '" << param[i].message_substring
961 << "' but found '" << message << "'";
962 BOOST_ERROR(ss.str().c_str());
963 }
964 }
965 }
966}
967
968const bad_parse_w
969errors_w[] = {
970 {.json: L"", .message_substring: "expected value"},
971 {.json: L"(", .message_substring: "expected value"},
972
973 {.json: L"n", .message_substring: "expected 'null'"},
974 {.json: L"nu", .message_substring: "expected 'null'"},
975 {.json: L"nul", .message_substring: "expected 'null'"},
976 {.json: L"n ", .message_substring: "expected 'null'"},
977 {.json: L"nu ", .message_substring: "expected 'null'"},
978 {.json: L"nul ", .message_substring: "expected 'null'"},
979 {.json: L"nx", .message_substring: "expected 'null'"},
980 {.json: L"nux", .message_substring: "expected 'null'"},
981 {.json: L"nulx", .message_substring: "expected 'null'"},
982
983 {.json: L"t", .message_substring: "expected 'true'"},
984 {.json: L"tr", .message_substring: "expected 'true'"},
985 {.json: L"tu", .message_substring: "expected 'true'"},
986 {.json: L"t ", .message_substring: "expected 'true'"},
987 {.json: L"tr ", .message_substring: "expected 'true'"},
988 {.json: L"tru ", .message_substring: "expected 'true'"},
989 {.json: L"tx", .message_substring: "expected 'true'"},
990 {.json: L"trx", .message_substring: "expected 'true'"},
991 {.json: L"trux", .message_substring: "expected 'true'"},
992
993 {.json: L"f", .message_substring: "expected 'false'"},
994 {.json: L"fa", .message_substring: "expected 'false'"},
995 {.json: L"fal", .message_substring: "expected 'false'"},
996 {.json: L"fals", .message_substring: "expected 'false'"},
997 {.json: L"f ", .message_substring: "expected 'false'"},
998 {.json: L"fa ", .message_substring: "expected 'false'"},
999 {.json: L"fal ", .message_substring: "expected 'false'"},
1000 {.json: L"fals ", .message_substring: "expected 'false'"},
1001 {.json: L"fx", .message_substring: "expected 'false'"},
1002 {.json: L"fax", .message_substring: "expected 'false'"},
1003 {.json: L"falx", .message_substring: "expected 'false'"},
1004 {.json: L"falsx", .message_substring: "expected 'false'"},
1005
1006 {.json: L"-", .message_substring: "expected digits"},
1007 {.json: L"01", .message_substring: "garbage after data"},
1008 {.json: L"0.", .message_substring: "need at least one digit after '.'"},
1009 {.json: L"0e", .message_substring: "need at least one digit in exponent"},
1010 {.json: L"0e-", .message_substring: "need at least one digit in exponent"},
1011
1012 {.json: L"\"", .message_substring: "unterminated string"},
1013 {.json: L"\"asd", .message_substring: "unterminated string"},
1014 {.json: L"\"\n\"", .message_substring: "invalid code sequence"}, // control character
1015 // Encoding not known, so no UTF-16 encoding error tests.
1016 {.json: L"\"\\", .message_substring: "invalid escape sequence"},
1017 {.json: L"\"\\p\"", .message_substring: "invalid escape sequence"},
1018 {.json: L"\"\\u", .message_substring: "invalid escape sequence"},
1019 {.json: L"\"\\u\"", .message_substring: "invalid escape sequence"},
1020 {.json: L"\"\\ug\"", .message_substring: "invalid escape sequence"},
1021 {.json: L"\"\\u1\"", .message_substring: "invalid escape sequence"},
1022 {.json: L"\"\\u1g\"", .message_substring: "invalid escape sequence"},
1023 {.json: L"\"\\u11\"", .message_substring: "invalid escape sequence"},
1024 {.json: L"\"\\u11g\"", .message_substring: "invalid escape sequence"},
1025 {.json: L"\"\\u111\"", .message_substring: "invalid escape sequence"},
1026 {.json: L"\"\\u111g\"", .message_substring: "invalid escape sequence"},
1027 {.json: L"\"\\ude00\"", .message_substring: "stray low surrogate"},
1028 {.json: L"\"\\ud900", .message_substring: "stray high surrogate"},
1029 {.json: L"\"\\ud900foo\"", .message_substring: "stray high surrogate"},
1030 {.json: L"\"\\ud900\\", .message_substring: "expected codepoint reference"},
1031 {.json: L"\"\\ud900\\n\"", .message_substring: "expected codepoint reference"},
1032 {.json: L"\"\\ud900\\u1000\"", .message_substring: "expected low surrogate"},
1033
1034 {.json: L"[", .message_substring: "expected value"},
1035 {.json: L"[1", .message_substring: "expected ']' or ','"},
1036 {.json: L"[1,", .message_substring: "expected value"},
1037 {.json: L"[1,]", .message_substring: "expected value"},
1038 {.json: L"[1}", .message_substring: "expected ']' or ','"},
1039
1040 {.json: L"{", .message_substring: "expected key string"},
1041 {.json: L"{1:2}", .message_substring: "expected key string"},
1042 {.json: L"{\"\"", .message_substring: "expected ':'"},
1043 {.json: L"{\"\"}", .message_substring: "expected ':'"},
1044 {.json: L"{\"\":", .message_substring: "expected value"},
1045 {.json: L"{\"\":}", .message_substring: "expected value"},
1046 {.json: L"{\"\":0", .message_substring: "expected '}' or ','"},
1047 {.json: L"{\"\":0]", .message_substring: "expected '}' or ','"},
1048 {.json: L"{\"\":0,", .message_substring: "expected key string"},
1049 {.json: L"{\"\":0,}", .message_substring: "expected key string"},
1050};
1051
1052int main()
1053{
1054 test_null_parse_result_is_input();
1055 test_uses_traits_from_null();
1056 test_null_parse_skips_bom();
1057 test_null_parse_result_is_input_w();
1058 test_null_parse_skips_bom_w();
1059 test_uses_traits_from_boolean_n();
1060 test_uses_traits_from_boolean_w();
1061 test_boolean_parse_result_is_input_n(param: booleans_n);
1062 test_boolean_parse_result_is_input_w(param: booleans_w);
1063 test_number_parse_result_is_input_n(param: numbers_n);
1064 test_number_parse_result_is_input_w(param: numbers_w);
1065 test_uses_traits_from_number_n();
1066 test_string_parsed_correctly_n(param: strings_n);
1067 test_string_parsed_correctly_w(param: strings_w);
1068 test_parse_error_thrown_with_message_n(param: errors_n);
1069 test_parse_error_thrown_with_message_w(param: errors_w);
1070 test_uses_string_callbacks();
1071 test_empty_array();
1072 test_array_with_values();
1073 test_array_values_get_tagged();
1074 test_nested_array();
1075 test_empty_object();
1076 test_object_gets_tagged();
1077 test_object_with_values();
1078 test_object_values_get_tagged();
1079 test_nested_object();
1080 test_array_in_object();
1081 test_object_in_array();
1082 test_parser_works_with_input_iterators();
1083 test_uses_traits_from_null_w();
1084 test_uses_traits_from_number_w();
1085 test_array_gets_tagged();
1086 return boost::report_errors();
1087}
1088
1089/*
1090test_suite* init_unit_test_suite(int, char*[])
1091{
1092 master_test_suite_t& ts = boost::unit_test::framework::master_test_suite();
1093 ts.add(ARRAY_TEST_CASE(boolean_parse_result_is_input_n, booleans_n));
1094 ts.add(ARRAY_TEST_CASE(boolean_parse_result_is_input_w, booleans_w));
1095 ts.add(ARRAY_TEST_CASE(number_parse_result_is_input_n, numbers_n));
1096 ts.add(ARRAY_TEST_CASE(number_parse_result_is_input_w, numbers_w));
1097 ts.add(ARRAY_TEST_CASE(string_parsed_correctly_n, strings_n));
1098 ts.add(ARRAY_TEST_CASE(string_parsed_correctly_w, strings_w));
1099 ts.add(ARRAY_TEST_CASE(parse_error_thrown_with_message_n, errors_n));
1100 ts.add(ARRAY_TEST_CASE(parse_error_thrown_with_message_w, errors_w));
1101
1102 return 0;
1103}
1104*/

source code of boost/libs/property_tree/test/test_json_parser2.cpp