X-Git-Url: http://git.pk910.de/?p=ircu2.10.12-pk.git;a=blobdiff_plain;f=ircd%2Ftest%2Fircd_match_t.c;fp=ircd%2Ftest%2Fircd_match_t.c;h=b675cd644f0770c2ee5b19090f72362cdc0098d8;hp=0000000000000000000000000000000000000000;hb=0400a5a6479398d82526785c18c0df8bc8b92dce;hpb=d17e10da972ce5776c60b4c317267c6abe0e1ead diff --git a/ircd/test/ircd_match_t.c b/ircd/test/ircd_match_t.c new file mode 100644 index 0000000..b675cd6 --- /dev/null +++ b/ircd/test/ircd_match_t.c @@ -0,0 +1,161 @@ +/* + * ircd_match_t.c - test cases for irc glob matching + */ + +#include "ircd_log.h" +#include "match.h" + +#include /* errno */ +#include /* O_RDONLY */ +#include +#include +#include /* mmap(), munmap() */ +#include /* sysconf() */ + +#if !defined(MAP_ANONYMOUS) +# if defined(MAP_ANON) +# define MAP_ANONYMOUS MAP_ANON +# else +# error I do not know how to request an anonymous mmap from your OS. +# endif +#endif + +#if !defined(_SC_PAGE_SIZE) +# if defined(_SC_PAGESIZE) +# define _SC_PAGE_SIZE _SC_PAGESIZE +# else +# error I do not know how to request the page size from your OS. +# endif +#endif + +struct match_test { + const char *glob; + const char *should_match; + const char *shouldnt_match; +}; + +const struct match_test match_tests[] = { + { "\\*", + "*\0", + "a\0*PeacefuL*\0" }, + { "*a*", + "a\0pizza\0abe\0brack\0", + "b\0" }, + { "?", + "*\0a\0?\0", + "*PeacefuL*\0pizza\0???\0" }, + { "abc", + "abc\0", + "abcd\0cabc\0" }, + { "*abc", + "abc\0fooabc\0ababc\0", + "abra\0abcd\0" }, + { "\\?", + "?\0", + "a\0" }, + { "*\\\\[*!~*", + "har\\[dy!~boy\0", + "dark\\s|de!pimp\0joe\\[mama\0" }, + { NULL, NULL, NULL } +}; + +int test_match(const char glob[], const char name[]) +{ + static unsigned int page_size; + static char *pages; + char *test_glob; + char *test_name; + size_t length; + int res; + + /* If we have not yet set up our test mappings, do so. */ + if (!page_size) + { + int dev_zero_fd; + + page_size = sysconf(_SC_PAGE_SIZE); + if (page_size == 0 || page_size == (unsigned int)-1) + { + fprintf(stderr, "sysconf(_SC_PAGE_SIZE) failed: %s\n", strerror(errno)); + assert(0); + } + dev_zero_fd = open("/dev/zero", O_RDONLY); + /* If dev_zero_fd == -1 (failed), we may still be able to mmap anonymously. */ + pages = mmap(NULL, 4 * page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, dev_zero_fd, 0); + if (pages == MAP_FAILED) + { + /* Try using fd == -1 for MAP_ANONYMOUS, which BSD systems require. */ + pages = mmap(NULL, 4 * page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + } + if (pages == MAP_FAILED) + { + fprintf(stderr, "Unable to map pages: %s\n", strerror(errno)); + assert(0); + } + if (dev_zero_fd >= 0) + { + close(dev_zero_fd); + dev_zero_fd = -1; + } + res = munmap(pages + page_size * 1, page_size); + if (res < 0) + { + fprintf(stderr, "Unable to unmap page 2/4: %s\n", strerror(errno)); + /* Dysfunctional OSes */ + } + munmap(pages + page_size * 3, page_size); + if (res < 0) + { + fprintf(stderr, "Unable to unmap page 4/4: %s\n", strerror(errno)); + } + } + + /* Copy the strings to the end of their respective pages. */ + length = strlen(glob) + 1; + test_glob = pages + page_size * 1 - length; + memcpy(test_glob, glob, length); + length = strlen(name) + 1; + test_name = pages + page_size * 3 - length; + memcpy(test_name, name, length); + + /* Perform the test. */ + return match(test_glob, test_name); +} + +void do_match_test(const struct match_test *test) +{ + const char *candidate; + unsigned int matched, not_matched; + int res; + + for (candidate = test->should_match, matched = 0; + *candidate; + candidate += strlen(candidate) + 1, ++matched) { + res = test_match(test->glob, candidate); + if (res != 0) { + fprintf(stderr, "\"%s\" failed to match \"%s\".\n", test->glob, candidate); + assert(0); + } + } + + for (candidate = test->shouldnt_match, not_matched = 0; + *candidate; + candidate += strlen(candidate) + 1, ++not_matched) { + res = test_match(test->glob, candidate); + if (res == 0) { + fprintf(stderr, "\"%s\" incorrectly matched \"%s\".\n", test->glob, candidate); + assert(0); + } + } + + printf("Passed: %s (%u matches, %u non-matches)\n", + test->glob, matched, not_matched); +} + +int main(int argc, char *argv[]) +{ + const struct match_test *match; + for (match = match_tests; match->glob; ++match) + do_match_test(match); + return 0; +}