add a test for iterative parsing

This commit is contained in:
Sven M. Hallberg 2015-09-03 19:58:39 +02:00
parent 0231dc141e
commit 10fde548ad
2 changed files with 75 additions and 0 deletions

View file

@ -443,6 +443,37 @@ static void test_rightrec(gconstpointer backend) {
g_check_parse_match(rr_, (HParserBackend)GPOINTER_TO_INT(backend), "aaa", 3, "(u0x61 (u0x61 (u0x61)))");
}
static void test_iterative(gconstpointer backend) {
HParserBackend be = (HParserBackend)GPOINTER_TO_INT(backend);
HParser *p;
p = h_token((uint8_t*)"foobar", 6);
g_check_parse_chunks_match(p, be, "foo",3, "bar",3, "<66.6f.6f.62.61.72>");
g_check_parse_chunks_match(p, be, "foo",3, "barbaz",6, "<66.6f.6f.62.61.72>");
g_check_parse_chunks_failed(p, be, "fou",3, "bar",3);
g_check_parse_chunks_failed(p, be, "foo",3, "par",3);
g_check_parse_chunks_failed(p, be, "foo",3, "baz",3);
p = h_sequence(h_ch('f'), h_token((uint8_t*)"ooba", 4), h_ch('r'), NULL);
g_check_parse_chunks_match(p, be, "foo",3, "bar",3, "(u0x66 <6f.6f.62.61> u0x72)");
g_check_parse_chunks_match(p, be, "foo",3, "barbaz",6, "(u0x66 <6f.6f.62.61> u0x72)");
g_check_parse_chunks_failed(p, be, "fou",3, "bar",3);
g_check_parse_chunks_failed(p, be, "foo",3, "par",3);
g_check_parse_chunks_failed(p, be, "foo",3, "baz",3);
p = h_choice(h_token((uint8_t*)"foobar", 6),
h_token((uint8_t*)"foopar", 6), NULL);
g_check_parse_chunks_match(p, be, "foo",3, "bar",3, "<66.6f.6f.62.61.72>");
g_check_parse_chunks_match(p, be, "foo",3, "barbaz",6, "<66.6f.6f.62.61.72>");
g_check_parse_chunks_match(p, be, "foo",3, "par",3, "<66.6f.6f.70.61.72>");
g_check_parse_chunks_failed(p, be, "fou",3, "bar",3);
g_check_parse_chunks_failed(p, be, "foo",3, "baz",3);
g_check_parse_chunks_match(p, be, "foobar",6, "",0, "<66.6f.6f.62.61.72>");
g_check_parse_chunks_match(p, be, "",0, "foobar",6, "<66.6f.6f.62.61.72>");
g_check_parse_chunks_failed(p, be, "foo",3, "",0);
g_check_parse_chunks_failed(p, be, "",0, "foo",3);
}
static void test_ambiguous(gconstpointer backend) {
HParser *d_ = h_ch('d');
HParser *p_ = h_ch('+');
@ -691,6 +722,7 @@ void register_parser_tests(void) {
g_test_add_data_func("/core/parser/llk/ignore", GINT_TO_POINTER(PB_LLk), test_ignore);
//g_test_add_data_func("/core/parser/llk/leftrec", GINT_TO_POINTER(PB_LLk), test_leftrec);
g_test_add_data_func("/core/parser/llk/rightrec", GINT_TO_POINTER(PB_LLk), test_rightrec);
g_test_add_data_func("/core/parser/llk/iterative", GINT_TO_POINTER(PB_LLk), test_iterative);
g_test_add_data_func("/core/parser/regex/token", GINT_TO_POINTER(PB_REGULAR), test_token);
g_test_add_data_func("/core/parser/regex/ch", GINT_TO_POINTER(PB_REGULAR), test_ch);

View file

@ -145,6 +145,49 @@
} \
} while(0)
#define g_check_parse_chunks_failed(parser, backend, chunk1, c1_len, chunk2, c2_len) do { \
int skip = h_compile((HParser *)(parser), (HParserBackend)backend, NULL); \
HSuspendedParser *s = h_parse_start(parser); \
if(skip || !s) { \
g_test_message("Backend not applicable, skipping test"); \
break; \
} \
h_parse_chunk(s, (const uint8_t*)chunk1, c1_len); \
h_parse_chunk(s, (const uint8_t*)chunk2, c2_len); \
const HParseResult *res = h_parse_finish(s); \
if (NULL != res) { \
g_test_message("Check failed: shouldn't have succeeded, but did"); \
g_test_fail(); \
} \
} while(0)
#define g_check_parse_chunks_match(parser, backend, chunk1, c1_len, chunk2, c2_len, result) do { \
int skip = h_compile((HParser *)(parser), (HParserBackend) backend, NULL); \
HSuspendedParser *s = h_parse_start(parser); \
if(skip || !s) { \
g_test_message("Backend not applicable, skipping test"); \
break; \
} \
h_parse_chunk(s, (const uint8_t*)chunk1, c1_len); \
h_parse_chunk(s, (const uint8_t*)chunk2, c2_len); \
HParseResult *res = h_parse_finish(s); \
if (!res) { \
g_test_message("Parse failed on line %d", __LINE__); \
g_test_fail(); \
} else { \
char* cres = h_write_result_unamb(res->ast); \
g_check_string(cres, ==, result); \
(&system_allocator)->free(&system_allocator, cres); \
HArenaStats stats; \
h_allocator_stats(res->arena, &stats); \
g_test_message("Parse used %zd bytes, wasted %zd bytes. " \
"Inefficiency: %5f%%", \
stats.used, stats.wasted, \
stats.wasted * 100. / (stats.used+stats.wasted)); \
h_delete_arena(res->arena); \
} \
} while(0)
#define g_check_hashtable_present(table, key) do { \
if(!h_hashtable_present(table, key)) { \
g_test_message("Check failed: key should have been in table, but wasn't"); \