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"
7 #define BOOST_TEST_NO_MAIN
8 #include <boost/test/unit_test.hpp>
9 #include <boost/test/parameterized_test.hpp>
11 #include <boost/property_tree/ptree.hpp>
12 #include <boost/range/iterator_range.hpp>
18 using namespace boost::property_tree
;
20 template <typename Ch
> struct encoding
;
21 template <> struct encoding
<char>
22 : json_parser::detail::utf8_utf8_encoding
24 template <> struct encoding
<wchar_t>
25 : json_parser::detail::wide_wide_encoding
28 template <typename Callbacks
, typename Ch
>
32 ::encoding
<Ch
> encoding
;
33 typedef std::basic_string
<Ch
> string
;
34 typedef basic_ptree
<string
, string
> tree
;
35 json_parser::detail::parser
<Callbacks
, ::encoding
<Ch
>,
36 typename
string::const_iterator
,
37 typename
string::const_iterator
>
40 test_parser() : parser(callbacks
, encoding
) {}
42 bool parse_null(const string
& input
, string
& output
) {
43 parser
.set_input("", input
);
44 bool result
= parser
.parse_null();
47 output
= callbacks
.output().data();
52 bool parse_boolean(const string
& input
, string
& output
) {
53 parser
.set_input("", input
);
54 bool result
= parser
.parse_boolean();
57 output
= callbacks
.output().data();
62 bool parse_number(const string
& input
, string
& output
) {
63 parser
.set_input("", input
);
64 bool result
= parser
.parse_number();
67 output
= callbacks
.output().data();
72 bool parse_string(const string
& input
, string
& output
) {
73 parser
.set_input("", input
);
74 bool result
= parser
.parse_string();
77 output
= callbacks
.output().data();
82 bool parse_array(const string
& input
, tree
& output
) {
83 parser
.set_input("", input
);
84 bool result
= parser
.parse_array();
87 output
= callbacks
.output();
92 bool parse_object(const string
& input
, tree
& output
) {
93 parser
.set_input("", input
);
94 bool result
= parser
.parse_object();
97 output
= callbacks
.output();
102 void parse_value(const string
& input
, tree
& output
) {
103 parser
.set_input("", input
);
104 parser
.parse_value();
106 output
= callbacks
.output();
110 template <typename Ch
>
111 struct standard_parser
113 json_parser::detail::standard_callbacks
<
114 basic_ptree
<std::basic_string
<Ch
>, std::basic_string
<Ch
> > >,
118 template <typename Ch
>
119 struct prefixing_parser
122 basic_ptree
<std::basic_string
<Ch
>, std::basic_string
<Ch
> > >,
126 #define BOM_N "\xef\xbb\xbf"
127 #define BOM_W L"\xfeff"
129 namespace boost
{ namespace test_tools
{ namespace tt_detail
{
131 struct print_log_value
<std::wstring
> {
132 void operator()(std::ostream
& os
, const std::wstring
& s
) {
133 print_log_value
<const wchar_t*>()(os
, s
.c_str());
137 BOOST_TEST_DONT_PRINT_LOG_VALUE(ptree::iterator
)
138 BOOST_TEST_DONT_PRINT_LOG_VALUE(ptree::const_iterator
)
139 BOOST_TEST_DONT_PRINT_LOG_VALUE(wptree::iterator
)
140 BOOST_TEST_DONT_PRINT_LOG_VALUE(wptree::const_iterator
)
142 BOOST_AUTO_TEST_CASE(null_parse_result_is_input
) {
144 standard_parser
<char> p
;
145 BOOST_REQUIRE(p
.parse_null("null", parsed
));
146 BOOST_CHECK_EQUAL("null", parsed
);
149 BOOST_AUTO_TEST_CASE(uses_traits_from_null
)
152 prefixing_parser
<char> p
;
153 BOOST_REQUIRE(p
.parse_null("null", parsed
));
154 BOOST_CHECK_EQUAL("_:null", parsed
);
157 BOOST_AUTO_TEST_CASE(null_parse_skips_bom
) {
159 standard_parser
<char> p
;
160 BOOST_REQUIRE(p
.parse_null(BOM_N
"null", parsed
));
161 BOOST_CHECK_EQUAL("null", parsed
);
164 BOOST_AUTO_TEST_CASE(null_parse_result_is_input_w
) {
166 standard_parser
<wchar_t> p
;
167 BOOST_REQUIRE(p
.parse_null(L
"null", parsed
));
168 BOOST_CHECK_EQUAL(L
"null", parsed
);
171 BOOST_AUTO_TEST_CASE(uses_traits_from_null_w
)
174 prefixing_parser
<wchar_t> p
;
175 BOOST_REQUIRE(p
.parse_null(L
"null", parsed
));
176 BOOST_CHECK_EQUAL(L
"_:null", parsed
);
179 BOOST_AUTO_TEST_CASE(null_parse_skips_bom_w
) {
181 standard_parser
<wchar_t> p
;
182 BOOST_REQUIRE(p
.parse_null(BOM_W L
"null", parsed
));
183 BOOST_CHECK_EQUAL(L
"null", parsed
);
186 void boolean_parse_result_is_input_n(const char* param
) {
188 standard_parser
<char> p
;
189 BOOST_REQUIRE(p
.parse_boolean(param
, parsed
));
190 BOOST_CHECK_EQUAL(param
, parsed
);
193 const char* const booleans_n
[] = { "true", "false" };
195 BOOST_AUTO_TEST_CASE(uses_traits_from_boolean_n
)
198 prefixing_parser
<char> p
;
199 BOOST_REQUIRE(p
.parse_boolean("true", parsed
));
200 BOOST_CHECK_EQUAL("b:true", parsed
);
203 void boolean_parse_result_is_input_w(const wchar_t* param
) {
205 standard_parser
<wchar_t> p
;
206 BOOST_REQUIRE(p
.parse_boolean(param
, parsed
));
207 BOOST_CHECK_EQUAL(param
, parsed
);
210 const wchar_t* const booleans_w
[] = { L
"true", L
"false" };
212 BOOST_AUTO_TEST_CASE(uses_traits_from_boolean_w
)
215 prefixing_parser
<wchar_t> p
;
216 BOOST_REQUIRE(p
.parse_boolean(L
"true", parsed
));
217 BOOST_CHECK_EQUAL(L
"b:true", parsed
);
220 void number_parse_result_is_input_n(const char* param
) {
222 standard_parser
<char> p
;
223 BOOST_REQUIRE(p
.parse_number(param
, parsed
));
224 BOOST_CHECK_EQUAL(param
, parsed
);
227 const char* const numbers_n
[] = {
238 BOOST_AUTO_TEST_CASE(uses_traits_from_number_n
)
241 prefixing_parser
<char> p
;
242 BOOST_REQUIRE(p
.parse_number("12345", parsed
));
243 BOOST_CHECK_EQUAL("n:12345", parsed
);
246 void number_parse_result_is_input_w(const wchar_t* param
) {
248 standard_parser
<wchar_t> p
;
249 BOOST_REQUIRE(p
.parse_number(param
, parsed
));
250 BOOST_CHECK_EQUAL(param
, parsed
);
253 const wchar_t* const numbers_w
[] = {
264 BOOST_AUTO_TEST_CASE(uses_traits_from_number_w
)
267 prefixing_parser
<wchar_t> p
;
268 BOOST_REQUIRE(p
.parse_number(L
"12345", parsed
));
269 BOOST_CHECK_EQUAL(L
"n:12345", parsed
);
272 struct string_input_n
{
274 const char* expected
;
277 void string_parsed_correctly_n(string_input_n param
) {
279 standard_parser
<char> p
;
280 BOOST_REQUIRE(p
.parse_string(param
.encoded
, parsed
));
281 BOOST_CHECK_EQUAL(param
.expected
, parsed
);
284 const string_input_n strings_n
[] = {
287 {"\"a\\nb\"", "a\nb"},
295 {"\"\\u0001\\u00f2\\u28Ec\"", "\x01" "\xC3\xB2" "\xE2\xA3\xAC"},
296 {"\"\\ud801\\udc37\"", "\xf0\x90\x90\xb7"}, // U+10437
297 {"\xef\xbb\xbf\"\"", ""} // BOM
300 BOOST_AUTO_TEST_CASE(uses_string_callbacks
)
303 prefixing_parser
<char> p
;
304 BOOST_REQUIRE(p
.parse_string("\"a\"", parsed
));
305 BOOST_CHECK_EQUAL("s:a", parsed
);
308 struct string_input_w
{
309 const wchar_t* encoded
;
310 const wchar_t* expected
;
313 void string_parsed_correctly_w(string_input_w param
) {
315 standard_parser
<wchar_t> p
;
316 BOOST_REQUIRE(p
.parse_string(param
.encoded
, parsed
));
317 BOOST_CHECK_EQUAL(param
.expected
, parsed
);
320 const string_input_w strings_w
[] = {
322 {L
"\"abc\"", L
"abc"},
323 {L
"\"a\\nb\"", L
"a\nb"},
324 {L
"\"\\\"\"", L
"\""},
325 {L
"\"\\\\\"", L
"\\"},
331 {L
"\"\\u0001\\u00f2\\u28Ec\"", L
"\x0001" L
"\x00F2" L
"\x28EC"},
332 {L
"\xfeff\"\"", L
""} // BOM
335 BOOST_AUTO_TEST_CASE(empty_array
) {
337 standard_parser
<char> p
;
338 const char* input
= " [ ]";
339 BOOST_REQUIRE(p
.parse_array(input
, tree
));
340 BOOST_CHECK_EQUAL("", tree
.data());
341 BOOST_CHECK_EQUAL(0u, tree
.size());
344 BOOST_AUTO_TEST_CASE(array_gets_tagged
) {
346 prefixing_parser
<wchar_t> p
;
347 const wchar_t* input
= L
" [ ]";
348 BOOST_REQUIRE(p
.parse_array(input
, tree
));
349 BOOST_CHECK_EQUAL(L
"a:", tree
.data());
350 BOOST_CHECK_EQUAL(0u, tree
.size());
353 BOOST_AUTO_TEST_CASE(array_with_values
) {
355 standard_parser
<wchar_t> p
;
356 const wchar_t* input
= L
"[\n"
357 L
" 123, \"abc\" ,true ,\n"
360 BOOST_REQUIRE(p
.parse_array(input
, tree
));
361 BOOST_REQUIRE_EQUAL(4u, tree
.size());
362 wptree::iterator it
= tree
.begin();
363 BOOST_CHECK_EQUAL(L
"", it
->first
);
364 BOOST_CHECK_EQUAL(L
"123", it
->second
.data());
366 BOOST_CHECK_EQUAL(L
"", it
->first
);
367 BOOST_CHECK_EQUAL(L
"abc", it
->second
.data());
369 BOOST_CHECK_EQUAL(L
"", it
->first
);
370 BOOST_CHECK_EQUAL(L
"true", it
->second
.data());
372 BOOST_CHECK_EQUAL(L
"", it
->first
);
373 BOOST_CHECK_EQUAL(L
"null", it
->second
.data());
375 BOOST_CHECK_EQUAL(tree
.end(), it
);
378 BOOST_AUTO_TEST_CASE(array_values_get_tagged
) {
380 prefixing_parser
<char> p
;
381 const char* input
= "[\n"
382 " 123, \"abc\" ,true ,\n"
385 BOOST_REQUIRE(p
.parse_array(input
, tree
));
386 BOOST_REQUIRE_EQUAL(4u, tree
.size());
387 BOOST_CHECK_EQUAL("a:", tree
.data());
388 ptree::iterator it
= tree
.begin();
389 BOOST_CHECK_EQUAL("", it
->first
);
390 BOOST_CHECK_EQUAL("n:123", it
->second
.data());
392 BOOST_CHECK_EQUAL("", it
->first
);
393 BOOST_CHECK_EQUAL("s:abc", it
->second
.data());
395 BOOST_CHECK_EQUAL("", it
->first
);
396 BOOST_CHECK_EQUAL("b:true", it
->second
.data());
398 BOOST_CHECK_EQUAL("", it
->first
);
399 BOOST_CHECK_EQUAL("_:null", it
->second
.data());
401 BOOST_CHECK_EQUAL(tree
.end(), it
);
404 BOOST_AUTO_TEST_CASE(nested_array
) {
406 standard_parser
<char> p
;
407 const char* input
= "[[1,2],3,[4,5]]";
408 BOOST_REQUIRE(p
.parse_array(input
, tree
));
409 BOOST_REQUIRE_EQUAL(3u, tree
.size());
410 ptree::iterator it
= tree
.begin();
411 BOOST_CHECK_EQUAL("", it
->first
);
413 ptree
& sub
= it
->second
;
414 BOOST_CHECK_EQUAL("", sub
.data());
415 BOOST_REQUIRE_EQUAL(2u, sub
.size());
416 ptree::iterator iit
= sub
.begin();
417 BOOST_CHECK_EQUAL("", iit
->first
);
418 BOOST_CHECK_EQUAL("1", iit
->second
.data());
420 BOOST_CHECK_EQUAL("", iit
->first
);
421 BOOST_CHECK_EQUAL("2", iit
->second
.data());
423 BOOST_CHECK_EQUAL(sub
.end(), iit
);
426 BOOST_CHECK_EQUAL("", it
->first
);
427 BOOST_CHECK_EQUAL("3", it
->second
.data());
429 BOOST_CHECK_EQUAL("", it
->first
);
431 ptree
& sub
= it
->second
;
432 BOOST_CHECK_EQUAL("", sub
.data());
433 BOOST_REQUIRE_EQUAL(2u, sub
.size());
434 ptree::iterator iit
= sub
.begin();
435 BOOST_CHECK_EQUAL("", iit
->first
);
436 BOOST_CHECK_EQUAL("4", iit
->second
.data());
438 BOOST_CHECK_EQUAL("", iit
->first
);
439 BOOST_CHECK_EQUAL("5", iit
->second
.data());
441 BOOST_CHECK_EQUAL(sub
.end(), iit
);
444 BOOST_CHECK_EQUAL(tree
.end(), it
);
447 BOOST_AUTO_TEST_CASE(empty_object
) {
449 standard_parser
<char> p
;
450 const char* input
= " { }";
451 BOOST_REQUIRE(p
.parse_object(input
, tree
));
452 BOOST_CHECK_EQUAL("", tree
.data());
453 BOOST_CHECK_EQUAL(0u, tree
.size());
456 BOOST_AUTO_TEST_CASE(object_gets_tagged
) {
458 prefixing_parser
<wchar_t> p
;
459 const wchar_t* input
= L
" { }";
460 BOOST_REQUIRE(p
.parse_object(input
, tree
));
461 BOOST_CHECK_EQUAL(L
"o:", tree
.data());
462 BOOST_CHECK_EQUAL(0u, tree
.size());
465 BOOST_AUTO_TEST_CASE(object_with_values
) {
467 standard_parser
<wchar_t> p
;
468 const wchar_t* input
= L
"{\n"
469 L
" \"1\":123, \"2\"\n"
470 L
" :\"abc\" ,\"3\": true ,\n"
473 BOOST_REQUIRE(p
.parse_object(input
, tree
));
474 BOOST_REQUIRE_EQUAL(4u, tree
.size());
475 wptree::iterator it
= tree
.begin();
476 BOOST_CHECK_EQUAL(L
"1", it
->first
);
477 BOOST_CHECK_EQUAL(L
"123", it
->second
.data());
479 BOOST_CHECK_EQUAL(L
"2", it
->first
);
480 BOOST_CHECK_EQUAL(L
"abc", it
->second
.data());
482 BOOST_CHECK_EQUAL(L
"3", it
->first
);
483 BOOST_CHECK_EQUAL(L
"true", it
->second
.data());
485 BOOST_CHECK_EQUAL(L
"4", it
->first
);
486 BOOST_CHECK_EQUAL(L
"null", it
->second
.data());
488 BOOST_CHECK_EQUAL(tree
.end(), it
);
491 BOOST_AUTO_TEST_CASE(object_values_get_tagged
) {
493 prefixing_parser
<char> p
;
494 const char* input
= "{\n"
495 "\"1\": 123, \"2\": \"abc\" ,\"3\": true ,\n"
498 BOOST_REQUIRE(p
.parse_object(input
, tree
));
499 BOOST_REQUIRE_EQUAL(4u, tree
.size());
500 BOOST_CHECK_EQUAL("o:", tree
.data());
501 ptree::iterator it
= tree
.begin();
502 BOOST_CHECK_EQUAL("1", it
->first
);
503 BOOST_CHECK_EQUAL("n:123", it
->second
.data());
505 BOOST_CHECK_EQUAL("2", it
->first
);
506 BOOST_CHECK_EQUAL("s:abc", it
->second
.data());
508 BOOST_CHECK_EQUAL("3", it
->first
);
509 BOOST_CHECK_EQUAL("b:true", it
->second
.data());
511 BOOST_CHECK_EQUAL("4", it
->first
);
512 BOOST_CHECK_EQUAL("_:null", it
->second
.data());
514 BOOST_CHECK_EQUAL(tree
.end(), it
);
517 BOOST_AUTO_TEST_CASE(nested_object
) {
519 standard_parser
<char> p
;
520 const char* input
= "{\"a\":{\"b\":1,\"c\":2},\"d\":3,\"e\":{\"f\":4,\"g\":5}}";
521 BOOST_REQUIRE(p
.parse_object(input
, tree
));
522 BOOST_REQUIRE_EQUAL(3u, tree
.size());
523 ptree::iterator it
= tree
.begin();
524 BOOST_CHECK_EQUAL("a", it
->first
);
526 ptree
& sub
= it
->second
;
527 BOOST_CHECK_EQUAL("", sub
.data());
528 BOOST_REQUIRE_EQUAL(2u, sub
.size());
529 ptree::iterator iit
= sub
.begin();
530 BOOST_CHECK_EQUAL("b", iit
->first
);
531 BOOST_CHECK_EQUAL("1", iit
->second
.data());
533 BOOST_CHECK_EQUAL("c", iit
->first
);
534 BOOST_CHECK_EQUAL("2", iit
->second
.data());
536 BOOST_CHECK_EQUAL(sub
.end(), iit
);
539 BOOST_CHECK_EQUAL("d", it
->first
);
540 BOOST_CHECK_EQUAL("3", it
->second
.data());
542 BOOST_CHECK_EQUAL("e", it
->first
);
544 ptree
& sub
= it
->second
;
545 BOOST_CHECK_EQUAL("", sub
.data());
546 BOOST_REQUIRE_EQUAL(2u, sub
.size());
547 ptree::iterator iit
= sub
.begin();
548 BOOST_CHECK_EQUAL("f", iit
->first
);
549 BOOST_CHECK_EQUAL("4", iit
->second
.data());
551 BOOST_CHECK_EQUAL("g", iit
->first
);
552 BOOST_CHECK_EQUAL("5", iit
->second
.data());
554 BOOST_CHECK_EQUAL(sub
.end(), iit
);
557 BOOST_CHECK_EQUAL(tree
.end(), it
);
560 BOOST_AUTO_TEST_CASE(array_in_object
) {
562 standard_parser
<char> p
;
563 const char* input
= "{\"a\":[1,2],\"b\":3,\"c\":[4,5]}";
564 BOOST_REQUIRE(p
.parse_object(input
, tree
));
565 BOOST_REQUIRE_EQUAL(3u, tree
.size());
566 ptree::iterator it
= tree
.begin();
567 BOOST_CHECK_EQUAL("a", it
->first
);
569 ptree
& sub
= it
->second
;
570 BOOST_CHECK_EQUAL("", sub
.data());
571 BOOST_REQUIRE_EQUAL(2u, sub
.size());
572 ptree::iterator iit
= sub
.begin();
573 BOOST_CHECK_EQUAL("", iit
->first
);
574 BOOST_CHECK_EQUAL("1", iit
->second
.data());
576 BOOST_CHECK_EQUAL("", iit
->first
);
577 BOOST_CHECK_EQUAL("2", iit
->second
.data());
579 BOOST_CHECK_EQUAL(sub
.end(), iit
);
582 BOOST_CHECK_EQUAL("b", it
->first
);
583 BOOST_CHECK_EQUAL("3", it
->second
.data());
585 BOOST_CHECK_EQUAL("c", it
->first
);
587 ptree
& sub
= it
->second
;
588 BOOST_CHECK_EQUAL("", sub
.data());
589 BOOST_REQUIRE_EQUAL(2u, sub
.size());
590 ptree::iterator iit
= sub
.begin();
591 BOOST_CHECK_EQUAL("", iit
->first
);
592 BOOST_CHECK_EQUAL("4", iit
->second
.data());
594 BOOST_CHECK_EQUAL("", iit
->first
);
595 BOOST_CHECK_EQUAL("5", iit
->second
.data());
597 BOOST_CHECK_EQUAL(sub
.end(), iit
);
600 BOOST_CHECK_EQUAL(tree
.end(), it
);
603 BOOST_AUTO_TEST_CASE(object_in_array
) {
605 standard_parser
<char> p
;
606 const char* input
= "[{\"a\":1,\"b\":2},3,{\"c\":4,\"d\":5}]";
607 BOOST_REQUIRE(p
.parse_array(input
, tree
));
608 BOOST_REQUIRE_EQUAL(3u, tree
.size());
609 ptree::iterator it
= tree
.begin();
610 BOOST_CHECK_EQUAL("", it
->first
);
612 ptree
& sub
= it
->second
;
613 BOOST_CHECK_EQUAL("", sub
.data());
614 BOOST_REQUIRE_EQUAL(2u, sub
.size());
615 ptree::iterator iit
= sub
.begin();
616 BOOST_CHECK_EQUAL("a", iit
->first
);
617 BOOST_CHECK_EQUAL("1", iit
->second
.data());
619 BOOST_CHECK_EQUAL("b", iit
->first
);
620 BOOST_CHECK_EQUAL("2", iit
->second
.data());
622 BOOST_CHECK_EQUAL(sub
.end(), iit
);
625 BOOST_CHECK_EQUAL("", it
->first
);
626 BOOST_CHECK_EQUAL("3", it
->second
.data());
628 BOOST_CHECK_EQUAL("", it
->first
);
630 ptree
& sub
= it
->second
;
631 BOOST_CHECK_EQUAL("", sub
.data());
632 BOOST_REQUIRE_EQUAL(2u, sub
.size());
633 ptree::iterator iit
= sub
.begin();
634 BOOST_CHECK_EQUAL("c", iit
->first
);
635 BOOST_CHECK_EQUAL("4", iit
->second
.data());
637 BOOST_CHECK_EQUAL("d", iit
->first
);
638 BOOST_CHECK_EQUAL("5", iit
->second
.data());
640 BOOST_CHECK_EQUAL(sub
.end(), iit
);
643 BOOST_CHECK_EQUAL(tree
.end(), it
);
646 BOOST_AUTO_TEST_CASE(parser_works_with_input_iterators
) {
647 const char* input
= " {\n"
648 " \"1\":123, \"2\"\n"
649 " :\"abc\" ,\"3\": true ,\n"
650 " \"4\" : null, \"5\" : [ 1, 23\n"
654 std::istringstream
is(input
);
655 typedef std::istreambuf_iterator
<char> iterator
;
656 json_parser::detail::standard_callbacks
<ptree
> callbacks
;
657 json_parser::detail::utf8_utf8_encoding encoding
;
658 json_parser::detail::parser
<json_parser::detail::standard_callbacks
<ptree
>,
659 json_parser::detail::utf8_utf8_encoding
,
661 p(callbacks
, encoding
);
663 p
.set_input("", boost::make_iterator_range(iterator(is
), iterator()));
666 const ptree
& tree
= callbacks
.output();
667 BOOST_REQUIRE_EQUAL(5u, tree
.size());
668 ptree::const_iterator it
= tree
.begin();
669 BOOST_CHECK_EQUAL("1", it
->first
);
670 BOOST_CHECK_EQUAL("123", it
->second
.data());
672 BOOST_CHECK_EQUAL("2", it
->first
);
673 BOOST_CHECK_EQUAL("abc", it
->second
.data());
675 BOOST_CHECK_EQUAL("3", it
->first
);
676 BOOST_CHECK_EQUAL("true", it
->second
.data());
678 BOOST_CHECK_EQUAL("4", it
->first
);
679 BOOST_CHECK_EQUAL("null", it
->second
.data());
681 BOOST_CHECK_EQUAL("5", it
->first
);
683 const ptree
& sub
= it
->second
;
684 BOOST_CHECK_EQUAL("", sub
.data());
685 BOOST_REQUIRE_EQUAL(3u, sub
.size());
686 ptree::const_iterator iit
= sub
.begin();
687 BOOST_CHECK_EQUAL("", iit
->first
);
688 BOOST_CHECK_EQUAL("1", iit
->second
.data());
690 BOOST_CHECK_EQUAL("", iit
->first
);
691 BOOST_CHECK_EQUAL("23", iit
->second
.data());
693 BOOST_CHECK_EQUAL("", iit
->first
);
694 BOOST_CHECK_EQUAL("456", iit
->second
.data());
696 BOOST_CHECK_EQUAL(sub
.end(), iit
);
699 BOOST_CHECK_EQUAL(tree
.end(), it
);
704 const char* message_substring
;
707 void parse_error_thrown_with_message_n(bad_parse_n param
) {
709 standard_parser
<char> p
;
711 p
.parse_value(param
.json
, dummy
);
712 BOOST_FAIL("expected exception");
713 } catch (json_parser::json_parser_error
& e
) {
714 std::string message
= e
.message();
715 BOOST_CHECK_MESSAGE(message
.find(param
.message_substring
) !=
717 "bad error message on input '" << param
.json
718 << "', need: '" << param
.message_substring
719 << "' but found '" << message
<< "'");
723 const bad_parse_n errors_n
[] = {
724 {"", "expected value"},
725 {"(", "expected value"},
727 {"n", "expected 'null'"},
728 {"nu", "expected 'null'"},
729 {"nul", "expected 'null'"},
730 {"n ", "expected 'null'"},
731 {"nu ", "expected 'null'"},
732 {"nul ", "expected 'null'"},
733 {"nx", "expected 'null'"},
734 {"nux", "expected 'null'"},
735 {"nulx", "expected 'null'"},
737 {"t", "expected 'true'"},
738 {"tr", "expected 'true'"},
739 {"tu", "expected 'true'"},
740 {"t ", "expected 'true'"},
741 {"tr ", "expected 'true'"},
742 {"tru ", "expected 'true'"},
743 {"tx", "expected 'true'"},
744 {"trx", "expected 'true'"},
745 {"trux", "expected 'true'"},
747 {"f", "expected 'false'"},
748 {"fa", "expected 'false'"},
749 {"fal", "expected 'false'"},
750 {"fals", "expected 'false'"},
751 {"f ", "expected 'false'"},
752 {"fa ", "expected 'false'"},
753 {"fal ", "expected 'false'"},
754 {"fals ", "expected 'false'"},
755 {"fx", "expected 'false'"},
756 {"fax", "expected 'false'"},
757 {"falx", "expected 'false'"},
758 {"falsx", "expected 'false'"},
760 {"-", "expected digits"},
761 {"01", "garbage after data"},
762 {"0.", "need at least one digit after '.'"},
763 {"0e", "need at least one digit in exponent"},
764 {"0e-", "need at least one digit in exponent"},
766 {"\"", "unterminated string"},
767 {"\"asd", "unterminated string"},
768 {"\"\n\"", "invalid code sequence"}, // control character
769 {"\"\xff\"", "invalid code sequence"}, // bad lead byte
770 {"\"\x80\"", "invalid code sequence"}, // stray trail byte
771 {"\"\xc0", "invalid code sequence"}, // eos after lead byte
772 {"\"\xc0\"", "invalid code sequence"}, // bad trail byte
773 {"\"\xc0m\"", "invalid code sequence"}, // also bad trail byte
774 {"\"\\", "invalid escape sequence"},
775 {"\"\\p\"", "invalid escape sequence"},
776 {"\"\\u", "invalid escape sequence"},
777 {"\"\\u\"", "invalid escape sequence"},
778 {"\"\\ug\"", "invalid escape sequence"},
779 {"\"\\u1\"", "invalid escape sequence"},
780 {"\"\\u1g\"", "invalid escape sequence"},
781 {"\"\\u11\"", "invalid escape sequence"},
782 {"\"\\u11g\"", "invalid escape sequence"},
783 {"\"\\u111\"", "invalid escape sequence"},
784 {"\"\\u111g\"", "invalid escape sequence"},
785 {"\"\\ude00\"", "stray low surrogate"},
786 {"\"\\ud900", "stray high surrogate"},
787 {"\"\\ud900foo\"", "stray high surrogate"},
788 {"\"\\ud900\\", "expected codepoint reference"},
789 {"\"\\ud900\\n\"", "expected codepoint reference"},
790 {"\"\\ud900\\u1000\"", "expected low surrogate"},
792 {"[", "expected value"},
793 {"[1", "expected ']' or ','"},
794 {"[1,", "expected value"},
795 {"[1,]", "expected value"},
796 {"[1}", "expected ']' or ','"},
798 {"{", "expected key string"},
799 {"{1:2}", "expected key string"},
800 {"{\"\"", "expected ':'"},
801 {"{\"\"}", "expected ':'"},
802 {"{\"\":", "expected value"},
803 {"{\"\":}", "expected value"},
804 {"{\"\":0", "expected '}' or ','"},
805 {"{\"\":0]", "expected '}' or ','"},
806 {"{\"\":0,", "expected key string"},
807 {"{\"\":0,}", "expected key string"},
812 const char* message_substring
;
815 void parse_error_thrown_with_message_w(bad_parse_w param
) {
817 standard_parser
<wchar_t> p
;
819 p
.parse_value(param
.json
, dummy
);
820 BOOST_FAIL("expected exception");
821 } catch (json_parser::json_parser_error
& e
) {
822 std::string message
= e
.message();
823 BOOST_CHECK_MESSAGE(message
.find(param
.message_substring
) !=
825 "bad error message on input '" << param
.json
826 << "', need: '" << param
.message_substring
827 << "' but found '" << message
<< "'");
831 const bad_parse_w errors_w
[] = {
832 {L
"", "expected value"},
833 {L
"(", "expected value"},
835 {L
"n", "expected 'null'"},
836 {L
"nu", "expected 'null'"},
837 {L
"nul", "expected 'null'"},
838 {L
"n ", "expected 'null'"},
839 {L
"nu ", "expected 'null'"},
840 {L
"nul ", "expected 'null'"},
841 {L
"nx", "expected 'null'"},
842 {L
"nux", "expected 'null'"},
843 {L
"nulx", "expected 'null'"},
845 {L
"t", "expected 'true'"},
846 {L
"tr", "expected 'true'"},
847 {L
"tu", "expected 'true'"},
848 {L
"t ", "expected 'true'"},
849 {L
"tr ", "expected 'true'"},
850 {L
"tru ", "expected 'true'"},
851 {L
"tx", "expected 'true'"},
852 {L
"trx", "expected 'true'"},
853 {L
"trux", "expected 'true'"},
855 {L
"f", "expected 'false'"},
856 {L
"fa", "expected 'false'"},
857 {L
"fal", "expected 'false'"},
858 {L
"fals", "expected 'false'"},
859 {L
"f ", "expected 'false'"},
860 {L
"fa ", "expected 'false'"},
861 {L
"fal ", "expected 'false'"},
862 {L
"fals ", "expected 'false'"},
863 {L
"fx", "expected 'false'"},
864 {L
"fax", "expected 'false'"},
865 {L
"falx", "expected 'false'"},
866 {L
"falsx", "expected 'false'"},
868 {L
"-", "expected digits"},
869 {L
"01", "garbage after data"},
870 {L
"0.", "need at least one digit after '.'"},
871 {L
"0e", "need at least one digit in exponent"},
872 {L
"0e-", "need at least one digit in exponent"},
874 {L
"\"", "unterminated string"},
875 {L
"\"asd", "unterminated string"},
876 {L
"\"\n\"", "invalid code sequence"}, // control character
877 // Encoding not known, so no UTF-16 encoding error tests.
878 {L
"\"\\", "invalid escape sequence"},
879 {L
"\"\\p\"", "invalid escape sequence"},
880 {L
"\"\\u", "invalid escape sequence"},
881 {L
"\"\\u\"", "invalid escape sequence"},
882 {L
"\"\\ug\"", "invalid escape sequence"},
883 {L
"\"\\u1\"", "invalid escape sequence"},
884 {L
"\"\\u1g\"", "invalid escape sequence"},
885 {L
"\"\\u11\"", "invalid escape sequence"},
886 {L
"\"\\u11g\"", "invalid escape sequence"},
887 {L
"\"\\u111\"", "invalid escape sequence"},
888 {L
"\"\\u111g\"", "invalid escape sequence"},
889 {L
"\"\\ude00\"", "stray low surrogate"},
890 {L
"\"\\ud900", "stray high surrogate"},
891 {L
"\"\\ud900foo\"", "stray high surrogate"},
892 {L
"\"\\ud900\\", "expected codepoint reference"},
893 {L
"\"\\ud900\\n\"", "expected codepoint reference"},
894 {L
"\"\\ud900\\u1000\"", "expected low surrogate"},
896 {L
"[", "expected value"},
897 {L
"[1", "expected ']' or ','"},
898 {L
"[1,", "expected value"},
899 {L
"[1,]", "expected value"},
900 {L
"[1}", "expected ']' or ','"},
902 {L
"{", "expected key string"},
903 {L
"{1:2}", "expected key string"},
904 {L
"{\"\"", "expected ':'"},
905 {L
"{\"\"}", "expected ':'"},
906 {L
"{\"\":", "expected value"},
907 {L
"{\"\":}", "expected value"},
908 {L
"{\"\":0", "expected '}' or ','"},
909 {L
"{\"\":0]", "expected '}' or ','"},
910 {L
"{\"\":0,", "expected key string"},
911 {L
"{\"\":0,}", "expected key string"},
914 template <typename T
, std::size_t N
>
915 std::size_t arraysize(T(&)[N
]) { return N
; }
917 #define ARRAY_TEST_CASE(fn, a) \
918 BOOST_PARAM_TEST_CASE(fn, (a), (a) + arraysize((a)))
920 using namespace boost::unit_test
;
922 test_suite
* init_unit_test_suite(int, char*[])
924 master_test_suite_t
& ts
= boost::unit_test::framework::master_test_suite();
925 ts
.add(ARRAY_TEST_CASE(boolean_parse_result_is_input_n
, booleans_n
));
926 ts
.add(ARRAY_TEST_CASE(boolean_parse_result_is_input_w
, booleans_w
));
927 ts
.add(ARRAY_TEST_CASE(number_parse_result_is_input_n
, numbers_n
));
928 ts
.add(ARRAY_TEST_CASE(number_parse_result_is_input_w
, numbers_w
));
929 ts
.add(ARRAY_TEST_CASE(string_parsed_correctly_n
, strings_n
));
930 ts
.add(ARRAY_TEST_CASE(string_parsed_correctly_w
, strings_w
));
931 ts
.add(ARRAY_TEST_CASE(parse_error_thrown_with_message_n
, errors_n
));
932 ts
.add(ARRAY_TEST_CASE(parse_error_thrown_with_message_w
, errors_w
));