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 
17 using namespace boost::property_tree;
18 
19 template <typename Ch> struct encoding;
20 template <> struct encoding<char>
21     : json_parser::detail::utf8_utf8_encoding
22 {};
23 template <> struct encoding<wchar_t>
24     : json_parser::detail::wide_wide_encoding
25 {};
26 
27 template <typename Callbacks, typename Ch>
28 struct 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 
test_parsertest_parser39     test_parser() : parser(callbacks, encoding) {}
40 
parse_nulltest_parser41     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 
parse_booleantest_parser51     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 
parse_numbertest_parser61     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 
parse_stringtest_parser71     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 
parse_arraytest_parser81     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 
parse_objecttest_parser91     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 
parse_valuetest_parser101     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 
109 template <typename Ch>
110 struct 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 
117 template <typename Ch>
118 struct 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 
128 static void
test_null_parse_result_is_input()129 test_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 
137 static void
test_uses_traits_from_null()138 test_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 
146 static void
test_null_parse_skips_bom()147 test_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 
155 static void
test_null_parse_result_is_input_w()156 test_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 
164 static void
test_uses_traits_from_null_w()165 test_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 
173 static void
test_null_parse_skips_bom_w()174 test_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 
182 template<std::size_t N>
183 static void
test_boolean_parse_result_is_input_n(const std::string (& param)[N])184 test_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 
195 const std::string
196 booleans_n[] = { "true", "false" };
197 
198 static void
test_uses_traits_from_boolean_n()199 test_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 
207 template<std::size_t N>
208 static void
test_boolean_parse_result_is_input_w(const std::wstring (& param)[N])209 test_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 
220 const std::wstring
221 booleans_w[] = { L"true", L"false" };
222 
223 static void
test_uses_traits_from_boolean_w()224 test_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 
232 template<std::size_t N>
233 static void
test_number_parse_result_is_input_n(std::string const (& param)[N])234 test_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 
245 std::string const
246 numbers_n[] = {
247     "0",
248     "-0",
249     "1824",
250     "-0.1",
251     "123.142",
252     "1e+0",
253     "1E-0",
254     "1.1e134"
255 };
256 
257 static void
test_uses_traits_from_number_n()258 test_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 
266 template<std::size_t N>
267 static void
test_number_parse_result_is_input_w(const std::wstring (& param)[N])268 test_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 
279 std::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 
290 static void
test_uses_traits_from_number_w()291 test_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 
299 struct string_input_n {
300     const char* encoded;
301     const char* expected;
302 };
303 
304 template<std::size_t N>
test_string_parsed_correctly_n(string_input_n const (& param)[N])305 void 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 
316 const string_input_n strings_n[] = {
317     {"\"\"", ""},
318     {"\"abc\"", "abc"},
319     {"\"a\\nb\"", "a\nb"},
320     {"\"\\\"\"", "\""},
321     {"\"\\\\\"", "\\"},
322     {"\"\\/\"", "/"},
323     {"\"\\b\"", "\b"},
324     {"\"\\f\"", "\f"},
325     {"\"\\r\"", "\r"},
326     {"\"\\t\"", "\t"},
327     {"\"\\u0001\\u00f2\\u28Ec\"", "\x01" "\xC3\xB2" "\xE2\xA3\xAC"},
328     {"\"\\ud801\\udc37\"", "\xf0\x90\x90\xb7"}, // U+10437
329     {"\xef\xbb\xbf\"\"", ""} // BOM
330 };
331 
332 static void
test_uses_string_callbacks()333 test_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 
341 struct string_input_w {
342     const wchar_t* encoded;
343     const wchar_t* expected;
344 };
345 
346 template<std::size_t N>
347 void
test_string_parsed_correctly_w(string_input_w const (& param)[N])348 test_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 
359 const string_input_w strings_w[] = {
360     {L"\"\"", L""},
361     {L"\"abc\"", L"abc"},
362     {L"\"a\\nb\"", L"a\nb"},
363     {L"\"\\\"\"", L"\""},
364     {L"\"\\\\\"", L"\\"},
365     {L"\"\\/\"", L"/"},
366     {L"\"\\b\"", L"\b"},
367     {L"\"\\f\"", L"\f"},
368     {L"\"\\r\"", L"\r"},
369     {L"\"\\t\"", L"\t"},
370     {L"\"\\u0001\\u00f2\\u28Ec\"", L"\x0001" L"\x00F2" L"\x28EC"},
371     {L"\xfeff\"\"", L""} // BOM
372 };
373 
374 static void
test_empty_array()375 test_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 
385 static void
test_array_gets_tagged()386 test_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 
396 static void
test_array_with_values()397 test_array_with_values()
398 {
399     wptree tree;
400     standard_parser<wchar_t> p;
401     const wchar_t* input = L"[\n"
402 L"      123, \"abc\" ,true ,\n"
403 L"      null\n"
404 L"  ]";
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 
425 static void
test_array_values_get_tagged()426 test_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 
455 static void
test_nested_array()456 test_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 
504 static void
test_empty_object()505 test_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 
517 static void
test_object_gets_tagged()518 test_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 
530 static void
test_object_with_values()531 test_object_with_values()
532 {
533     wptree tree;
534     standard_parser<wchar_t> p;
535     const wchar_t* input = L"{\n"
536 L"      \"1\":123, \"2\"\n"
537 L"            :\"abc\" ,\"3\": true ,\n"
538 L"      \"4\"   : null\n"
539 L"  }";
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 
560 static void
test_object_values_get_tagged()561 test_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 
590 static void
test_nested_object()591 test_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 
639 static void
test_array_in_object()640 test_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 
690 static void
test_object_in_array()691 test_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 
741 static void
test_parser_works_with_input_iterators()742 test_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("", boost::make_iterator_range(iterator(is), 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 
801 struct bad_parse_n {
802     const char* json;
803     const char* message_substring;
804 };
805 
806 template<std::size_t N>
test_parse_error_thrown_with_message_n(bad_parse_n const (& param)[N])807 void 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(param[i].json, 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 
831 const bad_parse_n errors_n[] = {
832     {"", "expected value"},
833     {"(", "expected value"},
834 
835     {"n", "expected 'null'"},
836     {"nu", "expected 'null'"},
837     {"nul", "expected 'null'"},
838     {"n ", "expected 'null'"},
839     {"nu ", "expected 'null'"},
840     {"nul ", "expected 'null'"},
841     {"nx", "expected 'null'"},
842     {"nux", "expected 'null'"},
843     {"nulx", "expected 'null'"},
844 
845     {"t", "expected 'true'"},
846     {"tr", "expected 'true'"},
847     {"tu", "expected 'true'"},
848     {"t ", "expected 'true'"},
849     {"tr ", "expected 'true'"},
850     {"tru ", "expected 'true'"},
851     {"tx", "expected 'true'"},
852     {"trx", "expected 'true'"},
853     {"trux", "expected 'true'"},
854 
855     {"f", "expected 'false'"},
856     {"fa", "expected 'false'"},
857     {"fal", "expected 'false'"},
858     {"fals", "expected 'false'"},
859     {"f ", "expected 'false'"},
860     {"fa ", "expected 'false'"},
861     {"fal ", "expected 'false'"},
862     {"fals ", "expected 'false'"},
863     {"fx", "expected 'false'"},
864     {"fax", "expected 'false'"},
865     {"falx", "expected 'false'"},
866     {"falsx", "expected 'false'"},
867 
868     {"-", "expected digits"},
869     {"01", "garbage after data"},
870     {"0.", "need at least one digit after '.'"},
871     {"0e", "need at least one digit in exponent"},
872     {"0e-", "need at least one digit in exponent"},
873 
874     {"\"", "unterminated string"},
875     {"\"asd", "unterminated string"},
876     {"\"\n\"", "invalid code sequence"}, // control character
877     {"\"\xff\"", "invalid code sequence"}, // bad lead byte
878     {"\"\x80\"", "invalid code sequence"}, // stray trail byte
879     {"\"\xc0", "invalid code sequence"}, // eos after lead byte
880     {"\"\xc0\"", "invalid code sequence"}, // bad trail byte
881     {"\"\xc0m\"", "invalid code sequence"}, // also bad trail byte
882     {"\"\\", "invalid escape sequence"},
883     {"\"\\p\"", "invalid escape sequence"},
884     {"\"\\u", "invalid escape sequence"},
885     {"\"\\u\"", "invalid escape sequence"},
886     {"\"\\ug\"", "invalid escape sequence"},
887     {"\"\\u1\"", "invalid escape sequence"},
888     {"\"\\u1g\"", "invalid escape sequence"},
889     {"\"\\u11\"", "invalid escape sequence"},
890     {"\"\\u11g\"", "invalid escape sequence"},
891     {"\"\\u111\"", "invalid escape sequence"},
892     {"\"\\u111g\"", "invalid escape sequence"},
893     {"\"\\ude00\"", "stray low surrogate"},
894     {"\"\\ud900", "stray high surrogate"},
895     {"\"\\ud900foo\"", "stray high surrogate"},
896     {"\"\\ud900\\", "expected codepoint reference"},
897     {"\"\\ud900\\n\"", "expected codepoint reference"},
898     {"\"\\ud900\\u1000\"", "expected low surrogate"},
899 
900     {"[", "expected value"},
901     {"[1", "expected ']' or ','"},
902     {"[1,", "expected value"},
903     {"[1,]", "expected value"},
904     {"[1}", "expected ']' or ','"},
905 
906     {"{", "expected key string"},
907     {"{1:2}", "expected key string"},
908     {"{\"\"", "expected ':'"},
909     {"{\"\"}", "expected ':'"},
910     {"{\"\":", "expected value"},
911     {"{\"\":}", "expected value"},
912     {"{\"\":0", "expected '}' or ','"},
913     {"{\"\":0]", "expected '}' or ','"},
914     {"{\"\":0,", "expected key string"},
915     {"{\"\":0,}", "expected key string"},
916 };
917 
918 struct bad_parse_w {
919     const wchar_t* json;
920     const char* message_substring;
921 };
922 
923 struct do_narrow
924 {
operator ()do_narrow925     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 };
934 static std::string
make_narrow(std::wstring const & in)935 make_narrow(std::wstring const& in)
936 {
937     std::string result(in.size(), ' ');
938     std::transform(in.begin(), in.end(), result.begin(), do_narrow());
939     return result;
940 }
941 
942 template<std::size_t N>
943 void
test_parse_error_thrown_with_message_w(bad_parse_w const (& param)[N])944 test_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(param[i].json, 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 
968 const bad_parse_w
969 errors_w[] = {
970     {L"", "expected value"},
971     {L"(", "expected value"},
972 
973     {L"n", "expected 'null'"},
974     {L"nu", "expected 'null'"},
975     {L"nul", "expected 'null'"},
976     {L"n ", "expected 'null'"},
977     {L"nu ", "expected 'null'"},
978     {L"nul ", "expected 'null'"},
979     {L"nx", "expected 'null'"},
980     {L"nux", "expected 'null'"},
981     {L"nulx", "expected 'null'"},
982 
983     {L"t", "expected 'true'"},
984     {L"tr", "expected 'true'"},
985     {L"tu", "expected 'true'"},
986     {L"t ", "expected 'true'"},
987     {L"tr ", "expected 'true'"},
988     {L"tru ", "expected 'true'"},
989     {L"tx", "expected 'true'"},
990     {L"trx", "expected 'true'"},
991     {L"trux", "expected 'true'"},
992 
993     {L"f", "expected 'false'"},
994     {L"fa", "expected 'false'"},
995     {L"fal", "expected 'false'"},
996     {L"fals", "expected 'false'"},
997     {L"f ", "expected 'false'"},
998     {L"fa ", "expected 'false'"},
999     {L"fal ", "expected 'false'"},
1000     {L"fals ", "expected 'false'"},
1001     {L"fx", "expected 'false'"},
1002     {L"fax", "expected 'false'"},
1003     {L"falx", "expected 'false'"},
1004     {L"falsx", "expected 'false'"},
1005 
1006     {L"-", "expected digits"},
1007     {L"01", "garbage after data"},
1008     {L"0.", "need at least one digit after '.'"},
1009     {L"0e", "need at least one digit in exponent"},
1010     {L"0e-", "need at least one digit in exponent"},
1011 
1012     {L"\"", "unterminated string"},
1013     {L"\"asd", "unterminated string"},
1014     {L"\"\n\"", "invalid code sequence"}, // control character
1015     // Encoding not known, so no UTF-16 encoding error tests.
1016     {L"\"\\", "invalid escape sequence"},
1017     {L"\"\\p\"", "invalid escape sequence"},
1018     {L"\"\\u", "invalid escape sequence"},
1019     {L"\"\\u\"", "invalid escape sequence"},
1020     {L"\"\\ug\"", "invalid escape sequence"},
1021     {L"\"\\u1\"", "invalid escape sequence"},
1022     {L"\"\\u1g\"", "invalid escape sequence"},
1023     {L"\"\\u11\"", "invalid escape sequence"},
1024     {L"\"\\u11g\"", "invalid escape sequence"},
1025     {L"\"\\u111\"", "invalid escape sequence"},
1026     {L"\"\\u111g\"", "invalid escape sequence"},
1027     {L"\"\\ude00\"", "stray low surrogate"},
1028     {L"\"\\ud900", "stray high surrogate"},
1029     {L"\"\\ud900foo\"", "stray high surrogate"},
1030     {L"\"\\ud900\\", "expected codepoint reference"},
1031     {L"\"\\ud900\\n\"", "expected codepoint reference"},
1032     {L"\"\\ud900\\u1000\"", "expected low surrogate"},
1033 
1034     {L"[", "expected value"},
1035     {L"[1", "expected ']' or ','"},
1036     {L"[1,", "expected value"},
1037     {L"[1,]", "expected value"},
1038     {L"[1}", "expected ']' or ','"},
1039 
1040     {L"{", "expected key string"},
1041     {L"{1:2}", "expected key string"},
1042     {L"{\"\"", "expected ':'"},
1043     {L"{\"\"}", "expected ':'"},
1044     {L"{\"\":", "expected value"},
1045     {L"{\"\":}", "expected value"},
1046     {L"{\"\":0", "expected '}' or ','"},
1047     {L"{\"\":0]", "expected '}' or ','"},
1048     {L"{\"\":0,", "expected key string"},
1049     {L"{\"\":0,}", "expected key string"},
1050 };
1051 
main()1052 int 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(booleans_n);
1062     test_boolean_parse_result_is_input_w(booleans_w);
1063     test_number_parse_result_is_input_n(numbers_n);
1064     test_number_parse_result_is_input_w(numbers_w);
1065     test_uses_traits_from_number_n();
1066     test_string_parsed_correctly_n(strings_n);
1067     test_string_parsed_correctly_w(strings_w);
1068     test_parse_error_thrown_with_message_n(errors_n);
1069     test_parse_error_thrown_with_message_w(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 /*
1090 test_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 */