]> git.ozlabs.org Git - ccan/blob - ccan/altstack/test/run.c
23dd2e93ef69e83be1312b01da37f88b86d7ea85
[ccan] / ccan / altstack / test / run.c
1 #include "config.h"
2 #include <assert.h>
3 #include <err.h>
4 #include <errno.h>
5 #include <setjmp.h>
6 #include <signal.h>
7 #include <string.h>
8 #include <unistd.h>
9 #include <sys/mman.h>
10 #include <ccan/tap/tap.h>
11 #include <ccan/altstack/altstack.h>
12 #include <stdio.h>
13
14 enum {
15         getrlimit_      = 1<<0,
16         setrlimit_      = 1<<1,
17         mmap_           = 1<<2,
18         sigaltstack_    = 1<<3,
19         sigaction_      = 1<<4,
20         munmap_         = 1<<5,
21 };
22 int fail, call1, call2;
23 char *m_;
24 rlim_t msz_;
25 #define e(x) (900+(x))
26 #define seterr(x) (errno = e(x))
27 #define setcall(x) ((call1 |= !errno ? (x) : 0), (call2 |= errno || state.out ? (x) : 0))
28 #define getrlimit(...)          (fail&getrlimit_        ? (seterr(getrlimit_),          -1) : (setcall(getrlimit_),     getrlimit(__VA_ARGS__)))
29 #define mmap(...)               (fail&mmap_             ? (seterr(mmap_),       (void *)-1) : (setcall(mmap_),          mmap(__VA_ARGS__)))
30 #define munmap(a, b)            (fail&munmap_           ? (seterr(munmap_),             -1) : (setcall(munmap_),        munmap(m_=(a), msz_=(b))))
31 #define setrlimit(...)          (fail&setrlimit_        ? (seterr(setrlimit_),          -1) : (setcall(setrlimit_),     setrlimit(__VA_ARGS__)))
32 #define sigaltstack(...)        (fail&sigaltstack_      ? (seterr(sigaltstack_),        -1) : (setcall(sigaltstack_),   sigaltstack(__VA_ARGS__)))
33 #define sigaction(...)          (fail&sigaction_        ? (seterr(sigaction_),          -1) : (setcall(sigaction_),     sigaction(__VA_ARGS__)))
34
35 #define KiB (1024UL)
36 #define MiB (KiB*KiB)
37 #define GiB (MiB*KiB)
38 #define TiB (GiB*KiB)
39
40 FILE *mystderr;
41 #undef stderr
42 #define stderr mystderr
43 #undef ok
44 #include <ccan/altstack/altstack.c>
45 #undef ok
46
47 long used;
48
49 static void __attribute__((optimize("O0"))) dn(unsigned long i)
50 {
51         if (used) used = altstack_used();
52         if (i) dn(--i);
53 }
54 static void *wrap(void *i)
55 {
56         dn((unsigned long) i);
57         return wrap;
58 }
59
60 #define chkfail(x, y, z, c1, c2)                                        \
61         do {                                                            \
62                 call1 = 0;                                              \
63                 call2 = 0;                                              \
64                 errno = 0;                                              \
65                 ok1((fail = x) && (y));                                 \
66                 ok1(errno == (z));                                      \
67                 ok1(call1 == (c1));                                     \
68                 ok1(call2 == (c2));                                     \
69         } while (0);
70
71 #define chkok(y, z, c1, c2)                                             \
72         do {                                                            \
73                 call1 = 0;                                              \
74                 call2 = 0;                                              \
75                 errno = 0;                                              \
76                 fail = 0;                                               \
77                 ok1((y));                                               \
78                 ok1(errno == (z));                                      \
79                 ok1(call1 == (c1));                                     \
80                 ok1(call2 == (c2));                                     \
81         } while (0)
82
83 int main(void)
84 {
85         long pgsz = sysconf(_SC_PAGESIZE);
86
87         plan_tests(50);
88
89         chkfail(getrlimit_,     altstack(8*MiB, wrap, 0, 0) == -1, e(getrlimit_),
90                 0,
91                 0);
92
93         chkfail(setrlimit_,     altstack(8*MiB, wrap, 0, 0) == -1, e(setrlimit_),
94                 getrlimit_,
95                 0);
96
97         chkfail(mmap_,          altstack(8*MiB, wrap, 0, 0) == -1, e(mmap_),
98                 getrlimit_|setrlimit_,
99                 setrlimit_);
100
101         chkfail(sigaltstack_,   altstack(8*MiB, wrap, 0, 0) == -1, e(sigaltstack_),
102                 getrlimit_|setrlimit_|mmap_,
103                 setrlimit_|munmap_);
104
105         chkfail(sigaction_,     altstack(8*MiB, wrap, 0, 0) == -1, e(sigaction_),
106                 getrlimit_|setrlimit_|mmap_|sigaltstack_,
107                 setrlimit_|munmap_|sigaltstack_);
108
109         chkfail(munmap_,        altstack(8*MiB, wrap, 0, 0) ==  1, e(munmap_),
110                 getrlimit_|setrlimit_|mmap_|sigaltstack_|sigaction_,
111                 setrlimit_|sigaltstack_|sigaction_);
112         if (fail = 0, munmap(m_, msz_) == -1)
113                 err(1, "munmap");
114
115         chkok(                  altstack(1*MiB, wrap, (void *) 1000000, 0) == -1, EOVERFLOW,
116                 getrlimit_|setrlimit_|mmap_|sigaltstack_|sigaction_,
117                 setrlimit_|munmap_|sigaltstack_|sigaction_);
118
119         // be sure segv catch is repeatable (SA_NODEFER)
120         chkok(                  altstack(1*MiB, wrap, (void *) 1000000, 0) == -1, EOVERFLOW,
121                 getrlimit_|setrlimit_|mmap_|sigaltstack_|sigaction_,
122                 setrlimit_|munmap_|sigaltstack_|sigaction_);
123
124         used = 1;
125         chkfail(munmap_,        altstack(1*MiB, wrap, (void *) 1000000, 0) == -1, EOVERFLOW,
126                 getrlimit_|setrlimit_|mmap_|sigaltstack_|sigaction_,
127                 setrlimit_|sigaltstack_|sigaction_);
128         if (fail = 0, munmap(m_, msz_) == -1)
129                 err(1, "munmap");
130
131         ok1(altstack_max() == 1*MiB);
132         diag("used: %lu", used);
133         ok1(used >= 1*MiB - pgsz && used <= 1*MiB + pgsz);
134
135         char *p;
136         for(p = altstack_geterr(); *p; p++)
137                 if (*p >= '0' && *p <= '9')
138                         *p = '~';
139
140         #define estr "(altstack@~~~) SIGSEGV caught; (altstack@~~~) munmap(m, max): Unknown error ~~~"
141         ok1(strcmp(altstack_geterr(), estr) == 0);
142
143         char buf[ALTSTACK_ERR_MAXLEN*2] = {0};
144         if ((mystderr = fmemopen(buf, sizeof(buf), "w")) == NULL)
145                 err(1, "fmemopen");
146
147         altstack_perror();
148         fflush(mystderr);
149         ok1(strcmp(buf, estr "\n") == 0);
150
151         used = 1;
152         chkok(                  altstack(8*MiB, wrap, (void *) 1000000, 0) == -1, EOVERFLOW,
153                 getrlimit_|setrlimit_|mmap_|sigaltstack_|sigaction_,
154                 setrlimit_|munmap_|sigaltstack_|sigaction_);
155
156         diag("used: %lu", used);
157         ok1(used >= 8*MiB - pgsz && used <= 8*MiB + pgsz);
158
159         used = 0;
160         chkok(                  altstack(8*MiB, wrap, (void *) 100000, 0) == 0, 0,
161                 getrlimit_|setrlimit_|mmap_|sigaltstack_|sigaction_|munmap_,
162                 setrlimit_|munmap_|sigaltstack_|sigaction_);
163
164         used = 1;
165         altstack_rsp_save();
166         dn(0);
167         diag("used: %lu", used);
168         ok1(used == 32 || used == 40);
169
170         return exit_status();
171 }