|
/* retoor <retoor@molodetz.nl> */
|
|
#include "../include/lorex.h"
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
|
|
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;
|
|
}
|