1#include "tests.h"
  2
  3void test_json_parser(testing &t) {
  4    // Test parsing a simple JSON object
  5    t.test("simple JSON object parsing", [](testing &t) {
  6        auto json = build_peg_parser([](common_peg_parser_builder & p) { return p.json(); });
  7
  8        std::string    input = R"({"name": "test", "value": 42, "flag": true})";
  9        common_peg_parse_context ctx(input);
 10
 11        auto result = json.parse(ctx);
 12
 13        t.assert_equal("result_is_success", true, result.success());
 14        t.assert_equal("result_end", input.size(), result.end);
 15    });
 16
 17    // Test parsing a JSON array with mixed types
 18    t.test("JSON array with mixed types", [](testing &t) {
 19        auto json = build_peg_parser([](common_peg_parser_builder & p) { return p.json(); });
 20
 21        std::string    input = R"([1, "hello", true, null, 3.14])";
 22        common_peg_parse_context ctx(input);
 23
 24        auto result = json.parse(ctx);
 25
 26        t.assert_equal("result_is_success", true, result.success());
 27        t.assert_equal("result_end", input.size(), result.end);
 28    });
 29
 30    // Test parsing nested JSON with objects and arrays
 31    t.test("nested JSON with objects and arrays", [](testing &t) {
 32        auto json = build_peg_parser([](common_peg_parser_builder & p) { return p.json(); });
 33
 34        std::string input =
 35            R"({"users": [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}], "count": 2, "metadata": {"version": "1.0", "tags": ["admin", "user"]}})";
 36        common_peg_parse_context ctx(input);
 37
 38        auto result = json.parse(ctx);
 39
 40        t.assert_equal("result_is_success", true, result.success());
 41        t.assert_equal("result_end", input.size(), result.end);
 42    });
 43
 44    // Test need_more_input() parsing - incomplete object
 45    t.test("need_more_input() parsing - incomplete object", [](testing &t) {
 46        auto json = build_peg_parser([](common_peg_parser_builder & p) { return p.json(); });
 47
 48        std::string    input = R"({"name": "test", "value": )";
 49        common_peg_parse_context ctx(input, true);
 50
 51        auto result = json.parse(ctx);
 52
 53        t.assert_equal("result_is_need_more_input", true, result.need_more_input());
 54    });
 55
 56    // Test need_more_input() parsing - incomplete array
 57    t.test("need_more_input() parsing - incomplete array", [](testing &t) {
 58        auto json = build_peg_parser([](common_peg_parser_builder & p) { return p.json(); });
 59
 60        std::string    input = R"([1, 2, 3, )";
 61        common_peg_parse_context ctx(input, true);
 62
 63        auto result = json.parse(ctx);
 64
 65        t.assert_equal("result_is_need_more_input", true, result.need_more_input());
 66    });
 67
 68    // Test need_more_input() parsing - incomplete nested structure
 69    t.test("need_more_input() parsing - incomplete nested structure", [](testing &t) {
 70        auto json = build_peg_parser([](common_peg_parser_builder & p) { return p.json(); });
 71
 72        std::string    input = R"({"data": {"nested": )";
 73        common_peg_parse_context ctx(input, true);
 74
 75        auto result = json.parse(ctx);
 76
 77        t.assert_equal("result_is_need_more_input", true, result.need_more_input());
 78    });
 79
 80    t.test("object member", [](testing &t) {
 81        auto parser = build_peg_parser([](common_peg_parser_builder & p) {
 82            return p.json_member("name", "\"" + p.chars("[a-z]") + "\"");
 83        });
 84
 85        t.test("success", [&](testing &t) {
 86            std::string input = R"("name": "bob")";
 87            common_peg_parse_context ctx(input, false);
 88
 89            auto result = parser.parse(ctx);
 90            t.assert_true("success", result.success());
 91        });
 92
 93        t.test("partial", [&](testing &t) {
 94            std::string input = R"("name": "bo)";
 95            common_peg_parse_context ctx(input, true);
 96
 97            auto result = parser.parse(ctx);
 98            t.assert_true("need more input", result.need_more_input());
 99        });
100
101        t.test("failed", [&](testing &t) {
102            std::string input = R"([])";
103            common_peg_parse_context ctx(input, false);
104
105            auto result = parser.parse(ctx);
106            t.assert_true("fail", result.fail());
107        });
108    });
109}