|
21 | 21 | #include <json/config.h>
|
22 | 22 | #include <json/json.h>
|
23 | 23 | #include <limits>
|
| 24 | +#include <memory> |
24 | 25 | #include <sstream>
|
25 | 26 | #include <string>
|
26 | 27 |
|
@@ -2641,167 +2642,213 @@ JSONTEST_FIXTURE_LOCAL(StreamWriterTest, unicode) {
|
2641 | 2642 | "\"\\t\\n\\ud806\\udca1=\\u0133\\ud82c\\udd1b\\uff67\"\n}");
|
2642 | 2643 | }
|
2643 | 2644 |
|
2644 |
| -struct ReaderTest : JsonTest::TestCase {}; |
| 2645 | +struct ReaderTest : JsonTest::TestCase { |
| 2646 | + void setStrictMode() { |
| 2647 | + reader = std::unique_ptr<Json::Reader>( |
| 2648 | + new Json::Reader(Json::Features{}.strictMode())); |
| 2649 | + } |
2645 | 2650 |
|
2646 |
| -JSONTEST_FIXTURE_LOCAL(ReaderTest, parseWithNoErrors) { |
2647 |
| - Json::Reader reader; |
| 2651 | + void checkStructuredErrors( |
| 2652 | + const std::vector<Json::Reader::StructuredError>& actual, |
| 2653 | + const std::vector<Json::Reader::StructuredError>& expected) { |
| 2654 | + JSONTEST_ASSERT_EQUAL(actual.size(), expected.size()); |
| 2655 | + for (size_t i = 0; i < actual.size(); ++i) { |
| 2656 | + const auto& a = actual[i]; |
| 2657 | + const auto& e = expected[i]; |
| 2658 | + JSONTEST_ASSERT_EQUAL(a.offset_start, e.offset_start) << i; |
| 2659 | + JSONTEST_ASSERT_EQUAL(a.offset_limit, e.offset_limit) << i; |
| 2660 | + JSONTEST_ASSERT_EQUAL(a.message, e.message) << i; |
| 2661 | + } |
| 2662 | + } |
| 2663 | + |
| 2664 | + template <typename Input> void checkParse(Input&& input) { |
| 2665 | + JSONTEST_ASSERT(reader->parse(input, root)); |
| 2666 | + } |
| 2667 | + |
| 2668 | + template <typename Input> |
| 2669 | + void |
| 2670 | + checkParse(Input&& input, |
| 2671 | + const std::vector<Json::Reader::StructuredError>& structured) { |
| 2672 | + JSONTEST_ASSERT(!reader->parse(input, root)); |
| 2673 | + checkStructuredErrors(reader->getStructuredErrors(), structured); |
| 2674 | + } |
| 2675 | + |
| 2676 | + template <typename Input> |
| 2677 | + void checkParse(Input&& input, |
| 2678 | + const std::vector<Json::Reader::StructuredError>& structured, |
| 2679 | + const std::string& formatted) { |
| 2680 | + checkParse(input, structured); |
| 2681 | + JSONTEST_ASSERT_EQUAL(reader->getFormattedErrorMessages(), formatted); |
| 2682 | + } |
| 2683 | + |
| 2684 | + std::unique_ptr<Json::Reader> reader{new Json::Reader()}; |
2648 | 2685 | Json::Value root;
|
2649 |
| - bool ok = reader.parse("{ \"property\" : \"value\" }", root); |
2650 |
| - JSONTEST_ASSERT(ok); |
2651 |
| - JSONTEST_ASSERT(reader.getFormattedErrorMessages().empty()); |
2652 |
| - JSONTEST_ASSERT(reader.getStructuredErrors().empty()); |
| 2686 | +}; |
| 2687 | + |
| 2688 | +JSONTEST_FIXTURE_LOCAL(ReaderTest, parseWithNoErrors) { |
| 2689 | + checkParse(R"({ "property" : "value" })"); |
| 2690 | +} |
| 2691 | + |
| 2692 | +JSONTEST_FIXTURE_LOCAL(ReaderTest, parseObject) { |
| 2693 | + checkParse(R"({"property"})", |
| 2694 | + {{11, 12, "Missing ':' after object member name"}}, |
| 2695 | + "* Line 1, Column 12\n Missing ':' after object member name\n"); |
| 2696 | + checkParse( |
| 2697 | + R"({"property" : "value" )", |
| 2698 | + {{22, 22, "Missing ',' or '}' in object declaration"}}, |
| 2699 | + "* Line 1, Column 23\n Missing ',' or '}' in object declaration\n"); |
| 2700 | + checkParse(R"({"property" : "value", )", |
| 2701 | + {{23, 23, "Missing '}' or object member name"}}, |
| 2702 | + "* Line 1, Column 24\n Missing '}' or object member name\n"); |
| 2703 | +} |
| 2704 | + |
| 2705 | +JSONTEST_FIXTURE_LOCAL(ReaderTest, parseArray) { |
| 2706 | + checkParse( |
| 2707 | + R"([ "value" )", {{10, 10, "Missing ',' or ']' in array declaration"}}, |
| 2708 | + "* Line 1, Column 11\n Missing ',' or ']' in array declaration\n"); |
| 2709 | + checkParse( |
| 2710 | + R"([ "value1" "value2" ] )", |
| 2711 | + {{11, 19, "Missing ',' or ']' in array declaration"}}, |
| 2712 | + "* Line 1, Column 12\n Missing ',' or ']' in array declaration\n"); |
| 2713 | +} |
| 2714 | + |
| 2715 | +JSONTEST_FIXTURE_LOCAL(ReaderTest, parseString) { |
| 2716 | + checkParse(R"([ "\u8a2a" ])"); |
| 2717 | + checkParse( |
| 2718 | + R"([ "\ud801" ])", |
| 2719 | + {{2, 10, |
| 2720 | + "additional six characters expected to parse unicode surrogate " |
| 2721 | + "pair."}}, |
| 2722 | + "* Line 1, Column 3\n" |
| 2723 | + " additional six characters expected to parse unicode surrogate pair.\n" |
| 2724 | + "See Line 1, Column 10 for detail.\n"); |
| 2725 | + checkParse(R"([ "\ud801\d1234" ])", |
| 2726 | + {{2, 16, |
| 2727 | + "expecting another \\u token to begin the " |
| 2728 | + "second half of a unicode surrogate pair"}}, |
| 2729 | + "* Line 1, Column 3\n" |
| 2730 | + " expecting another \\u token to begin the " |
| 2731 | + "second half of a unicode surrogate pair\n" |
| 2732 | + "See Line 1, Column 12 for detail.\n"); |
| 2733 | + checkParse(R"([ "\ua3t@" ])", |
| 2734 | + {{2, 10, |
| 2735 | + "Bad unicode escape sequence in string: " |
| 2736 | + "hexadecimal digit expected."}}, |
| 2737 | + "* Line 1, Column 3\n" |
| 2738 | + " Bad unicode escape sequence in string: " |
| 2739 | + "hexadecimal digit expected.\n" |
| 2740 | + "See Line 1, Column 9 for detail.\n"); |
| 2741 | + checkParse( |
| 2742 | + R"([ "\ua3t" ])", |
| 2743 | + {{2, 9, "Bad unicode escape sequence in string: four digits expected."}}, |
| 2744 | + "* Line 1, Column 3\n" |
| 2745 | + " Bad unicode escape sequence in string: four digits expected.\n" |
| 2746 | + "See Line 1, Column 6 for detail.\n"); |
2653 | 2747 | }
|
2654 | 2748 |
|
2655 | 2749 | JSONTEST_FIXTURE_LOCAL(ReaderTest, parseComment) {
|
2656 |
| - Json::Reader reader; |
2657 |
| - Json::Value root; |
2658 |
| - bool ok = reader.parse("{ /*commentBeforeValue*/" |
2659 |
| - " \"property\" : \"value\" }" |
2660 |
| - "//commentAfterValue\n", |
2661 |
| - root); |
2662 |
| - JSONTEST_ASSERT(ok); |
2663 |
| - JSONTEST_ASSERT(reader.getFormattedErrorMessages().empty()); |
2664 |
| - JSONTEST_ASSERT(reader.getStructuredErrors().empty()); |
| 2750 | + checkParse( |
| 2751 | + R"({ /*commentBeforeValue*/ "property" : "value" }//commentAfterValue)" |
| 2752 | + "\n"); |
| 2753 | + checkParse(" true //comment1\n//comment2\r//comment3\r\n"); |
2665 | 2754 | }
|
2666 | 2755 |
|
2667 | 2756 | JSONTEST_FIXTURE_LOCAL(ReaderTest, streamParseWithNoErrors) {
|
2668 |
| - Json::Reader reader; |
2669 |
| - std::string styled = "{ \"property\" : \"value\" }"; |
| 2757 | + std::string styled = R"({ "property" : "value" })"; |
2670 | 2758 | std::istringstream iss(styled);
|
2671 |
| - Json::Value root; |
2672 |
| - bool ok = reader.parse(iss, root); |
2673 |
| - JSONTEST_ASSERT(ok); |
2674 |
| - JSONTEST_ASSERT(reader.getFormattedErrorMessages().empty()); |
2675 |
| - JSONTEST_ASSERT(reader.getStructuredErrors().empty()); |
| 2759 | + checkParse(iss); |
2676 | 2760 | }
|
2677 | 2761 |
|
2678 | 2762 | JSONTEST_FIXTURE_LOCAL(ReaderTest, parseWithNoErrorsTestingOffsets) {
|
2679 |
| - Json::Reader reader; |
2680 |
| - Json::Value root; |
2681 |
| - bool ok = reader.parse("{ \"property\" : [\"value\", \"value2\"], \"obj\" : " |
2682 |
| - "{ \"nested\" : -6.2e+15, \"bool\" : true}, \"null\" :" |
2683 |
| - " null, \"false\" : false }", |
2684 |
| - root); |
2685 |
| - JSONTEST_ASSERT(ok); |
2686 |
| - JSONTEST_ASSERT(reader.getFormattedErrorMessages().empty()); |
2687 |
| - JSONTEST_ASSERT(reader.getStructuredErrors().empty()); |
2688 |
| - JSONTEST_ASSERT(root["property"].getOffsetStart() == 15); |
2689 |
| - JSONTEST_ASSERT(root["property"].getOffsetLimit() == 34); |
2690 |
| - JSONTEST_ASSERT(root["property"][0].getOffsetStart() == 16); |
2691 |
| - JSONTEST_ASSERT(root["property"][0].getOffsetLimit() == 23); |
2692 |
| - JSONTEST_ASSERT(root["property"][1].getOffsetStart() == 25); |
2693 |
| - JSONTEST_ASSERT(root["property"][1].getOffsetLimit() == 33); |
2694 |
| - JSONTEST_ASSERT(root["obj"].getOffsetStart() == 44); |
2695 |
| - JSONTEST_ASSERT(root["obj"].getOffsetLimit() == 81); |
2696 |
| - JSONTEST_ASSERT(root["obj"]["nested"].getOffsetStart() == 57); |
2697 |
| - JSONTEST_ASSERT(root["obj"]["nested"].getOffsetLimit() == 65); |
2698 |
| - JSONTEST_ASSERT(root["obj"]["bool"].getOffsetStart() == 76); |
2699 |
| - JSONTEST_ASSERT(root["obj"]["bool"].getOffsetLimit() == 80); |
2700 |
| - JSONTEST_ASSERT(root["null"].getOffsetStart() == 92); |
2701 |
| - JSONTEST_ASSERT(root["null"].getOffsetLimit() == 96); |
2702 |
| - JSONTEST_ASSERT(root["false"].getOffsetStart() == 108); |
2703 |
| - JSONTEST_ASSERT(root["false"].getOffsetLimit() == 113); |
2704 |
| - JSONTEST_ASSERT(root.getOffsetStart() == 0); |
2705 |
| - JSONTEST_ASSERT(root.getOffsetLimit() == 115); |
| 2763 | + checkParse(R"({)" |
| 2764 | + R"( "property" : ["value", "value2"],)" |
| 2765 | + R"( "obj" : { "nested" : -6.2e+15, "bool" : true},)" |
| 2766 | + R"( "null" : null,)" |
| 2767 | + R"( "false" : false)" |
| 2768 | + R"( })"); |
| 2769 | + auto checkOffsets = [&](const Json::Value& v, int start, int limit) { |
| 2770 | + JSONTEST_ASSERT_EQUAL(v.getOffsetStart(), start); |
| 2771 | + JSONTEST_ASSERT_EQUAL(v.getOffsetLimit(), limit); |
| 2772 | + }; |
| 2773 | + checkOffsets(root, 0, 115); |
| 2774 | + checkOffsets(root["property"], 15, 34); |
| 2775 | + checkOffsets(root["property"][0], 16, 23); |
| 2776 | + checkOffsets(root["property"][1], 25, 33); |
| 2777 | + checkOffsets(root["obj"], 44, 81); |
| 2778 | + checkOffsets(root["obj"]["nested"], 57, 65); |
| 2779 | + checkOffsets(root["obj"]["bool"], 76, 80); |
| 2780 | + checkOffsets(root["null"], 92, 96); |
| 2781 | + checkOffsets(root["false"], 108, 113); |
2706 | 2782 | }
|
2707 | 2783 |
|
2708 | 2784 | JSONTEST_FIXTURE_LOCAL(ReaderTest, parseWithOneError) {
|
2709 |
| - Json::Reader reader; |
2710 |
| - Json::Value root; |
2711 |
| - bool ok = reader.parse("{ \"property\" :: \"value\" }", root); |
2712 |
| - JSONTEST_ASSERT(!ok); |
2713 |
| - JSONTEST_ASSERT(reader.getFormattedErrorMessages() == |
2714 |
| - "* Line 1, Column 15\n Syntax error: value, object or array " |
2715 |
| - "expected.\n"); |
2716 |
| - std::vector<Json::Reader::StructuredError> errors = |
2717 |
| - reader.getStructuredErrors(); |
2718 |
| - JSONTEST_ASSERT(errors.size() == 1); |
2719 |
| - JSONTEST_ASSERT(errors.at(0).offset_start == 14); |
2720 |
| - JSONTEST_ASSERT(errors.at(0).offset_limit == 15); |
2721 |
| - JSONTEST_ASSERT(errors.at(0).message == |
2722 |
| - "Syntax error: value, object or array expected."); |
| 2785 | + checkParse(R"({ "property" :: "value" })", |
| 2786 | + {{14, 15, "Syntax error: value, object or array expected."}}, |
| 2787 | + "* Line 1, Column 15\n Syntax error: value, object or array " |
| 2788 | + "expected.\n"); |
| 2789 | + checkParse("s", {{0, 1, "Syntax error: value, object or array expected."}}, |
| 2790 | + "* Line 1, Column 1\n Syntax error: value, object or array " |
| 2791 | + "expected.\n"); |
| 2792 | +} |
| 2793 | + |
| 2794 | +JSONTEST_FIXTURE_LOCAL(ReaderTest, parseSpecialFloat) { |
| 2795 | + checkParse(R"({ "a" : Infi })", |
| 2796 | + {{8, 9, "Syntax error: value, object or array expected."}}, |
| 2797 | + "* Line 1, Column 9\n Syntax error: value, object or array " |
| 2798 | + "expected.\n"); |
| 2799 | + checkParse(R"({ "a" : Infiniaa })", |
| 2800 | + {{8, 9, "Syntax error: value, object or array expected."}}, |
| 2801 | + "* Line 1, Column 9\n Syntax error: value, object or array " |
| 2802 | + "expected.\n"); |
2723 | 2803 | }
|
2724 | 2804 |
|
2725 | 2805 | JSONTEST_FIXTURE_LOCAL(ReaderTest, strictModeParseNumber) {
|
2726 |
| - Json::Features feature; |
2727 |
| - Json::Reader reader(feature.strictMode()); |
2728 |
| - Json::Value root; |
2729 |
| - bool ok = reader.parse("123", root); |
2730 |
| - JSONTEST_ASSERT(!ok); |
2731 |
| - JSONTEST_ASSERT(reader.getFormattedErrorMessages() == |
2732 |
| - "* Line 1, Column 1\n" |
2733 |
| - " A valid JSON document must be either an array or" |
2734 |
| - " an object value.\n"); |
2735 |
| - std::vector<Json::Reader::StructuredError> errors = |
2736 |
| - reader.getStructuredErrors(); |
2737 |
| - JSONTEST_ASSERT(errors.size() == 1); |
2738 |
| - JSONTEST_ASSERT(errors.at(0).offset_start == 0); |
2739 |
| - JSONTEST_ASSERT(errors.at(0).offset_limit == 3); |
2740 |
| - JSONTEST_ASSERT(errors.at(0).message == |
2741 |
| - "A valid JSON document must be either an array or" |
2742 |
| - " an object value."); |
| 2806 | + setStrictMode(); |
| 2807 | + checkParse( |
| 2808 | + "123", |
| 2809 | + {{0, 3, |
| 2810 | + "A valid JSON document must be either an array or an object value."}}, |
| 2811 | + "* Line 1, Column 1\n" |
| 2812 | + " A valid JSON document must be either an array or an object value.\n"); |
2743 | 2813 | }
|
2744 | 2814 |
|
2745 | 2815 | JSONTEST_FIXTURE_LOCAL(ReaderTest, parseChineseWithOneError) {
|
2746 |
| - Json::Reader reader; |
2747 |
| - Json::Value root; |
2748 |
| - bool ok = reader.parse("{ \"pr佐藤erty\" :: \"value\" }", root); |
2749 |
| - JSONTEST_ASSERT(!ok); |
2750 |
| - JSONTEST_ASSERT(reader.getFormattedErrorMessages() == |
2751 |
| - "* Line 1, Column 19\n Syntax error: value, object or array " |
2752 |
| - "expected.\n"); |
2753 |
| - std::vector<Json::Reader::StructuredError> errors = |
2754 |
| - reader.getStructuredErrors(); |
2755 |
| - JSONTEST_ASSERT(errors.size() == 1); |
2756 |
| - JSONTEST_ASSERT(errors.at(0).offset_start == 18); |
2757 |
| - JSONTEST_ASSERT(errors.at(0).offset_limit == 19); |
2758 |
| - JSONTEST_ASSERT(errors.at(0).message == |
2759 |
| - "Syntax error: value, object or array expected."); |
| 2816 | + // \u4f50\u85e4 佐藤 |
| 2817 | + checkParse(R"({ "pr)" |
| 2818 | + "佐藤" |
| 2819 | + R"(erty" :: "value" })", |
| 2820 | + {{18, 19, "Syntax error: value, object or array expected."}}, |
| 2821 | + "* Line 1, Column 19\n Syntax error: value, object or array " |
| 2822 | + "expected.\n"); |
2760 | 2823 | }
|
2761 | 2824 |
|
2762 | 2825 | JSONTEST_FIXTURE_LOCAL(ReaderTest, parseWithDetailError) {
|
2763 |
| - Json::Reader reader; |
2764 |
| - Json::Value root; |
2765 |
| - bool ok = reader.parse("{ \"property\" : \"v\\alue\" }", root); |
2766 |
| - JSONTEST_ASSERT(!ok); |
2767 |
| - JSONTEST_ASSERT(reader.getFormattedErrorMessages() == |
2768 |
| - "* Line 1, Column 16\n Bad escape sequence in string\nSee " |
2769 |
| - "Line 1, Column 20 for detail.\n"); |
2770 |
| - std::vector<Json::Reader::StructuredError> errors = |
2771 |
| - reader.getStructuredErrors(); |
2772 |
| - JSONTEST_ASSERT(errors.size() == 1); |
2773 |
| - JSONTEST_ASSERT(errors.at(0).offset_start == 15); |
2774 |
| - JSONTEST_ASSERT(errors.at(0).offset_limit == 23); |
2775 |
| - JSONTEST_ASSERT(errors.at(0).message == "Bad escape sequence in string"); |
| 2826 | + checkParse(R"({ "property" : "v\alue" })", |
| 2827 | + {{15, 23, "Bad escape sequence in string"}}, |
| 2828 | + "* Line 1, Column 16\n" |
| 2829 | + " Bad escape sequence in string\n" |
| 2830 | + "See Line 1, Column 20 for detail.\n"); |
2776 | 2831 | }
|
2777 | 2832 |
|
2778 | 2833 | JSONTEST_FIXTURE_LOCAL(ReaderTest, pushErrorTest) {
|
2779 |
| - Json::Reader reader; |
2780 |
| - Json::Value root; |
2781 |
| - { |
2782 |
| - bool ok = reader.parse("{ \"AUTHOR\" : 123 }", root); |
2783 |
| - JSONTEST_ASSERT(ok); |
2784 |
| - if (!root["AUTHOR"].isString()) { |
2785 |
| - ok = reader.pushError(root["AUTHOR"], "AUTHOR must be a string"); |
2786 |
| - } |
2787 |
| - JSONTEST_ASSERT(ok); |
2788 |
| - JSONTEST_ASSERT(reader.getFormattedErrorMessages() == |
2789 |
| - "* Line 1, Column 14\n" |
2790 |
| - " AUTHOR must be a string\n"); |
| 2834 | + checkParse(R"({ "AUTHOR" : 123 })"); |
| 2835 | + if (!root["AUTHOR"].isString()) { |
| 2836 | + JSONTEST_ASSERT( |
| 2837 | + reader->pushError(root["AUTHOR"], "AUTHOR must be a string")); |
2791 | 2838 | }
|
2792 |
| - { |
2793 |
| - bool ok = reader.parse("{ \"AUTHOR\" : 123 }", root); |
2794 |
| - JSONTEST_ASSERT(ok); |
2795 |
| - if (!root["AUTHOR"].isString()) { |
2796 |
| - ok = reader.pushError(root["AUTHOR"], "AUTHOR must be a string", |
2797 |
| - root["AUTHOR"]); |
2798 |
| - } |
2799 |
| - JSONTEST_ASSERT(ok); |
2800 |
| - JSONTEST_ASSERT(reader.getFormattedErrorMessages() == |
2801 |
| - "* Line 1, Column 14\n" |
2802 |
| - " AUTHOR must be a string\n" |
2803 |
| - "See Line 1, Column 14 for detail.\n"); |
| 2839 | + JSONTEST_ASSERT_STRING_EQUAL(reader->getFormattedErrorMessages(), |
| 2840 | + "* Line 1, Column 14\n" |
| 2841 | + " AUTHOR must be a string\n"); |
| 2842 | + |
| 2843 | + checkParse(R"({ "AUTHOR" : 123 })"); |
| 2844 | + if (!root["AUTHOR"].isString()) { |
| 2845 | + JSONTEST_ASSERT(reader->pushError(root["AUTHOR"], "AUTHOR must be a string", |
| 2846 | + root["AUTHOR"])); |
2804 | 2847 | }
|
| 2848 | + JSONTEST_ASSERT_STRING_EQUAL(reader->getFormattedErrorMessages(), |
| 2849 | + "* Line 1, Column 14\n" |
| 2850 | + " AUTHOR must be a string\n" |
| 2851 | + "See Line 1, Column 14 for detail.\n"); |
2805 | 2852 | }
|
2806 | 2853 |
|
2807 | 2854 | struct CharReaderTest : JsonTest::TestCase {};
|
|
0 commit comments