Fix compilation problems when _SC_PAGE_SIZE is not defined by the OS.
[ircu2.10.12-pk.git] / ircd / test / ircd_match_t.c
1 /*
2  * ircd_match_t.c - test cases for irc glob matching
3  */
4
5 #include "ircd_log.h"
6 #include "match.h"
7
8 #include <errno.h>    /* errno */
9 #include <fcntl.h>    /* O_RDONLY */
10 #include <stdio.h>
11 #include <string.h>
12 #include <sys/mman.h> /* mmap(), munmap() */
13 #include <unistd.h>   /* sysconf() */
14
15 #if !defined(MAP_ANONYMOUS)
16 # if defined(MAP_ANON)
17 #  define MAP_ANONYMOUS MAP_ANON
18 # else
19 #  error I do not know how to request an anonymous mmap from your OS.
20 # endif
21 #endif
22
23 #if !defined(_SC_PAGE_SIZE)
24 # if defined(_SC_PAGESIZE)
25 #  define _SC_PAGE_SIZE _SC_PAGESIZE
26 # else
27 #  error I do not know how to request the page size from your OS.
28 # endif
29 #endif
30
31 struct match_test {
32   const char *glob;
33   const char *should_match;
34   const char *shouldnt_match;
35 };
36
37 const struct match_test match_tests[] = {
38   { "\\*",
39     "*\0",
40     "a\0*PeacefuL*\0" },
41   { "*a*",
42     "a\0pizza\0abe\0brack\0",
43     "b\0" },
44   { "?",
45     "*\0a\0?\0",
46     "*PeacefuL*\0pizza\0???\0" },
47   { "abc",
48     "abc\0",
49     "abcd\0cabc\0" },
50   { "*abc",
51     "abc\0fooabc\0ababc\0",
52     "abra\0abcd\0" },
53   { "\\?",
54     "?\0",
55     "a\0" },
56   { "*\\\\[*!~*",
57     "har\\[dy!~boy\0",
58     "dark\\s|de!pimp\0joe\\[mama\0" },
59   { NULL, NULL, NULL }
60 };
61
62 int test_match(const char glob[], const char name[])
63 {
64   static unsigned int page_size;
65   static char *pages;
66   char *test_glob;
67   char *test_name;
68   size_t length;
69   int res;
70
71   /* If we have not yet set up our test mappings, do so. */
72   if (!page_size)
73   {
74     int dev_zero_fd;
75
76     page_size = sysconf(_SC_PAGE_SIZE);
77     if (page_size == 0 || page_size == (unsigned int)-1)
78     {
79       fprintf(stderr, "sysconf(_SC_PAGE_SIZE) failed: %s\n", strerror(errno));
80       assert(0);
81     }
82     dev_zero_fd = open("/dev/zero", O_RDONLY);
83     /* If dev_zero_fd == -1 (failed), we may still be able to mmap anonymously. */
84     pages = mmap(NULL, 4 * page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, dev_zero_fd, 0);
85     if (pages == MAP_FAILED)
86     {
87       /* Try using fd == -1 for MAP_ANONYMOUS, which BSD systems require. */
88       pages = mmap(NULL, 4 * page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
89     }
90     if (pages == MAP_FAILED)
91     {
92       fprintf(stderr, "Unable to map pages: %s\n", strerror(errno));
93       assert(0);
94     }
95     if (dev_zero_fd >= 0)
96     {
97       close(dev_zero_fd);
98       dev_zero_fd = -1;
99     }
100     res = munmap(pages + page_size * 1, page_size);
101     if (res < 0)
102     {
103       fprintf(stderr, "Unable to unmap page 2/4: %s\n", strerror(errno));
104       /* Dysfunctional OSes */
105     }
106     munmap(pages + page_size * 3, page_size);
107     if (res < 0)
108     {
109       fprintf(stderr, "Unable to unmap page 4/4: %s\n", strerror(errno));
110     }
111   }
112
113   /* Copy the strings to the end of their respective pages. */
114   length = strlen(glob) + 1;
115   test_glob = pages + page_size * 1 - length;
116   memcpy(test_glob, glob, length);
117   length = strlen(name) + 1;
118   test_name = pages + page_size * 3 - length;
119   memcpy(test_name, name, length);
120
121   /* Perform the test. */
122   return match(test_glob, test_name);
123 }
124
125 void do_match_test(const struct match_test *test)
126 {
127   const char *candidate;
128   unsigned int matched, not_matched;
129   int res;
130
131   for (candidate = test->should_match, matched = 0;
132        *candidate;
133        candidate += strlen(candidate) + 1, ++matched) {
134     res = test_match(test->glob, candidate);
135     if (res != 0) {
136       fprintf(stderr, "\"%s\" failed to match \"%s\".\n", test->glob, candidate);
137       assert(0);
138     }
139   }
140
141   for (candidate = test->shouldnt_match, not_matched = 0;
142        *candidate;
143        candidate += strlen(candidate) + 1, ++not_matched) {
144     res = test_match(test->glob, candidate);
145     if (res == 0) {
146       fprintf(stderr, "\"%s\" incorrectly matched \"%s\".\n", test->glob, candidate);
147       assert(0);
148     }
149   }
150
151   printf("Passed: %s (%u matches, %u non-matches)\n",
152          test->glob, matched, not_matched);
153 }
154
155 int main(int argc, char *argv[])
156 {
157   const struct match_test *match;
158   for (match = match_tests; match->glob; ++match)
159     do_match_test(match);
160   return 0;
161 }