ccanlint: Move ccanlint test options from _info comments to code
[ccan] / ccan / rszshm / test / run.c
1 #define _GNU_SOURCE
2 #include <err.h>
3 #include <setjmp.h>
4 #include <stdint.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <unistd.h>
8 #include <sys/types.h>
9 #include <sys/wait.h>
10
11 #include <ccan/rszshm/rszshm.h>
12 #include <ccan/tap/tap.h>
13
14 #include <sys/mman.h>
15 #include <sys/file.h>
16
17 int fail_close, fail_flock, fail_ftruncate, fail_msync, fail_munmap, fail_open;
18 #define close(...)      (fail_close     ? errno = 9000, -1 : close(__VA_ARGS__))
19 #define flock(...)      (fail_flock     ? errno = 9001, -1 : flock(__VA_ARGS__))
20 #define ftruncate(...)  (fail_ftruncate ? errno = 9002, -1 : ftruncate(__VA_ARGS__))
21 #define msync(...)      (fail_msync     ? errno = 9003, -1 : msync(__VA_ARGS__))
22 #define munmap(...)     (fail_munmap    ? errno = 9004, -1 : munmap(__VA_ARGS__))
23 #define open(...)       (fail_open      ? errno = 9005, -1 : open(__VA_ARGS__))
24
25 int fail_read, short_read;
26 #define read(...)       (fail_read      ? errno = 9006, -1 : short_read ? 1 : read(__VA_ARGS__))
27
28 int fail_mmap_anon, fail_mmap_fixed, bad_mmap_addr;
29 #define mmap(adr, len, rw, flags, fd, off) (                                    \
30         fail_mmap_anon  && (flags) & MAP_ANON  ? errno = 9010, MAP_FAILED :     \
31         fail_mmap_fixed && (flags) & MAP_FIXED ? errno = 9011, MAP_FAILED :     \
32         bad_mmap_addr ? NULL :                                                  \
33         mmap(adr, len, rw, flags, fd, off)                                      \
34 )
35 #include <ccan/rszshm/rszshm.c>
36
37 #define noerr(x) ({ int n = (x); if (n == -1) err(1, "%s", #x); n; })
38
39 #define longstr \
40 ".................................................................................................................................."
41
42 static jmp_buf j;
43 static struct sigaction sa;
44 static void segvjmp(int signum)
45 {
46         longjmp(j, 1);
47 }
48
49 int main(void)
50 {
51         plan_tests(37);
52
53         ok1(rszshm_mk(NULL, 0, NULL) == NULL && errno == EINVAL);
54
55         struct rszshm s, t;
56         ok1(rszshm_mk(&s, 0, NULL) == NULL && errno == EINVAL);
57
58         ok1(rszshm_mk(&s, 4096, longstr) == NULL && errno == EINVAL);
59
60         fail_mmap_anon = 1;
61         ok1(rszshm_mk(&s, 4096, NULL) == NULL && errno == 9010);
62         rszshm_rm(&s);
63         fail_mmap_anon = 0;
64
65         fail_open = 1;
66         ok1(rszshm_mk(&s, 4096, NULL) == NULL && errno == 9005);
67         rszshm_rm(&s);
68         fail_open = 0;
69
70         fail_ftruncate = 1;
71         ok1(rszshm_mk(&s, 4096, NULL) == NULL && errno == 9002);
72         rszshm_rm(&s);
73         fail_ftruncate = 0;
74
75         fail_mmap_fixed = 1;
76         ok1(rszshm_mk(&s, 4096, NULL) == NULL && errno == 9011);
77         rszshm_rm(&s);
78         fail_mmap_fixed = 0;
79
80         fail_msync = 1;
81         ok1(rszshm_mk(&s, 4096, NULL) == NULL && errno == 9003);
82         rszshm_rm(&s);
83         fail_msync = 0;
84
85         ok1(rszshm_mk(&s, 4096, NULL) != NULL);
86
87         struct rszshm_scan scan = RSZSHM_DFLT_SCAN;
88         scan.iter = 1;
89         ok1(rszshm_mk(&t, 4096, NULL, scan) == NULL && errno == ENOSPC);
90
91         ok1(rszshm_dt(&s) == 0);
92         ok1(rszshm_rm(&s) == 0);
93
94         long pgsz = sysconf(_SC_PAGE_SIZE);
95         scan.len = UINT64_MAX - pgsz;
96         ok1(rszshm_mk(&t, 4096, NULL, scan) == NULL && errno == ENOMEM);
97
98         ok1(rszshm_mk(&t, 4096, "foo/bar_XXXXXX/0") == NULL && errno == ENOENT);
99
100         struct rszshm *r;
101         ok1(rszshm_mkm(r, 4096, NULL) != NULL);
102
103         pid_t p, *pp;
104         noerr(p = fork());
105         char *fname = strdupa(r->fname);
106         if (p)
107                 waitpid(p, NULL, 0);
108         else {
109                 ok1(rszshm_free(r) == 0);
110
111                 struct rszshm *q;
112                 ok1(rszshm_atm(q, fname) != NULL);
113
114                 *((pid_t *) q->dat) = getpid();
115
116                 ok1(rszshm_up(q) == 0);
117                 ok1(rszshm_grow(q) == 1);
118                 ok1(rszshm_free(q) == 0);
119                 exit(0);
120         }
121         pp = (pid_t *) r->dat;
122         ok1(p == *pp);
123
124         fail_mmap_fixed = 1;
125         ok1(rszshm_up(r) == -1 && errno == 9011);
126         fail_mmap_fixed = 0;
127
128         ok1(rszshm_grow(r) == 1);
129
130         ok1(rszshm_dt(r) == 0);
131
132         sa.sa_handler = segvjmp;
133         sa.sa_flags = SA_RESETHAND;
134         sigemptyset(&sa.sa_mask);
135         sigaction(SIGSEGV, &sa, NULL);
136         if (setjmp(j) == 0)
137                 fail("still mapped after detach: %d", *pp);
138         else
139                 pass("access after detach gives segv, OK!");
140
141         ok1(rszshm_at(r, longstr) == NULL && errno == EINVAL);
142
143         fail_open = 1;
144         ok1(rszshm_at(r, fname) == NULL && errno == 9005);
145         fail_open = 0;
146
147         fail_read = 1;
148         ok1(rszshm_at(r, fname) == NULL && errno == 9006);
149         fail_read = 0;
150
151         short_read = 1;
152         ok1(rszshm_at(r, fname) == NULL && errno == ENODATA);
153         short_read = 0;
154
155         fail_mmap_anon = 1;
156         ok1(rszshm_at(r, fname) == NULL && errno == 9010);
157         fail_mmap_anon = 0;
158
159         bad_mmap_addr = 1;
160         ok1(rszshm_at(r, fname) == NULL && errno == ENOSPC);
161         bad_mmap_addr = 0;
162
163         fail_mmap_fixed = 1;
164         ok1(rszshm_at(r, fname) == NULL && errno == 9011);
165         fail_mmap_fixed = 0;
166
167         ok1(rszshm_at(r, fname) != NULL);
168         ok1(p == *pp);
169
170         struct rszshm_hdr save = *r->hdr;
171         r->hdr->flen = r->flen;
172         r->hdr->max  = r->flen;
173         ok1(rszshm_grow(r) == -1 && errno == ENOMEM);
174         *r->hdr = save;
175
176         fail_flock = 1;
177         ok1(rszshm_grow(r) == -1 && errno == 9001);
178         fail_flock = 0;
179
180         fail_ftruncate = 1;
181         ok1(rszshm_grow(r) == -1 && errno == 9002);
182         fail_ftruncate = 0;
183
184         ok1(rszshm_grow(r) == 1);
185         ok1(rszshm_dt(r) == 0);
186         ok1(rszshm_rm(r) == 0);
187
188         r->fname[0] = '\0';
189         ok1(rszshm_rmdir(r) == -1 && errno == ENOTDIR);
190
191         ok1(rszshm_free(r) == 0);
192
193         return exit_status();
194 }