/* retoor */ #include "../include/lorex.h" #include #include #include static int total_passed = 0; static int total_failed = 0; #define ASSERT(cond, msg) do { \ if (!(cond)) { \ printf(" FAIL: %s\n", msg); \ total_failed++; \ return; \ } \ } while(0) #define TEST(name) static void test_##name(void) #define RUN(name) do { \ test_##name(); \ total_passed++; \ } while(0) TEST(basic_literals) { lorex_error_t err; lorex_regex_t *re = lorex_compile("hello", &err); ASSERT(re != NULL, "compile hello"); lorex_match_t m; ASSERT(lorex_search(re, "hello", &m), "match hello"); ASSERT(lorex_search(re, "say hello world", &m), "search hello"); ASSERT(!lorex_search(re, "helo", &m), "no match helo"); lorex_free(re); } TEST(metacharacters) { lorex_error_t err; lorex_match_t m; lorex_regex_t *re = lorex_compile("a.c", &err); ASSERT(re != NULL, "compile a.c"); ASSERT(lorex_search(re, "abc", &m), "match abc"); ASSERT(lorex_search(re, "axc", &m), "match axc"); ASSERT(!lorex_search(re, "ac", &m), "no match ac"); lorex_free(re); re = lorex_compile("^start", &err); ASSERT(re != NULL, "compile ^start"); ASSERT(lorex_search(re, "start here", &m), "match start here"); ASSERT(!lorex_search(re, "not start", &m), "no match not start"); lorex_free(re); re = lorex_compile("end$", &err); ASSERT(re != NULL, "compile end$"); ASSERT(lorex_search(re, "the end", &m), "match the end"); ASSERT(!lorex_search(re, "end here", &m), "no match end here"); lorex_free(re); } TEST(quantifiers) { lorex_error_t err; lorex_match_t m; lorex_regex_t *re = lorex_compile("ab*c", &err); ASSERT(re != NULL, "compile ab*c"); ASSERT(lorex_search(re, "ac", &m), "match ac"); ASSERT(lorex_search(re, "abc", &m), "match abc"); ASSERT(lorex_search(re, "abbbbc", &m), "match abbbbc"); lorex_free(re); re = lorex_compile("ab+c", &err); ASSERT(re != NULL, "compile ab+c"); ASSERT(!lorex_search(re, "ac", &m), "no match ac"); ASSERT(lorex_search(re, "abc", &m), "match abc"); ASSERT(lorex_search(re, "abbbbc", &m), "match abbbbc"); lorex_free(re); re = lorex_compile("ab?c", &err); ASSERT(re != NULL, "compile ab?c"); ASSERT(lorex_search(re, "ac", &m), "match ac"); ASSERT(lorex_search(re, "abc", &m), "match abc"); ASSERT(!lorex_search(re, "abbc", &m), "no match abbc"); lorex_free(re); re = lorex_compile("a{3}", &err); ASSERT(re != NULL, "compile a{3}"); ASSERT(lorex_search(re, "aaa", &m), "match aaa"); ASSERT(!lorex_search(re, "aa", &m), "no match aa"); lorex_free(re); re = lorex_compile("a{2,4}", &err); ASSERT(re != NULL, "compile a{2,4}"); ASSERT(lorex_search(re, "aa", &m), "match aa"); ASSERT(lorex_search(re, "aaa", &m), "match aaa"); ASSERT(lorex_search(re, "aaaa", &m), "match aaaa"); ASSERT(!lorex_search(re, "a", &m), "no match a"); lorex_free(re); } TEST(character_classes) { lorex_error_t err; lorex_match_t m; lorex_regex_t *re = lorex_compile("[aeiou]", &err); ASSERT(re != NULL, "compile [aeiou]"); ASSERT(lorex_search(re, "a", &m), "match a"); ASSERT(lorex_search(re, "test", &m), "match test"); ASSERT(!lorex_search(re, "xyz", &m), "no match xyz"); lorex_free(re); re = lorex_compile("[a-z]", &err); ASSERT(re != NULL, "compile [a-z]"); ASSERT(lorex_search(re, "m", &m), "match m"); ASSERT(!lorex_search(re, "5", &m), "no match 5"); lorex_free(re); re = lorex_compile("[^0-9]", &err); ASSERT(re != NULL, "compile [^0-9]"); ASSERT(lorex_search(re, "a", &m), "match a"); ASSERT(!lorex_search(re, "5", &m), "no match 5"); lorex_free(re); re = lorex_compile("\\d", &err); ASSERT(re != NULL, "compile \\d"); ASSERT(lorex_search(re, "5", &m), "match 5"); ASSERT(!lorex_search(re, "a", &m), "no match a"); lorex_free(re); re = lorex_compile("\\w+", &err); ASSERT(re != NULL, "compile \\w+"); ASSERT(lorex_search(re, "hello_123", &m), "match hello_123"); lorex_free(re); re = lorex_compile("\\s", &err); ASSERT(re != NULL, "compile \\s"); ASSERT(lorex_search(re, " ", &m), "match space"); ASSERT(lorex_search(re, "\t", &m), "match tab"); ASSERT(!lorex_search(re, "a", &m), "no match a"); lorex_free(re); } TEST(groups) { lorex_error_t err; lorex_match_t m; lorex_regex_t *re = lorex_compile("(ab)+", &err); ASSERT(re != NULL, "compile (ab)+"); ASSERT(lorex_search(re, "ab", &m), "match ab"); ASSERT(lorex_search(re, "abab", &m), "match abab"); ASSERT(!lorex_search(re, "a", &m), "no match a"); lorex_free(re); re = lorex_compile("(\\d+)-(\\d+)", &err); ASSERT(re != NULL, "compile groups"); ASSERT(lorex_search(re, "123-456", &m), "match 123-456"); ASSERT(m.group_count == 2, "2 groups"); ASSERT(m.groups[0].matched, "group 0 matched"); ASSERT(m.groups[1].matched, "group 1 matched"); lorex_free(re); } TEST(alternation) { lorex_error_t err; lorex_match_t m; lorex_regex_t *re = lorex_compile("cat|dog", &err); ASSERT(re != NULL, "compile cat|dog"); ASSERT(lorex_search(re, "cat", &m), "match cat"); ASSERT(lorex_search(re, "dog", &m), "match dog"); ASSERT(!lorex_search(re, "rat", &m), "no match rat"); lorex_free(re); re = lorex_compile("(red|blue) car", &err); ASSERT(re != NULL, "compile (red|blue) car"); ASSERT(lorex_search(re, "red car", &m), "match red car"); ASSERT(lorex_search(re, "blue car", &m), "match blue car"); ASSERT(!lorex_search(re, "green car", &m), "no match green car"); lorex_free(re); } TEST(escapes) { lorex_error_t err; lorex_match_t m; lorex_regex_t *re = lorex_compile("1\\.5", &err); ASSERT(re != NULL, "compile 1\\.5"); ASSERT(lorex_search(re, "1.5", &m), "match 1.5"); ASSERT(!lorex_search(re, "1x5", &m), "no match 1x5"); lorex_free(re); re = lorex_compile("\\(test\\)", &err); ASSERT(re != NULL, "compile \\(test\\)"); ASSERT(lorex_search(re, "(test)", &m), "match (test)"); lorex_free(re); } TEST(real_patterns) { lorex_error_t err; lorex_match_t m; lorex_regex_t *re = lorex_compile("[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}", &err); ASSERT(re != NULL, "compile email"); ASSERT(lorex_search(re, "user@example.com", &m), "match email"); ASSERT(!lorex_search(re, "invalid", &m), "no match invalid"); lorex_free(re); re = lorex_compile("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}", &err); ASSERT(re != NULL, "compile ip"); ASSERT(lorex_search(re, "192.168.1.1", &m), "match ip"); lorex_free(re); re = lorex_compile("https?://[a-zA-Z0-9.-]+(/[a-zA-Z0-9./-]*)?", &err); ASSERT(re != NULL, "compile url"); ASSERT(lorex_search(re, "http://example.com", &m), "match http"); ASSERT(lorex_search(re, "https://example.com/path", &m), "match https"); lorex_free(re); } TEST(error_handling) { lorex_error_t err; lorex_regex_t *re = lorex_compile("(abc", &err); ASSERT(re == NULL, "unbalanced paren"); ASSERT(err == LOREX_ERR_UNBALANCED_PAREN, "correct error"); } int main(void) { printf("lorex comprehensive tests\n"); printf("========================\n\n"); clock_t start = clock(); RUN(basic_literals); RUN(metacharacters); RUN(quantifiers); RUN(character_classes); RUN(groups); RUN(alternation); RUN(escapes); RUN(real_patterns); RUN(error_handling); clock_t end = clock(); double elapsed = (double)(end - start) / CLOCKS_PER_SEC; printf("\n========================\n"); printf("passed: %d, failed: %d\n", total_passed, total_failed); printf("time: %.3f seconds\n", elapsed); return total_failed > 0 ? 1 : 0; }