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 | |
39 | test_parser() : parser(callbacks, encoding) {} |
40 | |
41 | bool parse_null(const string& input, string& output) { |
42 | parser.set_input("" , input); |
43 | bool result = parser.parse_null(); |
44 | if (result) { |
45 | parser.finish(); |
46 | output = callbacks.output().data(); |
47 | } |
48 | return result; |
49 | } |
50 | |
51 | bool parse_boolean(const string& input, string& output) { |
52 | parser.set_input("" , input); |
53 | bool result = parser.parse_boolean(); |
54 | if (result) { |
55 | parser.finish(); |
56 | output = callbacks.output().data(); |
57 | } |
58 | return result; |
59 | } |
60 | |
61 | bool parse_number(const string& input, string& output) { |
62 | parser.set_input("" , input); |
63 | bool result = parser.parse_number(); |
64 | if (result) { |
65 | parser.finish(); |
66 | output = callbacks.output().data(); |
67 | } |
68 | return result; |
69 | } |
70 | |
71 | bool parse_string(const string& input, string& output) { |
72 | parser.set_input("" , input); |
73 | bool result = parser.parse_string(); |
74 | if (result) { |
75 | parser.finish(); |
76 | output = callbacks.output().data(); |
77 | } |
78 | return result; |
79 | } |
80 | |
81 | bool parse_array(const string& input, tree& output) { |
82 | parser.set_input("" , input); |
83 | bool result = parser.parse_array(); |
84 | if (result) { |
85 | parser.finish(); |
86 | output = callbacks.output(); |
87 | } |
88 | return result; |
89 | } |
90 | |
91 | bool parse_object(const string& input, tree& output) { |
92 | parser.set_input("" , input); |
93 | bool result = parser.parse_object(); |
94 | if (result) { |
95 | parser.finish(); |
96 | output = callbacks.output(); |
97 | } |
98 | return result; |
99 | } |
100 | |
101 | void parse_value(const string& input, tree& output) { |
102 | parser.set_input("" , input); |
103 | parser.parse_value(); |
104 | parser.finish(); |
105 | output = callbacks.output(); |
106 | } |
107 | }; |
108 | |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
184 | test_boolean_parse_result_is_input_n(const std::string (¶m)[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 |
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 |
209 | test_boolean_parse_result_is_input_w(const std::wstring (¶m)[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 |
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 |
234 | test_number_parse_result_is_input_n(std::string const (¶m)[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 |
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 |
268 | test_number_parse_result_is_input_w(const std::wstring (¶m)[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 |
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> |
305 | void test_string_parsed_correctly_n(string_input_n const (¶m)[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 | {.encoded: "\"\"" , .expected: "" }, |
318 | {.encoded: "\"abc\"" , .expected: "abc" }, |
319 | {.encoded: "\"a\\nb\"" , .expected: "a\nb" }, |
320 | {.encoded: "\"\\\"\"" , .expected: "\"" }, |
321 | {.encoded: "\"\\\\\"" , .expected: "\\" }, |
322 | {.encoded: "\"\\/\"" , .expected: "/" }, |
323 | {.encoded: "\"\\b\"" , .expected: "\b" }, |
324 | {.encoded: "\"\\f\"" , .expected: "\f" }, |
325 | {.encoded: "\"\\r\"" , .expected: "\r" }, |
326 | {.encoded: "\"\\t\"" , .expected: "\t" }, |
327 | {.encoded: "\"\\u0001\\u00f2\\u28Ec\"" , .expected: "\x01" "\xC3\xB2" "\xE2\xA3\xAC" }, |
328 | {.encoded: "\"\\ud801\\udc37\"" , .expected: "\xf0\x90\x90\xb7" }, // U+10437 |
329 | {.encoded: "\xef\xbb\xbf\"\"" , .expected: "" } // BOM |
330 | }; |
331 | |
332 | static void |
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 |
348 | test_string_parsed_correctly_w(string_input_w const (¶m)[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 | {.encoded: L"\"\"" , .expected: L"" }, |
361 | {.encoded: L"\"abc\"" , .expected: L"abc" }, |
362 | {.encoded: L"\"a\\nb\"" , .expected: L"a\nb" }, |
363 | {.encoded: L"\"\\\"\"" , .expected: L"\"" }, |
364 | {.encoded: L"\"\\\\\"" , .expected: L"\\" }, |
365 | {.encoded: L"\"\\/\"" , .expected: L"/" }, |
366 | {.encoded: L"\"\\b\"" , .expected: L"\b" }, |
367 | {.encoded: L"\"\\f\"" , .expected: L"\f" }, |
368 | {.encoded: L"\"\\r\"" , .expected: L"\r" }, |
369 | {.encoded: L"\"\\t\"" , .expected: L"\t" }, |
370 | {.encoded: L"\"\\u0001\\u00f2\\u28Ec\"" , .expected: L"\x0001" L"\x00F2" L"\x28EC" }, |
371 | {.encoded: L"\xfeff\"\"" , .expected: L"" } // BOM |
372 | }; |
373 | |
374 | static void |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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(filename: "" , r: boost::make_iterator_range(Begin: iterator(is), End: iterator())); |
761 | p.parse_value(); |
762 | |
763 | const ptree& tree = callbacks.output(); |
764 | if(!BOOST_TEST_EQ(5u, tree.size())) |
765 | return; |
766 | ptree::const_iterator it = tree.begin(); |
767 | BOOST_TEST_EQ("1" , it->first); |
768 | BOOST_TEST_EQ("123" , it->second.data()); |
769 | ++it; |
770 | BOOST_TEST_EQ("2" , it->first); |
771 | BOOST_TEST_EQ("abc" , it->second.data()); |
772 | ++it; |
773 | BOOST_TEST_EQ("3" , it->first); |
774 | BOOST_TEST_EQ("true" , it->second.data()); |
775 | ++it; |
776 | BOOST_TEST_EQ("4" , it->first); |
777 | BOOST_TEST_EQ("null" , it->second.data()); |
778 | ++it; |
779 | BOOST_TEST_EQ("5" , it->first); |
780 | { |
781 | const ptree& sub = it->second; |
782 | BOOST_TEST_EQ("" , sub.data()); |
783 | if(!BOOST_TEST_EQ(3u, sub.size())) |
784 | return; |
785 | ptree::const_iterator iit = sub.begin(); |
786 | BOOST_TEST_EQ("" , iit->first); |
787 | BOOST_TEST_EQ("1" , iit->second.data()); |
788 | ++iit; |
789 | BOOST_TEST_EQ("" , iit->first); |
790 | BOOST_TEST_EQ("23" , iit->second.data()); |
791 | ++iit; |
792 | BOOST_TEST_EQ("" , iit->first); |
793 | BOOST_TEST_EQ("456" , iit->second.data()); |
794 | ++iit; |
795 | BOOST_TEST(sub.end() == iit); |
796 | } |
797 | ++it; |
798 | BOOST_TEST(tree.end() == it); |
799 | } |
800 | |
801 | struct bad_parse_n { |
802 | const char* json; |
803 | const char* message_substring; |
804 | }; |
805 | |
806 | template<std::size_t N> |
807 | void test_parse_error_thrown_with_message_n(bad_parse_n const (¶m)[N]) |
808 | { |
809 | for(std::size_t i = 0 ; i < N ; ++i) |
810 | { |
811 | try { |
812 | standard_parser<char> p; |
813 | ptree dummy; |
814 | p.parse_value(input: param[i].json, output&: dummy); |
815 | BOOST_ERROR("expected exception" ); |
816 | } catch (json_parser::json_parser_error& e) { |
817 | std::string message = e.message(); |
818 | if(message.find(param[i].message_substring) == |
819 | std::string::npos) |
820 | { |
821 | std::ostringstream ss; |
822 | ss << "bad error message on input '" << param[i].json |
823 | << "', need: '" << param[i].message_substring |
824 | << "' but found '" << message << "'" ; |
825 | BOOST_ERROR(ss.str().c_str()); |
826 | } |
827 | } |
828 | } |
829 | } |
830 | |
831 | const bad_parse_n errors_n[] = { |
832 | {.json: "" , .message_substring: "expected value" }, |
833 | {.json: "(" , .message_substring: "expected value" }, |
834 | |
835 | {.json: "n" , .message_substring: "expected 'null'" }, |
836 | {.json: "nu" , .message_substring: "expected 'null'" }, |
837 | {.json: "nul" , .message_substring: "expected 'null'" }, |
838 | {.json: "n " , .message_substring: "expected 'null'" }, |
839 | {.json: "nu " , .message_substring: "expected 'null'" }, |
840 | {.json: "nul " , .message_substring: "expected 'null'" }, |
841 | {.json: "nx" , .message_substring: "expected 'null'" }, |
842 | {.json: "nux" , .message_substring: "expected 'null'" }, |
843 | {.json: "nulx" , .message_substring: "expected 'null'" }, |
844 | |
845 | {.json: "t" , .message_substring: "expected 'true'" }, |
846 | {.json: "tr" , .message_substring: "expected 'true'" }, |
847 | {.json: "tu" , .message_substring: "expected 'true'" }, |
848 | {.json: "t " , .message_substring: "expected 'true'" }, |
849 | {.json: "tr " , .message_substring: "expected 'true'" }, |
850 | {.json: "tru " , .message_substring: "expected 'true'" }, |
851 | {.json: "tx" , .message_substring: "expected 'true'" }, |
852 | {.json: "trx" , .message_substring: "expected 'true'" }, |
853 | {.json: "trux" , .message_substring: "expected 'true'" }, |
854 | |
855 | {.json: "f" , .message_substring: "expected 'false'" }, |
856 | {.json: "fa" , .message_substring: "expected 'false'" }, |
857 | {.json: "fal" , .message_substring: "expected 'false'" }, |
858 | {.json: "fals" , .message_substring: "expected 'false'" }, |
859 | {.json: "f " , .message_substring: "expected 'false'" }, |
860 | {.json: "fa " , .message_substring: "expected 'false'" }, |
861 | {.json: "fal " , .message_substring: "expected 'false'" }, |
862 | {.json: "fals " , .message_substring: "expected 'false'" }, |
863 | {.json: "fx" , .message_substring: "expected 'false'" }, |
864 | {.json: "fax" , .message_substring: "expected 'false'" }, |
865 | {.json: "falx" , .message_substring: "expected 'false'" }, |
866 | {.json: "falsx" , .message_substring: "expected 'false'" }, |
867 | |
868 | {.json: "-" , .message_substring: "expected digits" }, |
869 | {.json: "01" , .message_substring: "garbage after data" }, |
870 | {.json: "0." , .message_substring: "need at least one digit after '.'" }, |
871 | {.json: "0e" , .message_substring: "need at least one digit in exponent" }, |
872 | {.json: "0e-" , .message_substring: "need at least one digit in exponent" }, |
873 | |
874 | {.json: "\"" , .message_substring: "unterminated string" }, |
875 | {.json: "\"asd" , .message_substring: "unterminated string" }, |
876 | {.json: "\"\n\"" , .message_substring: "invalid code sequence" }, // control character |
877 | {.json: "\"\xff\"" , .message_substring: "invalid code sequence" }, // bad lead byte |
878 | {.json: "\"\x80\"" , .message_substring: "invalid code sequence" }, // stray trail byte |
879 | {.json: "\"\xc0" , .message_substring: "invalid code sequence" }, // eos after lead byte |
880 | {.json: "\"\xc0\"" , .message_substring: "invalid code sequence" }, // bad trail byte |
881 | {.json: "\"\xc0m\"" , .message_substring: "invalid code sequence" }, // also bad trail byte |
882 | {.json: "\"\\" , .message_substring: "invalid escape sequence" }, |
883 | {.json: "\"\\p\"" , .message_substring: "invalid escape sequence" }, |
884 | {.json: "\"\\u" , .message_substring: "invalid escape sequence" }, |
885 | {.json: "\"\\u\"" , .message_substring: "invalid escape sequence" }, |
886 | {.json: "\"\\ug\"" , .message_substring: "invalid escape sequence" }, |
887 | {.json: "\"\\u1\"" , .message_substring: "invalid escape sequence" }, |
888 | {.json: "\"\\u1g\"" , .message_substring: "invalid escape sequence" }, |
889 | {.json: "\"\\u11\"" , .message_substring: "invalid escape sequence" }, |
890 | {.json: "\"\\u11g\"" , .message_substring: "invalid escape sequence" }, |
891 | {.json: "\"\\u111\"" , .message_substring: "invalid escape sequence" }, |
892 | {.json: "\"\\u111g\"" , .message_substring: "invalid escape sequence" }, |
893 | {.json: "\"\\ude00\"" , .message_substring: "stray low surrogate" }, |
894 | {.json: "\"\\ud900" , .message_substring: "stray high surrogate" }, |
895 | {.json: "\"\\ud900foo\"" , .message_substring: "stray high surrogate" }, |
896 | {.json: "\"\\ud900\\" , .message_substring: "expected codepoint reference" }, |
897 | {.json: "\"\\ud900\\n\"" , .message_substring: "expected codepoint reference" }, |
898 | {.json: "\"\\ud900\\u1000\"" , .message_substring: "expected low surrogate" }, |
899 | |
900 | {.json: "[" , .message_substring: "expected value" }, |
901 | {.json: "[1" , .message_substring: "expected ']' or ','" }, |
902 | {.json: "[1," , .message_substring: "expected value" }, |
903 | {.json: "[1,]" , .message_substring: "expected value" }, |
904 | {.json: "[1}" , .message_substring: "expected ']' or ','" }, |
905 | |
906 | {.json: "{" , .message_substring: "expected key string" }, |
907 | {.json: "{1:2}" , .message_substring: "expected key string" }, |
908 | {.json: "{\"\"" , .message_substring: "expected ':'" }, |
909 | {.json: "{\"\"}" , .message_substring: "expected ':'" }, |
910 | {.json: "{\"\":" , .message_substring: "expected value" }, |
911 | {.json: "{\"\":}" , .message_substring: "expected value" }, |
912 | {.json: "{\"\":0" , .message_substring: "expected '}' or ','" }, |
913 | {.json: "{\"\":0]" , .message_substring: "expected '}' or ','" }, |
914 | {.json: "{\"\":0," , .message_substring: "expected key string" }, |
915 | {.json: "{\"\":0,}" , .message_substring: "expected key string" }, |
916 | }; |
917 | |
918 | struct bad_parse_w { |
919 | const wchar_t* json; |
920 | const char* message_substring; |
921 | }; |
922 | |
923 | struct do_narrow |
924 | { |
925 | char operator()(std::wstring::value_type w) const |
926 | { |
927 | unsigned long u = static_cast<unsigned long>(w); |
928 | if (u < 32 || u > 126) |
929 | return '?'; |
930 | else |
931 | return static_cast<char>(u); |
932 | } |
933 | }; |
934 | static std::string |
935 | make_narrow(std::wstring const& in) |
936 | { |
937 | std::string result(in.size(), ' '); |
938 | std::transform(first: in.begin(), last: in.end(), result: result.begin(), unary_op: do_narrow()); |
939 | return result; |
940 | } |
941 | |
942 | template<std::size_t N> |
943 | void |
944 | test_parse_error_thrown_with_message_w(bad_parse_w const (¶m)[N]) |
945 | { |
946 | for(std::size_t i = 0 ; i < N ; ++i) |
947 | { |
948 | try { |
949 | standard_parser<wchar_t> p; |
950 | wptree dummy; |
951 | p.parse_value(input: param[i].json, output&: dummy); |
952 | BOOST_ERROR("expected exception" ); |
953 | } catch (json_parser::json_parser_error& e) { |
954 | std::string message = e.message(); |
955 | if (message.find(param[i].message_substring) == |
956 | std::string::npos) |
957 | { |
958 | std::ostringstream ss; |
959 | ss << "bad error message on input '" << make_narrow(param[i].json) |
960 | << "', need: '" << param[i].message_substring |
961 | << "' but found '" << message << "'" ; |
962 | BOOST_ERROR(ss.str().c_str()); |
963 | } |
964 | } |
965 | } |
966 | } |
967 | |
968 | const bad_parse_w |
969 | errors_w[] = { |
970 | {.json: L"" , .message_substring: "expected value" }, |
971 | {.json: L"(" , .message_substring: "expected value" }, |
972 | |
973 | {.json: L"n" , .message_substring: "expected 'null'" }, |
974 | {.json: L"nu" , .message_substring: "expected 'null'" }, |
975 | {.json: L"nul" , .message_substring: "expected 'null'" }, |
976 | {.json: L"n " , .message_substring: "expected 'null'" }, |
977 | {.json: L"nu " , .message_substring: "expected 'null'" }, |
978 | {.json: L"nul " , .message_substring: "expected 'null'" }, |
979 | {.json: L"nx" , .message_substring: "expected 'null'" }, |
980 | {.json: L"nux" , .message_substring: "expected 'null'" }, |
981 | {.json: L"nulx" , .message_substring: "expected 'null'" }, |
982 | |
983 | {.json: L"t" , .message_substring: "expected 'true'" }, |
984 | {.json: L"tr" , .message_substring: "expected 'true'" }, |
985 | {.json: L"tu" , .message_substring: "expected 'true'" }, |
986 | {.json: L"t " , .message_substring: "expected 'true'" }, |
987 | {.json: L"tr " , .message_substring: "expected 'true'" }, |
988 | {.json: L"tru " , .message_substring: "expected 'true'" }, |
989 | {.json: L"tx" , .message_substring: "expected 'true'" }, |
990 | {.json: L"trx" , .message_substring: "expected 'true'" }, |
991 | {.json: L"trux" , .message_substring: "expected 'true'" }, |
992 | |
993 | {.json: L"f" , .message_substring: "expected 'false'" }, |
994 | {.json: L"fa" , .message_substring: "expected 'false'" }, |
995 | {.json: L"fal" , .message_substring: "expected 'false'" }, |
996 | {.json: L"fals" , .message_substring: "expected 'false'" }, |
997 | {.json: L"f " , .message_substring: "expected 'false'" }, |
998 | {.json: L"fa " , .message_substring: "expected 'false'" }, |
999 | {.json: L"fal " , .message_substring: "expected 'false'" }, |
1000 | {.json: L"fals " , .message_substring: "expected 'false'" }, |
1001 | {.json: L"fx" , .message_substring: "expected 'false'" }, |
1002 | {.json: L"fax" , .message_substring: "expected 'false'" }, |
1003 | {.json: L"falx" , .message_substring: "expected 'false'" }, |
1004 | {.json: L"falsx" , .message_substring: "expected 'false'" }, |
1005 | |
1006 | {.json: L"-" , .message_substring: "expected digits" }, |
1007 | {.json: L"01" , .message_substring: "garbage after data" }, |
1008 | {.json: L"0." , .message_substring: "need at least one digit after '.'" }, |
1009 | {.json: L"0e" , .message_substring: "need at least one digit in exponent" }, |
1010 | {.json: L"0e-" , .message_substring: "need at least one digit in exponent" }, |
1011 | |
1012 | {.json: L"\"" , .message_substring: "unterminated string" }, |
1013 | {.json: L"\"asd" , .message_substring: "unterminated string" }, |
1014 | {.json: L"\"\n\"" , .message_substring: "invalid code sequence" }, // control character |
1015 | // Encoding not known, so no UTF-16 encoding error tests. |
1016 | {.json: L"\"\\" , .message_substring: "invalid escape sequence" }, |
1017 | {.json: L"\"\\p\"" , .message_substring: "invalid escape sequence" }, |
1018 | {.json: L"\"\\u" , .message_substring: "invalid escape sequence" }, |
1019 | {.json: L"\"\\u\"" , .message_substring: "invalid escape sequence" }, |
1020 | {.json: L"\"\\ug\"" , .message_substring: "invalid escape sequence" }, |
1021 | {.json: L"\"\\u1\"" , .message_substring: "invalid escape sequence" }, |
1022 | {.json: L"\"\\u1g\"" , .message_substring: "invalid escape sequence" }, |
1023 | {.json: L"\"\\u11\"" , .message_substring: "invalid escape sequence" }, |
1024 | {.json: L"\"\\u11g\"" , .message_substring: "invalid escape sequence" }, |
1025 | {.json: L"\"\\u111\"" , .message_substring: "invalid escape sequence" }, |
1026 | {.json: L"\"\\u111g\"" , .message_substring: "invalid escape sequence" }, |
1027 | {.json: L"\"\\ude00\"" , .message_substring: "stray low surrogate" }, |
1028 | {.json: L"\"\\ud900" , .message_substring: "stray high surrogate" }, |
1029 | {.json: L"\"\\ud900foo\"" , .message_substring: "stray high surrogate" }, |
1030 | {.json: L"\"\\ud900\\" , .message_substring: "expected codepoint reference" }, |
1031 | {.json: L"\"\\ud900\\n\"" , .message_substring: "expected codepoint reference" }, |
1032 | {.json: L"\"\\ud900\\u1000\"" , .message_substring: "expected low surrogate" }, |
1033 | |
1034 | {.json: L"[" , .message_substring: "expected value" }, |
1035 | {.json: L"[1" , .message_substring: "expected ']' or ','" }, |
1036 | {.json: L"[1," , .message_substring: "expected value" }, |
1037 | {.json: L"[1,]" , .message_substring: "expected value" }, |
1038 | {.json: L"[1}" , .message_substring: "expected ']' or ','" }, |
1039 | |
1040 | {.json: L"{" , .message_substring: "expected key string" }, |
1041 | {.json: L"{1:2}" , .message_substring: "expected key string" }, |
1042 | {.json: L"{\"\"" , .message_substring: "expected ':'" }, |
1043 | {.json: L"{\"\"}" , .message_substring: "expected ':'" }, |
1044 | {.json: L"{\"\":" , .message_substring: "expected value" }, |
1045 | {.json: L"{\"\":}" , .message_substring: "expected value" }, |
1046 | {.json: L"{\"\":0" , .message_substring: "expected '}' or ','" }, |
1047 | {.json: L"{\"\":0]" , .message_substring: "expected '}' or ','" }, |
1048 | {.json: L"{\"\":0," , .message_substring: "expected key string" }, |
1049 | {.json: L"{\"\":0,}" , .message_substring: "expected key string" }, |
1050 | }; |
1051 | |
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(param: booleans_n); |
1062 | test_boolean_parse_result_is_input_w(param: booleans_w); |
1063 | test_number_parse_result_is_input_n(param: numbers_n); |
1064 | test_number_parse_result_is_input_w(param: numbers_w); |
1065 | test_uses_traits_from_number_n(); |
1066 | test_string_parsed_correctly_n(param: strings_n); |
1067 | test_string_parsed_correctly_w(param: strings_w); |
1068 | test_parse_error_thrown_with_message_n(param: errors_n); |
1069 | test_parse_error_thrown_with_message_w(param: errors_w); |
1070 | test_uses_string_callbacks(); |
1071 | test_empty_array(); |
1072 | test_array_with_values(); |
1073 | test_array_values_get_tagged(); |
1074 | test_nested_array(); |
1075 | test_empty_object(); |
1076 | test_object_gets_tagged(); |
1077 | test_object_with_values(); |
1078 | test_object_values_get_tagged(); |
1079 | test_nested_object(); |
1080 | test_array_in_object(); |
1081 | test_object_in_array(); |
1082 | test_parser_works_with_input_iterators(); |
1083 | test_uses_traits_from_null_w(); |
1084 | test_uses_traits_from_number_w(); |
1085 | test_array_gets_tagged(); |
1086 | return boost::report_errors(); |
1087 | } |
1088 | |
1089 | /* |
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 | */ |