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