1 #include <boost/property_tree/detail/json_parser/parser.hpp>
2 #include <boost/property_tree/detail/json_parser/narrow_encoding.hpp>
3 #include <boost/property_tree/detail/json_parser/wide_encoding.hpp>
4 #include <boost/property_tree/detail/json_parser/standard_callbacks.hpp>
5 #include "prefixing_callbacks.hpp"
6 
7 #define BOOST_TEST_NO_MAIN
8 #include <boost/test/unit_test.hpp>
9 #include <boost/test/parameterized_test.hpp>
10 
11 #include <boost/property_tree/ptree.hpp>
12 #include <boost/range/iterator_range.hpp>
13 
14 #include <cassert>
15 #include <sstream>
16 #include <vector>
17 
18 using namespace boost::property_tree;
19 
20 template <typename Ch> struct encoding;
21 template <> struct encoding<char>
22     : json_parser::detail::utf8_utf8_encoding
23 {};
24 template <> struct encoding<wchar_t>
25     : json_parser::detail::wide_wide_encoding
26 {};
27 
28 template <typename Callbacks, typename Ch>
29 struct test_parser
30 {
31     Callbacks callbacks;
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>
38         parser;
39 
test_parsertest_parser40     test_parser() : parser(callbacks, encoding) {}
41 
parse_nulltest_parser42     bool parse_null(const string& input, string& output) {
43         parser.set_input("", input);
44         bool result = parser.parse_null();
45         if (result) {
46             parser.finish();
47             output = callbacks.output().data();
48         }
49         return result;
50     }
51 
parse_booleantest_parser52     bool parse_boolean(const string& input, string& output) {
53         parser.set_input("", input);
54         bool result = parser.parse_boolean();
55         if (result) {
56             parser.finish();
57             output = callbacks.output().data();
58         }
59         return result;
60     }
61 
parse_numbertest_parser62     bool parse_number(const string& input, string& output) {
63         parser.set_input("", input);
64         bool result = parser.parse_number();
65         if (result) {
66             parser.finish();
67             output = callbacks.output().data();
68         }
69         return result;
70     }
71 
parse_stringtest_parser72     bool parse_string(const string& input, string& output) {
73         parser.set_input("", input);
74         bool result = parser.parse_string();
75         if (result) {
76             parser.finish();
77             output = callbacks.output().data();
78         }
79         return result;
80     }
81 
parse_arraytest_parser82     bool parse_array(const string& input, tree& output) {
83         parser.set_input("", input);
84         bool result = parser.parse_array();
85         if (result) {
86             parser.finish();
87             output = callbacks.output();
88         }
89         return result;
90     }
91 
parse_objecttest_parser92     bool parse_object(const string& input, tree& output) {
93         parser.set_input("", input);
94         bool result = parser.parse_object();
95         if (result) {
96             parser.finish();
97             output = callbacks.output();
98         }
99         return result;
100     }
101 
parse_valuetest_parser102     void parse_value(const string& input, tree& output) {
103         parser.set_input("", input);
104         parser.parse_value();
105         parser.finish();
106         output = callbacks.output();
107     }
108 };
109 
110 template <typename Ch>
111 struct standard_parser
112     : test_parser<
113         json_parser::detail::standard_callbacks<
114             basic_ptree<std::basic_string<Ch>, std::basic_string<Ch> > >,
115         Ch>
116 {};
117 
118 template <typename Ch>
119 struct prefixing_parser
120     : test_parser<
121         prefixing_callbacks<
122             basic_ptree<std::basic_string<Ch>, std::basic_string<Ch> > >,
123         Ch>
124 {};
125 
126 namespace boost { namespace test_tools { namespace tt_detail {
127     template<>
128     struct print_log_value<std::wstring> {
operator ()boost::test_tools::tt_detail::print_log_value129         void operator()(std::ostream& os, const std::wstring& s) {
130             print_log_value<const wchar_t*>()(os, s.c_str());
131         }
132     };
133 }}}
134 BOOST_TEST_DONT_PRINT_LOG_VALUE(ptree::iterator)
BOOST_TEST_DONT_PRINT_LOG_VALUE(ptree::const_iterator)135 BOOST_TEST_DONT_PRINT_LOG_VALUE(ptree::const_iterator)
136 BOOST_TEST_DONT_PRINT_LOG_VALUE(wptree::iterator)
137 BOOST_TEST_DONT_PRINT_LOG_VALUE(wptree::const_iterator)
138 
139 BOOST_AUTO_TEST_CASE(null_parse_result_is_input) {
140     std::string parsed;
141     standard_parser<char> p;
142     BOOST_REQUIRE(p.parse_null("null", parsed));
143     BOOST_CHECK_EQUAL("null", parsed);
144 }
145 
BOOST_AUTO_TEST_CASE(uses_traits_from_null)146 BOOST_AUTO_TEST_CASE(uses_traits_from_null)
147 {
148     std::string parsed;
149     prefixing_parser<char> p;
150     BOOST_REQUIRE(p.parse_null("null", parsed));
151     BOOST_CHECK_EQUAL("_:null", parsed);
152 }
153 
BOOST_AUTO_TEST_CASE(null_parse_result_is_input_w)154 BOOST_AUTO_TEST_CASE(null_parse_result_is_input_w) {
155     std::wstring parsed;
156     standard_parser<wchar_t> p;
157     BOOST_REQUIRE(p.parse_null(L"null", parsed));
158     BOOST_CHECK_EQUAL(L"null", parsed);
159 }
160 
BOOST_AUTO_TEST_CASE(uses_traits_from_null_w)161 BOOST_AUTO_TEST_CASE(uses_traits_from_null_w)
162 {
163     std::wstring parsed;
164     prefixing_parser<wchar_t> p;
165     BOOST_REQUIRE(p.parse_null(L"null", parsed));
166     BOOST_CHECK_EQUAL(L"_:null", parsed);
167 }
168 
boolean_parse_result_is_input_n(const char * param)169 void boolean_parse_result_is_input_n(const char* param) {
170     std::string parsed;
171     standard_parser<char> p;
172     BOOST_REQUIRE(p.parse_boolean(param, parsed));
173     BOOST_CHECK_EQUAL(param, parsed);
174 }
175 
176 const char* const booleans_n[] = { "true", "false" };
177 
BOOST_AUTO_TEST_CASE(uses_traits_from_boolean_n)178 BOOST_AUTO_TEST_CASE(uses_traits_from_boolean_n)
179 {
180     std::string parsed;
181     prefixing_parser<char> p;
182     BOOST_REQUIRE(p.parse_boolean("true", parsed));
183     BOOST_CHECK_EQUAL("b:true", parsed);
184 }
185 
boolean_parse_result_is_input_w(const wchar_t * param)186 void boolean_parse_result_is_input_w(const wchar_t* param) {
187     std::wstring parsed;
188     standard_parser<wchar_t> p;
189     BOOST_REQUIRE(p.parse_boolean(param, parsed));
190     BOOST_CHECK_EQUAL(param, parsed);
191 }
192 
193 const wchar_t* const booleans_w[] = { L"true", L"false" };
194 
BOOST_AUTO_TEST_CASE(uses_traits_from_boolean_w)195 BOOST_AUTO_TEST_CASE(uses_traits_from_boolean_w)
196 {
197     std::wstring parsed;
198     prefixing_parser<wchar_t> p;
199     BOOST_REQUIRE(p.parse_boolean(L"true", parsed));
200     BOOST_CHECK_EQUAL(L"b:true", parsed);
201 }
202 
number_parse_result_is_input_n(const char * param)203 void number_parse_result_is_input_n(const char* param) {
204     std::string parsed;
205     standard_parser<char> p;
206     BOOST_REQUIRE(p.parse_number(param, parsed));
207     BOOST_CHECK_EQUAL(param, parsed);
208 }
209 
210 const char* const numbers_n[] = { "0", "-0", "1824", "-0.1", "123.142", "1e+0", "1E-0", "1.1e134" };
211 
BOOST_AUTO_TEST_CASE(uses_traits_from_number_n)212 BOOST_AUTO_TEST_CASE(uses_traits_from_number_n)
213 {
214     std::string parsed;
215     prefixing_parser<char> p;
216     BOOST_REQUIRE(p.parse_number("12345", parsed));
217     BOOST_CHECK_EQUAL("n:12345", parsed);
218 }
219 
number_parse_result_is_input_w(const wchar_t * param)220 void number_parse_result_is_input_w(const wchar_t* param) {
221     std::wstring parsed;
222     standard_parser<wchar_t> p;
223     BOOST_REQUIRE(p.parse_number(param, parsed));
224     BOOST_CHECK_EQUAL(param, parsed);
225 }
226 
227 const wchar_t* const numbers_w[] = { L"0", L"-0", L"1824", L"-0.1", L"123.142", L"1e+0", L"1E-0", L"1.1e134" };
228 
BOOST_AUTO_TEST_CASE(uses_traits_from_number_w)229 BOOST_AUTO_TEST_CASE(uses_traits_from_number_w)
230 {
231     std::wstring parsed;
232     prefixing_parser<wchar_t> p;
233     BOOST_REQUIRE(p.parse_number(L"12345", parsed));
234     BOOST_CHECK_EQUAL(L"n:12345", parsed);
235 }
236 
237 struct string_input_n {
238     const char* encoded;
239     const char* expected;
240 };
241 
string_parsed_correctly_n(string_input_n param)242 void string_parsed_correctly_n(string_input_n param) {
243     std::string parsed;
244     standard_parser<char> p;
245     BOOST_REQUIRE(p.parse_string(param.encoded, parsed));
246     BOOST_CHECK_EQUAL(param.expected, parsed);
247 }
248 
249 const string_input_n strings_n[] = {
250     {"\"\"", ""},
251     {"\"abc\"", "abc"},
252     {"\"a\\nb\"", "a\nb"},
253     {"\"\\\"\"", "\""},
254     {"\"\\\\\"", "\\"},
255     {"\"\\/\"", "/"},
256     {"\"\\b\"", "\b"},
257     {"\"\\f\"", "\f"},
258     {"\"\\r\"", "\r"},
259     {"\"\\t\"", "\t"},
260     {"\"\\u0001\\u00f2\\u28Ec\"", "\x01" "\xC3\xB2" "\xE2\xA3\xAC"},
261     {"\"\\ud801\\udc37\"", "\xf0\x90\x90\xb7"} // U+10437
262 };
263 
BOOST_AUTO_TEST_CASE(uses_string_callbacks)264 BOOST_AUTO_TEST_CASE(uses_string_callbacks)
265 {
266     std::string parsed;
267     prefixing_parser<char> p;
268     BOOST_REQUIRE(p.parse_string("\"a\"", parsed));
269     BOOST_CHECK_EQUAL("s:a", parsed);
270 }
271 
272 struct string_input_w {
273     const wchar_t* encoded;
274     const wchar_t* expected;
275 };
276 
string_parsed_correctly_w(string_input_w param)277 void string_parsed_correctly_w(string_input_w param) {
278     std::wstring parsed;
279     standard_parser<wchar_t> p;
280     BOOST_REQUIRE(p.parse_string(param.encoded, parsed));
281     BOOST_CHECK_EQUAL(param.expected, parsed);
282 }
283 
284 const string_input_w strings_w[] = {
285     {L"\"\"", L""},
286     {L"\"abc\"", L"abc"},
287     {L"\"a\\nb\"", L"a\nb"},
288     {L"\"\\\"\"", L"\""},
289     {L"\"\\\\\"", L"\\"},
290     {L"\"\\/\"", L"/"},
291     {L"\"\\b\"", L"\b"},
292     {L"\"\\f\"", L"\f"},
293     {L"\"\\r\"", L"\r"},
294     {L"\"\\t\"", L"\t"},
295     {L"\"\\u0001\\u00f2\\u28Ec\"", L"\x0001" L"\x00F2" L"\x28EC"}
296 };
297 
BOOST_AUTO_TEST_CASE(empty_array)298 BOOST_AUTO_TEST_CASE(empty_array) {
299     ptree tree;
300     standard_parser<char> p;
301     const char* input = " [ ]";
302     BOOST_REQUIRE(p.parse_array(input, tree));
303     BOOST_CHECK_EQUAL("", tree.data());
304     BOOST_CHECK_EQUAL(0u, tree.size());
305 }
306 
BOOST_AUTO_TEST_CASE(array_gets_tagged)307 BOOST_AUTO_TEST_CASE(array_gets_tagged) {
308     wptree tree;
309     prefixing_parser<wchar_t> p;
310     const wchar_t* input = L" [ ]";
311     BOOST_REQUIRE(p.parse_array(input, tree));
312     BOOST_CHECK_EQUAL(L"a:", tree.data());
313     BOOST_CHECK_EQUAL(0u, tree.size());
314 }
315 
BOOST_AUTO_TEST_CASE(array_with_values)316 BOOST_AUTO_TEST_CASE(array_with_values) {
317     wptree tree;
318     standard_parser<wchar_t> p;
319     const wchar_t* input = L"[\n"
320 L"      123, \"abc\" ,true ,\n"
321 L"      null\n"
322 L"  ]";
323     BOOST_REQUIRE(p.parse_array(input, tree));
324     BOOST_REQUIRE_EQUAL(4u, tree.size());
325     wptree::iterator it = tree.begin();
326     BOOST_CHECK_EQUAL(L"", it->first);
327     BOOST_CHECK_EQUAL(L"123", it->second.data());
328     ++it;
329     BOOST_CHECK_EQUAL(L"", it->first);
330     BOOST_CHECK_EQUAL(L"abc", it->second.data());
331     ++it;
332     BOOST_CHECK_EQUAL(L"", it->first);
333     BOOST_CHECK_EQUAL(L"true", it->second.data());
334     ++it;
335     BOOST_CHECK_EQUAL(L"", it->first);
336     BOOST_CHECK_EQUAL(L"null", it->second.data());
337     ++it;
338     BOOST_CHECK_EQUAL(tree.end(), it);
339 }
340 
BOOST_AUTO_TEST_CASE(array_values_get_tagged)341 BOOST_AUTO_TEST_CASE(array_values_get_tagged) {
342     ptree tree;
343     prefixing_parser<char> p;
344     const char* input = "[\n"
345 "       123, \"abc\" ,true ,\n"
346 "       null\n"
347 "   ]";
348     BOOST_REQUIRE(p.parse_array(input, tree));
349     BOOST_REQUIRE_EQUAL(4u, tree.size());
350     BOOST_CHECK_EQUAL("a:", tree.data());
351     ptree::iterator it = tree.begin();
352     BOOST_CHECK_EQUAL("", it->first);
353     BOOST_CHECK_EQUAL("n:123", it->second.data());
354     ++it;
355     BOOST_CHECK_EQUAL("", it->first);
356     BOOST_CHECK_EQUAL("s:abc", it->second.data());
357     ++it;
358     BOOST_CHECK_EQUAL("", it->first);
359     BOOST_CHECK_EQUAL("b:true", it->second.data());
360     ++it;
361     BOOST_CHECK_EQUAL("", it->first);
362     BOOST_CHECK_EQUAL("_:null", it->second.data());
363     ++it;
364     BOOST_CHECK_EQUAL(tree.end(), it);
365 }
366 
BOOST_AUTO_TEST_CASE(nested_array)367 BOOST_AUTO_TEST_CASE(nested_array) {
368     ptree tree;
369     standard_parser<char> p;
370     const char* input = "[[1,2],3,[4,5]]";
371     BOOST_REQUIRE(p.parse_array(input, tree));
372     BOOST_REQUIRE_EQUAL(3u, tree.size());
373     ptree::iterator it = tree.begin();
374     BOOST_CHECK_EQUAL("", it->first);
375     {
376         ptree& sub = it->second;
377         BOOST_CHECK_EQUAL("", sub.data());
378         BOOST_REQUIRE_EQUAL(2u, sub.size());
379         ptree::iterator iit = sub.begin();
380         BOOST_CHECK_EQUAL("", iit->first);
381         BOOST_CHECK_EQUAL("1", iit->second.data());
382         ++iit;
383         BOOST_CHECK_EQUAL("", iit->first);
384         BOOST_CHECK_EQUAL("2", iit->second.data());
385         ++iit;
386         BOOST_CHECK_EQUAL(sub.end(), iit);
387     }
388     ++it;
389     BOOST_CHECK_EQUAL("", it->first);
390     BOOST_CHECK_EQUAL("3", it->second.data());
391     ++it;
392     BOOST_CHECK_EQUAL("", it->first);
393     {
394         ptree& sub = it->second;
395         BOOST_CHECK_EQUAL("", sub.data());
396         BOOST_REQUIRE_EQUAL(2u, sub.size());
397         ptree::iterator iit = sub.begin();
398         BOOST_CHECK_EQUAL("", iit->first);
399         BOOST_CHECK_EQUAL("4", iit->second.data());
400         ++iit;
401         BOOST_CHECK_EQUAL("", iit->first);
402         BOOST_CHECK_EQUAL("5", iit->second.data());
403         ++iit;
404         BOOST_CHECK_EQUAL(sub.end(), iit);
405     }
406     ++it;
407     BOOST_CHECK_EQUAL(tree.end(), it);
408 }
409 
BOOST_AUTO_TEST_CASE(empty_object)410 BOOST_AUTO_TEST_CASE(empty_object) {
411     ptree tree;
412     standard_parser<char> p;
413     const char* input = " { }";
414     BOOST_REQUIRE(p.parse_object(input, tree));
415     BOOST_CHECK_EQUAL("", tree.data());
416     BOOST_CHECK_EQUAL(0u, tree.size());
417 }
418 
BOOST_AUTO_TEST_CASE(object_gets_tagged)419 BOOST_AUTO_TEST_CASE(object_gets_tagged) {
420     wptree tree;
421     prefixing_parser<wchar_t> p;
422     const wchar_t* input = L" { }";
423     BOOST_REQUIRE(p.parse_object(input, tree));
424     BOOST_CHECK_EQUAL(L"o:", tree.data());
425     BOOST_CHECK_EQUAL(0u, tree.size());
426 }
427 
BOOST_AUTO_TEST_CASE(object_with_values)428 BOOST_AUTO_TEST_CASE(object_with_values) {
429     wptree tree;
430     standard_parser<wchar_t> p;
431     const wchar_t* input = L"{\n"
432 L"      \"1\":123, \"2\"\n"
433 L"            :\"abc\" ,\"3\": true ,\n"
434 L"      \"4\"   : null\n"
435 L"  }";
436     BOOST_REQUIRE(p.parse_object(input, tree));
437     BOOST_REQUIRE_EQUAL(4u, tree.size());
438     wptree::iterator it = tree.begin();
439     BOOST_CHECK_EQUAL(L"1", it->first);
440     BOOST_CHECK_EQUAL(L"123", it->second.data());
441     ++it;
442     BOOST_CHECK_EQUAL(L"2", it->first);
443     BOOST_CHECK_EQUAL(L"abc", it->second.data());
444     ++it;
445     BOOST_CHECK_EQUAL(L"3", it->first);
446     BOOST_CHECK_EQUAL(L"true", it->second.data());
447     ++it;
448     BOOST_CHECK_EQUAL(L"4", it->first);
449     BOOST_CHECK_EQUAL(L"null", it->second.data());
450     ++it;
451     BOOST_CHECK_EQUAL(tree.end(), it);
452 }
453 
BOOST_AUTO_TEST_CASE(object_values_get_tagged)454 BOOST_AUTO_TEST_CASE(object_values_get_tagged) {
455     ptree tree;
456     prefixing_parser<char> p;
457     const char* input = "{\n"
458         "\"1\": 123, \"2\": \"abc\" ,\"3\": true ,\n"
459         "\"4\": null\n"
460     "}";
461     BOOST_REQUIRE(p.parse_object(input, tree));
462     BOOST_REQUIRE_EQUAL(4u, tree.size());
463     BOOST_CHECK_EQUAL("o:", tree.data());
464     ptree::iterator it = tree.begin();
465     BOOST_CHECK_EQUAL("1", it->first);
466     BOOST_CHECK_EQUAL("n:123", it->second.data());
467     ++it;
468     BOOST_CHECK_EQUAL("2", it->first);
469     BOOST_CHECK_EQUAL("s:abc", it->second.data());
470     ++it;
471     BOOST_CHECK_EQUAL("3", it->first);
472     BOOST_CHECK_EQUAL("b:true", it->second.data());
473     ++it;
474     BOOST_CHECK_EQUAL("4", it->first);
475     BOOST_CHECK_EQUAL("_:null", it->second.data());
476     ++it;
477     BOOST_CHECK_EQUAL(tree.end(), it);
478 }
479 
BOOST_AUTO_TEST_CASE(nested_object)480 BOOST_AUTO_TEST_CASE(nested_object) {
481     ptree tree;
482     standard_parser<char> p;
483     const char* input = "{\"a\":{\"b\":1,\"c\":2},\"d\":3,\"e\":{\"f\":4,\"g\":5}}";
484     BOOST_REQUIRE(p.parse_object(input, tree));
485     BOOST_REQUIRE_EQUAL(3u, tree.size());
486     ptree::iterator it = tree.begin();
487     BOOST_CHECK_EQUAL("a", it->first);
488     {
489         ptree& sub = it->second;
490         BOOST_CHECK_EQUAL("", sub.data());
491         BOOST_REQUIRE_EQUAL(2u, sub.size());
492         ptree::iterator iit = sub.begin();
493         BOOST_CHECK_EQUAL("b", iit->first);
494         BOOST_CHECK_EQUAL("1", iit->second.data());
495         ++iit;
496         BOOST_CHECK_EQUAL("c", iit->first);
497         BOOST_CHECK_EQUAL("2", iit->second.data());
498         ++iit;
499         BOOST_CHECK_EQUAL(sub.end(), iit);
500     }
501     ++it;
502     BOOST_CHECK_EQUAL("d", it->first);
503     BOOST_CHECK_EQUAL("3", it->second.data());
504     ++it;
505     BOOST_CHECK_EQUAL("e", it->first);
506     {
507         ptree& sub = it->second;
508         BOOST_CHECK_EQUAL("", sub.data());
509         BOOST_REQUIRE_EQUAL(2u, sub.size());
510         ptree::iterator iit = sub.begin();
511         BOOST_CHECK_EQUAL("f", iit->first);
512         BOOST_CHECK_EQUAL("4", iit->second.data());
513         ++iit;
514         BOOST_CHECK_EQUAL("g", iit->first);
515         BOOST_CHECK_EQUAL("5", iit->second.data());
516         ++iit;
517         BOOST_CHECK_EQUAL(sub.end(), iit);
518     }
519     ++it;
520     BOOST_CHECK_EQUAL(tree.end(), it);
521 }
522 
BOOST_AUTO_TEST_CASE(array_in_object)523 BOOST_AUTO_TEST_CASE(array_in_object) {
524     ptree tree;
525     standard_parser<char> p;
526     const char* input = "{\"a\":[1,2],\"b\":3,\"c\":[4,5]}";
527     BOOST_REQUIRE(p.parse_object(input, tree));
528     BOOST_REQUIRE_EQUAL(3u, tree.size());
529     ptree::iterator it = tree.begin();
530     BOOST_CHECK_EQUAL("a", it->first);
531     {
532         ptree& sub = it->second;
533         BOOST_CHECK_EQUAL("", sub.data());
534         BOOST_REQUIRE_EQUAL(2u, sub.size());
535         ptree::iterator iit = sub.begin();
536         BOOST_CHECK_EQUAL("", iit->first);
537         BOOST_CHECK_EQUAL("1", iit->second.data());
538         ++iit;
539         BOOST_CHECK_EQUAL("", iit->first);
540         BOOST_CHECK_EQUAL("2", iit->second.data());
541         ++iit;
542         BOOST_CHECK_EQUAL(sub.end(), iit);
543     }
544     ++it;
545     BOOST_CHECK_EQUAL("b", it->first);
546     BOOST_CHECK_EQUAL("3", it->second.data());
547     ++it;
548     BOOST_CHECK_EQUAL("c", it->first);
549     {
550         ptree& sub = it->second;
551         BOOST_CHECK_EQUAL("", sub.data());
552         BOOST_REQUIRE_EQUAL(2u, sub.size());
553         ptree::iterator iit = sub.begin();
554         BOOST_CHECK_EQUAL("", iit->first);
555         BOOST_CHECK_EQUAL("4", iit->second.data());
556         ++iit;
557         BOOST_CHECK_EQUAL("", iit->first);
558         BOOST_CHECK_EQUAL("5", iit->second.data());
559         ++iit;
560         BOOST_CHECK_EQUAL(sub.end(), iit);
561     }
562     ++it;
563     BOOST_CHECK_EQUAL(tree.end(), it);
564 }
565 
BOOST_AUTO_TEST_CASE(object_in_array)566 BOOST_AUTO_TEST_CASE(object_in_array) {
567     ptree tree;
568     standard_parser<char> p;
569     const char* input = "[{\"a\":1,\"b\":2},3,{\"c\":4,\"d\":5}]";
570     BOOST_REQUIRE(p.parse_array(input, tree));
571     BOOST_REQUIRE_EQUAL(3u, tree.size());
572     ptree::iterator it = tree.begin();
573     BOOST_CHECK_EQUAL("", it->first);
574     {
575         ptree& sub = it->second;
576         BOOST_CHECK_EQUAL("", sub.data());
577         BOOST_REQUIRE_EQUAL(2u, sub.size());
578         ptree::iterator iit = sub.begin();
579         BOOST_CHECK_EQUAL("a", iit->first);
580         BOOST_CHECK_EQUAL("1", iit->second.data());
581         ++iit;
582         BOOST_CHECK_EQUAL("b", iit->first);
583         BOOST_CHECK_EQUAL("2", iit->second.data());
584         ++iit;
585         BOOST_CHECK_EQUAL(sub.end(), iit);
586     }
587     ++it;
588     BOOST_CHECK_EQUAL("", it->first);
589     BOOST_CHECK_EQUAL("3", it->second.data());
590     ++it;
591     BOOST_CHECK_EQUAL("", it->first);
592     {
593         ptree& sub = it->second;
594         BOOST_CHECK_EQUAL("", sub.data());
595         BOOST_REQUIRE_EQUAL(2u, sub.size());
596         ptree::iterator iit = sub.begin();
597         BOOST_CHECK_EQUAL("c", iit->first);
598         BOOST_CHECK_EQUAL("4", iit->second.data());
599         ++iit;
600         BOOST_CHECK_EQUAL("d", iit->first);
601         BOOST_CHECK_EQUAL("5", iit->second.data());
602         ++iit;
603         BOOST_CHECK_EQUAL(sub.end(), iit);
604     }
605     ++it;
606     BOOST_CHECK_EQUAL(tree.end(), it);
607 }
608 
BOOST_AUTO_TEST_CASE(parser_works_with_input_iterators)609 BOOST_AUTO_TEST_CASE(parser_works_with_input_iterators) {
610     const char* input = " {\n"
611 "       \"1\":123, \"2\"\n"
612 "            :\"abc\" ,\"3\": true ,\n"
613 "       \"4\"   : null, \"5\" : [ 1, 23\n"
614 "            , 456 ]\n"
615 "   }";
616 
617     std::istringstream is(input);
618     typedef std::istreambuf_iterator<char> iterator;
619     json_parser::detail::standard_callbacks<ptree> callbacks;
620     json_parser::detail::utf8_utf8_encoding encoding;
621     json_parser::detail::parser<json_parser::detail::standard_callbacks<ptree>,
622                                 json_parser::detail::utf8_utf8_encoding,
623                                 iterator, iterator>
624         p(callbacks, encoding);
625 
626     p.set_input("", boost::make_iterator_range(iterator(is), iterator()));
627     p.parse_value();
628 
629     const ptree& tree = callbacks.output();
630     BOOST_REQUIRE_EQUAL(5u, tree.size());
631     ptree::const_iterator it = tree.begin();
632     BOOST_CHECK_EQUAL("1", it->first);
633     BOOST_CHECK_EQUAL("123", it->second.data());
634     ++it;
635     BOOST_CHECK_EQUAL("2", it->first);
636     BOOST_CHECK_EQUAL("abc", it->second.data());
637     ++it;
638     BOOST_CHECK_EQUAL("3", it->first);
639     BOOST_CHECK_EQUAL("true", it->second.data());
640     ++it;
641     BOOST_CHECK_EQUAL("4", it->first);
642     BOOST_CHECK_EQUAL("null", it->second.data());
643     ++it;
644     BOOST_CHECK_EQUAL("5", it->first);
645     {
646         const ptree& sub = it->second;
647         BOOST_CHECK_EQUAL("", sub.data());
648         BOOST_REQUIRE_EQUAL(3u, sub.size());
649         ptree::const_iterator iit = sub.begin();
650         BOOST_CHECK_EQUAL("", iit->first);
651         BOOST_CHECK_EQUAL("1", iit->second.data());
652         ++iit;
653         BOOST_CHECK_EQUAL("", iit->first);
654         BOOST_CHECK_EQUAL("23", iit->second.data());
655         ++iit;
656         BOOST_CHECK_EQUAL("", iit->first);
657         BOOST_CHECK_EQUAL("456", iit->second.data());
658         ++iit;
659         BOOST_CHECK_EQUAL(sub.end(), iit);
660     }
661     ++it;
662     BOOST_CHECK_EQUAL(tree.end(), it);
663 }
664 
665 struct bad_parse_n {
666     const char* json;
667     const char* message_substring;
668 };
669 
parse_error_thrown_with_message_n(bad_parse_n param)670 void parse_error_thrown_with_message_n(bad_parse_n param) {
671     try {
672         standard_parser<char> p;
673         ptree dummy;
674         p.parse_value(param.json, dummy);
675         BOOST_FAIL("expected exception");
676     } catch (json_parser::json_parser_error& e) {
677         std::string message = e.message();
678         BOOST_CHECK_MESSAGE(message.find(param.message_substring) !=
679                                 std::string::npos,
680                             "bad error message on input '" << param.json
681                                 << "', need: '" << param.message_substring
682                                 << "' but found '" << message << "'");
683     }
684 }
685 
686 const bad_parse_n errors_n[] = {
687     {"", "expected value"},
688     {"(", "expected value"},
689 
690     {"n", "expected 'null'"},
691     {"nu", "expected 'null'"},
692     {"nul", "expected 'null'"},
693     {"n ", "expected 'null'"},
694     {"nu ", "expected 'null'"},
695     {"nul ", "expected 'null'"},
696     {"nx", "expected 'null'"},
697     {"nux", "expected 'null'"},
698     {"nulx", "expected 'null'"},
699 
700     {"t", "expected 'true'"},
701     {"tr", "expected 'true'"},
702     {"tu", "expected 'true'"},
703     {"t ", "expected 'true'"},
704     {"tr ", "expected 'true'"},
705     {"tru ", "expected 'true'"},
706     {"tx", "expected 'true'"},
707     {"trx", "expected 'true'"},
708     {"trux", "expected 'true'"},
709 
710     {"f", "expected 'false'"},
711     {"fa", "expected 'false'"},
712     {"fal", "expected 'false'"},
713     {"fals", "expected 'false'"},
714     {"f ", "expected 'false'"},
715     {"fa ", "expected 'false'"},
716     {"fal ", "expected 'false'"},
717     {"fals ", "expected 'false'"},
718     {"fx", "expected 'false'"},
719     {"fax", "expected 'false'"},
720     {"falx", "expected 'false'"},
721     {"falsx", "expected 'false'"},
722 
723     {"-", "expected digits"},
724     {"01", "garbage after data"},
725     {"0.", "need at least one digit after '.'"},
726     {"0e", "need at least one digit in exponent"},
727     {"0e-", "need at least one digit in exponent"},
728 
729     {"\"", "unterminated string"},
730     {"\"asd", "unterminated string"},
731     {"\"\n\"", "invalid code sequence"}, // control character
732     {"\"\xff\"", "invalid code sequence"}, // bad lead byte
733     {"\"\x80\"", "invalid code sequence"}, // stray trail byte
734     {"\"\xc0", "invalid code sequence"}, // eos after lead byte
735     {"\"\xc0\"", "invalid code sequence"}, // bad trail byte
736     {"\"\xc0m\"", "invalid code sequence"}, // also bad trail byte
737     {"\"\\", "invalid escape sequence"},
738     {"\"\\p\"", "invalid escape sequence"},
739     {"\"\\u", "invalid escape sequence"},
740     {"\"\\u\"", "invalid escape sequence"},
741     {"\"\\ug\"", "invalid escape sequence"},
742     {"\"\\u1\"", "invalid escape sequence"},
743     {"\"\\u1g\"", "invalid escape sequence"},
744     {"\"\\u11\"", "invalid escape sequence"},
745     {"\"\\u11g\"", "invalid escape sequence"},
746     {"\"\\u111\"", "invalid escape sequence"},
747     {"\"\\u111g\"", "invalid escape sequence"},
748     {"\"\\ude00\"", "stray low surrogate"},
749     {"\"\\ud900", "stray high surrogate"},
750     {"\"\\ud900foo\"", "stray high surrogate"},
751     {"\"\\ud900\\", "expected codepoint reference"},
752     {"\"\\ud900\\n\"", "expected codepoint reference"},
753     {"\"\\ud900\\u1000\"", "expected low surrogate"},
754 
755     {"[", "expected value"},
756     {"[1", "expected ']' or ','"},
757     {"[1,", "expected value"},
758     {"[1,]", "expected value"},
759     {"[1}", "expected ']' or ','"},
760 
761     {"{", "expected key string"},
762     {"{1:2}", "expected key string"},
763     {"{\"\"", "expected ':'"},
764     {"{\"\"}", "expected ':'"},
765     {"{\"\":", "expected value"},
766     {"{\"\":}", "expected value"},
767     {"{\"\":0", "expected '}' or ','"},
768     {"{\"\":0]", "expected '}' or ','"},
769     {"{\"\":0,", "expected key string"},
770     {"{\"\":0,}", "expected key string"},
771 };
772 
773 struct bad_parse_w {
774     const wchar_t* json;
775     const char* message_substring;
776 };
777 
parse_error_thrown_with_message_w(bad_parse_w param)778 void parse_error_thrown_with_message_w(bad_parse_w param) {
779     try {
780         standard_parser<wchar_t> p;
781         wptree dummy;
782         p.parse_value(param.json, dummy);
783         BOOST_FAIL("expected exception");
784     } catch (json_parser::json_parser_error& e) {
785         std::string message = e.message();
786         BOOST_CHECK_MESSAGE(message.find(param.message_substring) !=
787                                 std::string::npos,
788                             "bad error message on input '" << param.json
789                                 << "', need: '" << param.message_substring
790                                 << "' but found '" << message << "'");
791     }
792 }
793 
794 const bad_parse_w errors_w[] = {
795     {L"", "expected value"},
796     {L"(", "expected value"},
797 
798     {L"n", "expected 'null'"},
799     {L"nu", "expected 'null'"},
800     {L"nul", "expected 'null'"},
801     {L"n ", "expected 'null'"},
802     {L"nu ", "expected 'null'"},
803     {L"nul ", "expected 'null'"},
804     {L"nx", "expected 'null'"},
805     {L"nux", "expected 'null'"},
806     {L"nulx", "expected 'null'"},
807 
808     {L"t", "expected 'true'"},
809     {L"tr", "expected 'true'"},
810     {L"tu", "expected 'true'"},
811     {L"t ", "expected 'true'"},
812     {L"tr ", "expected 'true'"},
813     {L"tru ", "expected 'true'"},
814     {L"tx", "expected 'true'"},
815     {L"trx", "expected 'true'"},
816     {L"trux", "expected 'true'"},
817 
818     {L"f", "expected 'false'"},
819     {L"fa", "expected 'false'"},
820     {L"fal", "expected 'false'"},
821     {L"fals", "expected 'false'"},
822     {L"f ", "expected 'false'"},
823     {L"fa ", "expected 'false'"},
824     {L"fal ", "expected 'false'"},
825     {L"fals ", "expected 'false'"},
826     {L"fx", "expected 'false'"},
827     {L"fax", "expected 'false'"},
828     {L"falx", "expected 'false'"},
829     {L"falsx", "expected 'false'"},
830 
831     {L"-", "expected digits"},
832     {L"01", "garbage after data"},
833     {L"0.", "need at least one digit after '.'"},
834     {L"0e", "need at least one digit in exponent"},
835     {L"0e-", "need at least one digit in exponent"},
836 
837     {L"\"", "unterminated string"},
838     {L"\"asd", "unterminated string"},
839     {L"\"\n\"", "invalid code sequence"}, // control character
840     // Encoding not known, so no UTF-16 encoding error tests.
841     {L"\"\\", "invalid escape sequence"},
842     {L"\"\\p\"", "invalid escape sequence"},
843     {L"\"\\u", "invalid escape sequence"},
844     {L"\"\\u\"", "invalid escape sequence"},
845     {L"\"\\ug\"", "invalid escape sequence"},
846     {L"\"\\u1\"", "invalid escape sequence"},
847     {L"\"\\u1g\"", "invalid escape sequence"},
848     {L"\"\\u11\"", "invalid escape sequence"},
849     {L"\"\\u11g\"", "invalid escape sequence"},
850     {L"\"\\u111\"", "invalid escape sequence"},
851     {L"\"\\u111g\"", "invalid escape sequence"},
852     {L"\"\\ude00\"", "stray low surrogate"},
853     {L"\"\\ud900", "stray high surrogate"},
854     {L"\"\\ud900foo\"", "stray high surrogate"},
855     {L"\"\\ud900\\", "expected codepoint reference"},
856     {L"\"\\ud900\\n\"", "expected codepoint reference"},
857     {L"\"\\ud900\\u1000\"", "expected low surrogate"},
858 
859     {L"[", "expected value"},
860     {L"[1", "expected ']' or ','"},
861     {L"[1,", "expected value"},
862     {L"[1,]", "expected value"},
863     {L"[1}", "expected ']' or ','"},
864 
865     {L"{", "expected key string"},
866     {L"{1:2}", "expected key string"},
867     {L"{\"\"", "expected ':'"},
868     {L"{\"\"}", "expected ':'"},
869     {L"{\"\":", "expected value"},
870     {L"{\"\":}", "expected value"},
871     {L"{\"\":0", "expected '}' or ','"},
872     {L"{\"\":0]", "expected '}' or ','"},
873     {L"{\"\":0,", "expected key string"},
874     {L"{\"\":0,}", "expected key string"},
875 };
876 
877 template <typename T, std::size_t N>
arraysize(T (&)[N])878 std::size_t arraysize(T(&)[N]) { return N; }
879 
880 #define ARRAY_TEST_CASE(fn, a) \
881     BOOST_PARAM_TEST_CASE(fn, (a), (a) + arraysize((a)))
882 
883 using namespace boost::unit_test;
884 
init_unit_test_suite(int,char * [])885 test_suite* init_unit_test_suite(int, char*[])
886 {
887     master_test_suite_t& ts = boost::unit_test::framework::master_test_suite();
888     ts.add(ARRAY_TEST_CASE(boolean_parse_result_is_input_n, booleans_n));
889     ts.add(ARRAY_TEST_CASE(boolean_parse_result_is_input_w, booleans_w));
890     ts.add(ARRAY_TEST_CASE(number_parse_result_is_input_n, numbers_n));
891     ts.add(ARRAY_TEST_CASE(number_parse_result_is_input_w, numbers_w));
892     ts.add(ARRAY_TEST_CASE(string_parsed_correctly_n, strings_n));
893     ts.add(ARRAY_TEST_CASE(string_parsed_correctly_w, strings_w));
894     ts.add(ARRAY_TEST_CASE(parse_error_thrown_with_message_n, errors_n));
895     ts.add(ARRAY_TEST_CASE(parse_error_thrown_with_message_w, errors_w));
896 
897     return 0;
898 }
899