From bbd70800c81a65576d6bd6dc8f46aa293ba5aa9d Mon Sep 17 00:00:00 2001 From: ochafik Date: Mon, 18 Mar 2024 00:34:02 +0000 Subject: [PATCH] json: improve grammar parsing failures --- tests/test-json-schema-to-grammar.cpp | 50 +++++++++++++++++---------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/tests/test-json-schema-to-grammar.cpp b/tests/test-json-schema-to-grammar.cpp index 87b5b655f..d770f07de 100755 --- a/tests/test-json-schema-to-grammar.cpp +++ b/tests/test-json-schema-to-grammar.cpp @@ -30,29 +30,37 @@ struct TestCase { TestCaseStatus expected_status; string name; string schema; - string expected; + string expected_grammar; - void verify(const string& actual, bool parse = false) const { - if (trim(actual) != trim(expected)) { - cerr << "#" << endl; - cerr << "# Test '" << name.c_str() << "' failed." << endl; - cerr << "#" << endl; - cerr << schema.c_str() << endl; - cerr << "# EXPECTED:\n" << expected.c_str() << endl; - cerr << "# ACTUAL:\n" << actual.c_str() << endl; + void _print_failure_header() const { + cerr << "#" << endl; + cerr << "# Test '" << name.c_str() << "' failed." << endl; + cerr << "#" << endl; + cerr << schema.c_str() << endl; + } + void verify(const string& actual_grammar) const { + if (trim(actual_grammar) != trim(expected_grammar)) { + _print_failure_header(); + cerr << "# EXPECTED:\n" << expected_grammar.c_str() << endl; + cerr << "# ACTUAL:\n" << actual_grammar.c_str() << endl; assert(false); } - if (parse) { - auto state = grammar_parser::parse(actual.c_str()); - assert(state.symbol_ids.find("root") != state.symbol_ids.end()); + } + void verify_expectation_parseable() const { + try { + auto state = grammar_parser::parse(expected_grammar.c_str()); + if (state.symbol_ids.find("root") == state.symbol_ids.end()) { + throw runtime_error("Grammar failed to parse:\n" + expected_grammar); + } + } catch (const runtime_error& ex) { + _print_failure_header(); + cerr << "# GRAMMAR ERROR: " << ex.what() << endl; + assert(false); } } void verify_status(TestCaseStatus status) const { if (status != expected_status) { - cerr << "#" << endl; - cerr << "# Test '" << name.c_str() << "' failed." << endl; - cerr << "#" << endl; - cerr << schema.c_str() << endl; + _print_failure_header(); cerr << "# EXPECTED STATUS: " << (expected_status == SUCCESS ? "SUCCESS" : "FAILURE") << endl; cerr << "# ACTUAL STATUS: " << (status == SUCCESS ? "SUCCESS" : "FAILURE") << endl; assert(false); @@ -612,7 +620,7 @@ static void test_all(const string& lang, std::function ru SUCCESS, "mix of allOf, anyOf and $ref (similar to https://json.schemastore.org/tsconfig.json)", R"""({ - "allOf": [ + "allOf": [ {"$ref": "#/definitions/foo"}, {"$ref": "#/definitions/bar"}, { @@ -700,8 +708,7 @@ static void test_all(const string& lang, std::function ru int main() { test_all("C++", [](const TestCase& tc) { try { - // We only try and parse the grammar output in the C++ test. - tc.verify(json_schema_to_grammar(nlohmann::json::parse(tc.schema)), /* parse= */ true); + tc.verify(json_schema_to_grammar(nlohmann::json::parse(tc.schema))); tc.verify_status(SUCCESS); } catch (const runtime_error& ex) { cerr << "Error: " << ex.what() << endl; @@ -720,4 +727,9 @@ int main() { "node ./tests/run-json-schema-to-grammar.mjs test-json-schema-input.tmp > test-grammar-output.tmp") == 0 ? SUCCESS : FAILURE); tc.verify(read("test-grammar-output.tmp")); }); + test_all("Check Expectations Validity", [](const TestCase& tc) { + if (tc.expected_status == SUCCESS) { + tc.verify_expectation_parseable(); + } + }); }