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