From 46164756f53718981276a50ee7e24487b312c935 Mon Sep 17 00:00:00 2001 From: "Sven M. Hallberg" <pesco@khjk.org> Date: Thu, 22 Sep 2022 15:46:22 +0200 Subject: [PATCH] add a test for using dummy iterative with multiple chunks The test fails because currently parsers that fail may leave the input stream in any indeterminate state. Parsers that backtrack (h_many, h_choice, h_optional, etc.) do not propagate an overrun of their subordinate parsers to h_packrat_parse_chunk where we would detect it and fail. --- src/t_parser.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/t_parser.c b/src/t_parser.c index de273c95..37027e80 100644 --- a/src/t_parser.c +++ b/src/t_parser.c @@ -542,6 +542,34 @@ static void test_iterative_single(gconstpointer backend) { g_check_parse_chunk_failed(p, be, "fuo",3); } +// this test applies to backends that support the iterative API, but not actual +// chunked operation. in such cases, passing multiple chunks should fail the +// parse rather than treating the end of the first chunk as the end of input. +static void test_iterative_dummy(gconstpointer backend) { + HParserBackend be = (HParserBackend)GPOINTER_TO_INT(backend); + HParser *p; + + HParser *x = h_ch('x'); + HParser *y = h_ch('y'); + HParser *e = h_epsilon_p(); + + p = h_many(x); + g_check_parse_chunks_failed(p, be, "xxx",3, "xxx",3); + g_check_parse_chunks_failed(p, be, "xxx",3, "",0); + + p = h_optional(x); + g_check_parse_chunks_failed(p, be, "",0, "xxx",3); + + p = h_choice(x, e, NULL); + g_check_parse_chunks_failed(p, be, "",0, "xxx",3); + + // these are ok because the parse succeeds without overrun. + p = h_choice(e, x, NULL); + g_check_parse_chunks_match(p, be, "",0, "xxx",3, "NULL"); + p = h_choice(y, x, NULL); + g_check_parse_chunks_match(p, be, "y",1, "xxx",3, "u0x79"); +} + static void test_iterative_multi(gconstpointer backend) { HParserBackend be = (HParserBackend)GPOINTER_TO_INT(backend); HParser *p; @@ -969,6 +997,7 @@ void register_parser_tests(void) { g_test_add_data_func("/core/parser/packrat/result_length", GINT_TO_POINTER(PB_PACKRAT), test_result_length); //g_test_add_data_func("/core/parser/packrat/token_position", GINT_TO_POINTER(PB_PACKRAT), test_token_position); g_test_add_data_func("/core/parser/packrat/iterative/single", GINT_TO_POINTER(PB_PACKRAT), test_iterative_single); + g_test_add_data_func("/core/parser/packrat/iterative/dummy", GINT_TO_POINTER(PB_PACKRAT), test_iterative_dummy); // XXX remove when multi-chunk works //g_test_add_data_func("/core/parser/packrat/iterative/multi", GINT_TO_POINTER(PB_PACKRAT), test_iterative_multi); //g_test_add_data_func("/core/parser/packrat/iterative/lookahead", GINT_TO_POINTER(PB_PACKRAT), test_iterative_lookahead); //g_test_add_data_func("/core/parser/packrat/iterative/result_length", GINT_TO_POINTER(PB_PACKRAT), test_iterative_result_length); -- GitLab