/* retoor */ #include "../include/loreg.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) #define ASSERT_MATCH(pattern, text) do { \ loreg_error_t err; \ loreg_regex_t *re = loreg_compile(pattern, &err); \ ASSERT(re != NULL); \ loreg_match_t result; \ ASSERT(loreg_search(re, text, &result) == true); \ loreg_free(re); \ } while(0) #define ASSERT_NO_MATCH(pattern, text) do { \ loreg_error_t err; \ loreg_regex_t *re = loreg_compile(pattern, &err); \ ASSERT(re != NULL); \ loreg_match_t result; \ ASSERT(loreg_search(re, text, &result) == false); \ loreg_free(re); \ } while(0) TEST(simple_char) { ASSERT_MATCH("a", "a"); ASSERT_MATCH("a", "bab"); ASSERT_NO_MATCH("a", "bcd"); } TEST(concat) { ASSERT_MATCH("ab", "ab"); ASSERT_MATCH("ab", "xaby"); ASSERT_NO_MATCH("ab", "ba"); } TEST(alternation) { ASSERT_MATCH("a|b", "a"); ASSERT_MATCH("a|b", "b"); ASSERT_MATCH("cat|dog", "cat"); ASSERT_MATCH("cat|dog", "dog"); ASSERT_NO_MATCH("cat|dog", "rat"); } TEST(star) { ASSERT_MATCH("a*", ""); ASSERT_MATCH("a*", "a"); ASSERT_MATCH("a*", "aaa"); ASSERT_MATCH("a*b", "b"); ASSERT_MATCH("a*b", "ab"); ASSERT_MATCH("a*b", "aaab"); } TEST(plus) { ASSERT_NO_MATCH("a+", ""); ASSERT_MATCH("a+", "a"); ASSERT_MATCH("a+", "aaa"); ASSERT_MATCH("a+b", "ab"); ASSERT_MATCH("a+b", "aaab"); } TEST(question) { ASSERT_MATCH("a?", ""); ASSERT_MATCH("a?", "a"); ASSERT_MATCH("a?b", "b"); ASSERT_MATCH("a?b", "ab"); } TEST(dot) { ASSERT_MATCH(".", "a"); ASSERT_MATCH(".", "x"); ASSERT_MATCH("a.b", "aab"); ASSERT_MATCH("a.b", "axb"); ASSERT_NO_MATCH("a.b", "ab"); } TEST(bracket_simple) { ASSERT_MATCH("[abc]", "a"); ASSERT_MATCH("[abc]", "b"); ASSERT_MATCH("[abc]", "c"); ASSERT_NO_MATCH("[abc]", "d"); } TEST(bracket_range) { ASSERT_MATCH("[a-z]", "a"); ASSERT_MATCH("[a-z]", "m"); ASSERT_MATCH("[a-z]", "z"); ASSERT_NO_MATCH("[a-z]", "A"); ASSERT_NO_MATCH("[a-z]", "0"); } TEST(bracket_negated) { ASSERT_NO_MATCH("[^abc]", "a"); ASSERT_NO_MATCH("[^abc]", "b"); ASSERT_MATCH("[^abc]", "d"); ASSERT_MATCH("[^abc]", "x"); } TEST(group) { ASSERT_MATCH("(ab)", "ab"); ASSERT_MATCH("(ab)+", "abab"); ASSERT_MATCH("(a|b)+", "abba"); } TEST(anchors) { ASSERT_MATCH("^a", "a"); ASSERT_MATCH("^a", "abc"); ASSERT_NO_MATCH("^a", "ba"); ASSERT_MATCH("a$", "a"); ASSERT_MATCH("a$", "ba"); ASSERT_NO_MATCH("a$", "ab"); ASSERT_MATCH("^abc$", "abc"); ASSERT_NO_MATCH("^abc$", "xabc"); ASSERT_NO_MATCH("^abc$", "abcx"); } TEST(quantifier_exact) { ASSERT_MATCH("a{3}", "aaa"); ASSERT_MATCH("a{3}", "aaaa"); ASSERT_NO_MATCH("a{3}", "aa"); } TEST(quantifier_range) { ASSERT_MATCH("a{2,4}", "aa"); ASSERT_MATCH("a{2,4}", "aaa"); ASSERT_MATCH("a{2,4}", "aaaa"); ASSERT_NO_MATCH("a{2,4}", "a"); } TEST(quantifier_open) { ASSERT_MATCH("a{2,}", "aa"); ASSERT_MATCH("a{2,}", "aaaaa"); ASSERT_NO_MATCH("a{2,}", "a"); } TEST(class_digit) { ASSERT_MATCH("\\d", "0"); ASSERT_MATCH("\\d", "9"); ASSERT_MATCH("\\d+", "123"); ASSERT_NO_MATCH("\\d", "a"); } TEST(class_word) { ASSERT_MATCH("\\w", "a"); ASSERT_MATCH("\\w", "Z"); ASSERT_MATCH("\\w", "0"); ASSERT_MATCH("\\w", "_"); ASSERT_NO_MATCH("\\w", " "); ASSERT_NO_MATCH("\\w", "-"); } TEST(class_space) { ASSERT_MATCH("\\s", " "); ASSERT_MATCH("\\s", "\t"); ASSERT_MATCH("\\s", "\n"); ASSERT_NO_MATCH("\\s", "a"); } TEST(class_negated) { ASSERT_NO_MATCH("\\D", "0"); ASSERT_MATCH("\\D", "a"); ASSERT_NO_MATCH("\\W", "a"); ASSERT_MATCH("\\W", " "); ASSERT_NO_MATCH("\\S", " "); ASSERT_MATCH("\\S", "a"); } TEST(escape_sequences) { ASSERT_MATCH("\\.", "."); ASSERT_NO_MATCH("\\.", "a"); ASSERT_MATCH("\\*", "*"); ASSERT_MATCH("\\+", "+"); ASSERT_MATCH("\\?", "?"); } TEST(complex_email) { ASSERT_MATCH("[a-z]+@[a-z]+\\.[a-z]+", "test@example.com"); ASSERT_NO_MATCH("[a-z]+@[a-z]+\\.[a-z]+", "invalid"); } TEST(complex_phone) { ASSERT_MATCH("\\d{3}-\\d{3}-\\d{4}", "123-456-7890"); ASSERT_NO_MATCH("\\d{3}-\\d{3}-\\d{4}", "123-456-789"); } TEST(complex_url) { ASSERT_MATCH("https?://[a-z]+\\.[a-z]+", "http://example.com"); ASSERT_MATCH("https?://[a-z]+\\.[a-z]+", "https://example.com"); } TEST(group_capture) { loreg_error_t err; loreg_regex_t *re = loreg_compile("(\\d+)-(\\d+)", &err); ASSERT(re != NULL); loreg_match_t result; ASSERT(loreg_search(re, "123-456", &result)); ASSERT(result.group_count == 2); ASSERT(result.groups[0].matched); ASSERT(result.groups[1].matched); loreg_free(re); } TEST(nested_groups) { loreg_error_t err; loreg_regex_t *re = loreg_compile("((a)(b))", &err); ASSERT(re != NULL); loreg_match_t result; ASSERT(loreg_search(re, "ab", &result)); ASSERT(result.group_count == 3); loreg_free(re); } TEST(empty_pattern) { loreg_error_t err; loreg_regex_t *re = loreg_compile("", &err); ASSERT(re != NULL); loreg_match_t result; ASSERT(loreg_match(re, "anything", &result)); loreg_free(re); } TEST(match_position) { loreg_error_t err; loreg_regex_t *re = loreg_compile("test", &err); ASSERT(re != NULL); loreg_match_t result; ASSERT(loreg_search(re, "xxxtestyyy", &result)); ASSERT(result.match_start == 3); ASSERT(result.match_end == 7); loreg_free(re); } int main(void) { printf("matcher tests:\n"); RUN_TEST(simple_char); RUN_TEST(concat); RUN_TEST(alternation); RUN_TEST(star); RUN_TEST(plus); RUN_TEST(question); RUN_TEST(dot); RUN_TEST(bracket_simple); RUN_TEST(bracket_range); RUN_TEST(bracket_negated); RUN_TEST(group); RUN_TEST(anchors); RUN_TEST(quantifier_exact); RUN_TEST(quantifier_range); RUN_TEST(quantifier_open); RUN_TEST(class_digit); RUN_TEST(class_word); RUN_TEST(class_space); RUN_TEST(class_negated); RUN_TEST(escape_sequences); RUN_TEST(complex_email); RUN_TEST(complex_phone); RUN_TEST(complex_url); RUN_TEST(group_capture); RUN_TEST(nested_groups); RUN_TEST(empty_pattern); RUN_TEST(match_position); printf("\nmatcher: %d passed, %d failed\n", tests_passed, tests_failed); return tests_failed > 0 ? 1 : 0; }