/* retoor */ #include "../include/parser.h" #include #include static int tests_passed = 0; static int tests_failed = 0; #define TEST(name) static void test_##name(void) #define RUN_TEST(name) do { \ printf(" %s... ", #name); \ test_##name(); \ printf("ok\n"); \ tests_passed++; \ } while(0) #define ASSERT(cond) do { \ if (!(cond)) { \ printf("FAILED at line %d: %s\n", __LINE__, #cond); \ tests_failed++; \ return; \ } \ } while(0) TEST(single_char) { parser_t parser; parser_init(&parser, "a"); ast_node_t *ast = parser_parse(&parser); ASSERT(ast != NULL); ASSERT(ast->type == AST_CHAR); ASSERT(ast->value == 'a'); ast_free(ast); } TEST(concat) { parser_t parser; parser_init(&parser, "ab"); ast_node_t *ast = parser_parse(&parser); ASSERT(ast != NULL); ASSERT(ast->type == AST_CONCAT); ASSERT(ast->left->type == AST_CHAR); ASSERT(ast->left->value == 'a'); ASSERT(ast->right->type == AST_CHAR); ASSERT(ast->right->value == 'b'); ast_free(ast); } TEST(alternation) { parser_t parser; parser_init(&parser, "a|b"); ast_node_t *ast = parser_parse(&parser); ASSERT(ast != NULL); ASSERT(ast->type == AST_ALTER); ASSERT(ast->left->type == AST_CHAR); ASSERT(ast->left->value == 'a'); ASSERT(ast->right->type == AST_CHAR); ASSERT(ast->right->value == 'b'); ast_free(ast); } TEST(star) { parser_t parser; parser_init(&parser, "a*"); ast_node_t *ast = parser_parse(&parser); ASSERT(ast != NULL); ASSERT(ast->type == AST_STAR); ASSERT(ast->left->type == AST_CHAR); ASSERT(ast->left->value == 'a'); ast_free(ast); } TEST(plus) { parser_t parser; parser_init(&parser, "a+"); ast_node_t *ast = parser_parse(&parser); ASSERT(ast != NULL); ASSERT(ast->type == AST_PLUS); ASSERT(ast->left->type == AST_CHAR); ASSERT(ast->left->value == 'a'); ast_free(ast); } TEST(question) { parser_t parser; parser_init(&parser, "a?"); ast_node_t *ast = parser_parse(&parser); ASSERT(ast != NULL); ASSERT(ast->type == AST_QUESTION); ASSERT(ast->left->type == AST_CHAR); ASSERT(ast->left->value == 'a'); ast_free(ast); } TEST(group) { parser_t parser; parser_init(&parser, "(ab)"); ast_node_t *ast = parser_parse(&parser); ASSERT(ast != NULL); ASSERT(ast->type == AST_GROUP); ASSERT(ast->group_id == 0); ASSERT(ast->left->type == AST_CONCAT); ast_free(ast); } TEST(dot) { parser_t parser; parser_init(&parser, "."); ast_node_t *ast = parser_parse(&parser); ASSERT(ast != NULL); ASSERT(ast->type == AST_DOT); ast_free(ast); } TEST(anchors) { parser_t parser; parser_init(&parser, "^a$"); ast_node_t *ast = parser_parse(&parser); ASSERT(ast != NULL); ASSERT(ast->type == AST_CONCAT); ast_free(ast); } TEST(bracket_simple) { parser_t parser; parser_init(&parser, "[abc]"); ast_node_t *ast = parser_parse(&parser); ASSERT(ast != NULL); ASSERT(ast->type == AST_BRACKET); ASSERT(ast->bracket != NULL); ASSERT(ast->bracket->count == 3); ast_free(ast); } TEST(bracket_range) { parser_t parser; parser_init(&parser, "[a-z]"); ast_node_t *ast = parser_parse(&parser); ASSERT(ast != NULL); ASSERT(ast->type == AST_BRACKET); ASSERT(ast->bracket != NULL); ASSERT(ast->bracket->count == 1); ASSERT(ast->bracket->ranges[0].start == 'a'); ASSERT(ast->bracket->ranges[0].end == 'z'); ast_free(ast); } TEST(bracket_negated) { parser_t parser; parser_init(&parser, "[^a]"); ast_node_t *ast = parser_parse(&parser); ASSERT(ast != NULL); ASSERT(ast->type == AST_BRACKET); ASSERT(ast->bracket->negated == true); ast_free(ast); } TEST(quantifier_exact) { parser_t parser; parser_init(&parser, "a{3}"); ast_node_t *ast = parser_parse(&parser); ASSERT(ast != NULL); ASSERT(ast->type == AST_QUANTIFIER); ASSERT(ast->quant.min == 3); ASSERT(ast->quant.max == 3); ast_free(ast); } TEST(quantifier_range) { parser_t parser; parser_init(&parser, "a{2,5}"); ast_node_t *ast = parser_parse(&parser); ASSERT(ast != NULL); ASSERT(ast->type == AST_QUANTIFIER); ASSERT(ast->quant.min == 2); ASSERT(ast->quant.max == 5); ast_free(ast); } TEST(quantifier_open) { parser_t parser; parser_init(&parser, "a{2,}"); ast_node_t *ast = parser_parse(&parser); ASSERT(ast != NULL); ASSERT(ast->type == AST_QUANTIFIER); ASSERT(ast->quant.min == 2); ASSERT(ast->quant.max == -1); ast_free(ast); } TEST(character_class_digit) { parser_t parser; parser_init(&parser, "\\d"); ast_node_t *ast = parser_parse(&parser); ASSERT(ast != NULL); ASSERT(ast->type == AST_CLASS_DIGIT); ast_free(ast); } TEST(character_class_word) { parser_t parser; parser_init(&parser, "\\w"); ast_node_t *ast = parser_parse(&parser); ASSERT(ast != NULL); ASSERT(ast->type == AST_CLASS_WORD); ast_free(ast); } TEST(complex_pattern) { parser_t parser; parser_init(&parser, "^([a-z]+)@([a-z]+)\\.([a-z]{2,})$"); ast_node_t *ast = parser_parse(&parser); ASSERT(ast != NULL); ASSERT(parser_get_error(&parser) == LOREG_OK); ast_free(ast); } TEST(unbalanced_paren) { parser_t parser; parser_init(&parser, "(abc"); ast_node_t *ast = parser_parse(&parser); ASSERT(ast == NULL || parser_get_error(&parser) == LOREG_ERR_UNBALANCED_PAREN); ast_free(ast); } TEST(non_greedy) { parser_t parser; parser_init(&parser, "a*?"); ast_node_t *ast = parser_parse(&parser); ASSERT(ast != NULL); ASSERT(ast->type == AST_STAR); ASSERT(ast->quant.greedy == false); ast_free(ast); } int main(void) { printf("parser tests:\n"); RUN_TEST(single_char); RUN_TEST(concat); RUN_TEST(alternation); RUN_TEST(star); RUN_TEST(plus); RUN_TEST(question); RUN_TEST(group); RUN_TEST(dot); RUN_TEST(anchors); RUN_TEST(bracket_simple); RUN_TEST(bracket_range); RUN_TEST(bracket_negated); RUN_TEST(quantifier_exact); RUN_TEST(quantifier_range); RUN_TEST(quantifier_open); RUN_TEST(character_class_digit); RUN_TEST(character_class_word); RUN_TEST(complex_pattern); RUN_TEST(unbalanced_paren); RUN_TEST(non_greedy); printf("\nparser: %d passed, %d failed\n", tests_passed, tests_failed); return tests_failed > 0 ? 1 : 0; }