xref: /minix/minix/tests/test41.c (revision 83133719)
1 /* Tests for getitimer(2)/setitimer(2) - by D.C. van Moolenbroek */
2 /* Warning: this test deals with (real and virtual) time, and, lacking a proper
3  * point of reference, its correctness depends on circumstances like CPU speed
4  * and system load. A succeeding test run says a lot - failure not so much. */
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <time.h>
9 #include <minix/config.h>
10 #include <sys/types.h>
11 #include <sys/time.h>
12 #include <sys/wait.h>
13 #include <sys/syslimits.h>
14 #include <signal.h>
15 #include <unistd.h>
16 #include <errno.h>
17 
18 #define ITERATIONS 3
19 int max_error = 4;
20 #include "common.h"
21 
22 
23 
24 /* we have to keep in mind the millisecond values are rounded up */
25 #define UPPERUSEC(us) ((us)+(1000000/system_hz))
26 #define EQUSEC(l,r) \
27   ((l) <= ((r) + (1000000/system_hz)) && (l) >= ((r) - (1000000/system_hz)))
28 
29 #define FILLITIMER(it, vs, vu, is, iu) \
30   (it).it_value.tv_sec = (vs); \
31   (it).it_value.tv_usec = (vu); \
32   (it).it_interval.tv_sec = (is); \
33   (it).it_interval.tv_usec = (iu);
34 
35 /* these two macros are not fully working for all possible values;
36  * the tests only use values that the macros can deal with, though. */
37 #define EQITIMER(it, vs, vu, is, iu) \
38   ((it).it_value.tv_sec == (vs) && EQUSEC((it).it_value.tv_usec,vu) && \
39   (it).it_interval.tv_sec == (is) && (it).it_interval.tv_usec == (iu))
40 
41 #define LEITIMER(it, vs, vu, is, iu) \
42   ((it).it_value.tv_sec > 0 && ((it).it_value.tv_sec < (vs) || \
43   ((it).it_value.tv_sec == (vs) && (it).it_value.tv_usec <= \
44    UPPERUSEC(vu))) && \
45   (it).it_interval.tv_sec == (is) && EQUSEC((it).it_interval.tv_usec,iu))
46 
47 int main(int argc, char **argv);
48 void test(int m, int t);
49 void test_which(void);
50 void test_getset(void);
51 void test_neglarge(void);
52 void test_zero(void);
53 void test_timer(void);
54 void test_alarm(void);
55 void test_fork(void);
56 void test_exec(void);
57 int do_check(void);
58 void got_alarm(int sig);
59 void busy_wait(int secs);
60 #define my_e(n) do { printf("Timer %s, ", names[timer]); e(n); } while(0)
61 
62 static char *executable;
63 static int signals;
64 static int timer;
65 static long system_hz;
66 
67 static int sigs[] = { SIGALRM, SIGVTALRM, SIGPROF };
68 static const char *names[] = { "REAL", "VIRTUAL", "PROF" };
69 
70 int main(argc, argv)
71 int argc;
72 char **argv;
73 {
74   int i, m = 0xFFFF, n = 0xF;
75   char cp_cmd[NAME_MAX+10];
76 
77   system_hz = sysconf(_SC_CLK_TCK);
78 
79   if (strcmp(argv[0], "DO CHECK") == 0) {
80   	timer = atoi(argv[1]);
81 
82 	exit(do_check());
83   }
84 
85   executable = argv[0];
86 
87   start(41);
88 
89   snprintf(cp_cmd, sizeof(cp_cmd), "cp ../%s .", executable);
90   system(cp_cmd);
91 
92   if (argc >= 2) m = atoi(argv[1]);
93   if (argc >= 3) n = atoi(argv[2]);
94 
95   for (i = 0; i < ITERATIONS; i++) {
96   	if (n & 1) test(m, ITIMER_REAL);
97   	if (n & 2) test(m, ITIMER_VIRTUAL);
98   	if (n & 4) test(m, ITIMER_PROF);
99   }
100 
101   quit();
102   return(-1);			/* impossible */
103 }
104 
105 void test(m, t)
106 int m;
107 int t;
108 {
109   timer = t;
110 
111   if (m & 0001) test_which();
112   if (m & 0002) test_getset();
113   if (m & 0004) test_neglarge();
114   if (m & 0010) test_zero();
115   if (m & 0020) test_timer();
116   if (m & 0040) test_alarm();
117   if (m & 0100) test_fork();
118   if (m & 0200) test_exec();
119 }
120 
121 /* test invalid and unsupported 'which' values */
122 void test_which()
123 {
124   struct itimerval it;
125 
126   subtest = 0;
127 
128   errno = 0; if (!getitimer(-1, &it) || errno != EINVAL) my_e(1);
129   errno = 0; if ( getitimer(timer, &it)                ) my_e(2);
130   errno = 0; if (!getitimer( 3, &it) || errno != EINVAL) my_e(3);
131 }
132 
133 /* test if we get back what we set */
134 void test_getset()
135 {
136   struct itimerval it, oit;
137 
138   subtest = 1;
139 
140   /* no alarm should be set initially */
141   if (getitimer(timer, &it)) my_e(1);
142   if (!EQITIMER(it, 0, 0, 0, 0)) my_e(2);
143 
144   if (setitimer(timer, &it, &oit)) my_e(3);
145   if (setitimer(timer, &oit, NULL)) my_e(4);
146   if (!EQITIMER(oit, 0, 0, 0, 0)) my_e(5);
147 
148   FILLITIMER(it, 123, 0, 456, 0);
149   if (setitimer(timer, &it, NULL)) my_e(6);
150 
151   FILLITIMER(it, 987, 0, 654, 0);
152   if (setitimer(timer, &it, &oit)) my_e(7);
153   if (!LEITIMER(oit, 123, 0, 456, 0)) my_e(8);
154 
155   if (getitimer(timer, &oit)) my_e(9);
156   if (!LEITIMER(oit, 987, 0, 654, 0)) my_e(10);
157 
158   FILLITIMER(it, 0, 0, 0, 0);
159   if (setitimer(timer, &it, &oit)) my_e(11);
160   if (!LEITIMER(oit, 987, 0, 654, 0)) my_e(12);
161 
162   if (getitimer(timer, &oit)) my_e(13);
163   if (!EQITIMER(oit, 0, 0, 0, 0)) my_e(14);
164 }
165 
166 /* test negative/large values */
167 void test_neglarge()
168 {
169   struct itimerval it;
170 
171   subtest = 2;
172 
173   FILLITIMER(it, 4, 0, 5, 0);
174   if (setitimer(timer, &it, NULL)) my_e(1);
175 
176   FILLITIMER(it, 1000000000, 0, 0, 0);
177   if (!setitimer(timer, &it, NULL) || errno != EINVAL) my_e(2);
178 
179   FILLITIMER(it, 0, 1000000, 0, 0);
180   if (!setitimer(timer, &it, NULL) || errno != EINVAL) my_e(3);
181 
182   FILLITIMER(it, 0, 0, 0, 1000000);
183   if (!setitimer(timer, &it, NULL) || errno != EINVAL) my_e(4);
184 
185   FILLITIMER(it, -1, 0, 0, 0);
186   if (!setitimer(timer, &it, NULL) || errno != EINVAL) my_e(5);
187 
188   FILLITIMER(it, 0, -1, 0, 0);
189   if (!setitimer(timer, &it, NULL) || errno != EINVAL) my_e(6);
190 
191   FILLITIMER(it, 0, 0, -1, 0);
192   if (!setitimer(timer, &it, NULL) || errno != EINVAL) my_e(7);
193 
194   FILLITIMER(it, 0, 0, 0, -1);
195   if (!setitimer(timer, &it, NULL) || errno != EINVAL) my_e(8);
196 
197   if (getitimer(timer, &it)) my_e(9);
198   if (!LEITIMER(it, 4, 0, 5, 0)) my_e(10);
199 }
200 
201 /* setitimer with a zero timer has to set the interval to zero as well */
202 void test_zero()
203 {
204   struct itimerval it;
205 
206   subtest = 3;
207 
208   it.it_value.tv_sec = 0;
209   it.it_value.tv_usec = 0;
210   it.it_interval.tv_sec = 1;
211   it.it_interval.tv_usec = 1;
212 
213   if (setitimer(timer, &it, NULL)) my_e(1);
214   if (getitimer(timer, &it)) my_e(2);
215   if (!EQITIMER(it, 0, 0, 0, 0)) my_e(3);
216 }
217 
218 /* test actual timer functioning */
219 void test_timer()
220 {
221   struct itimerval it;
222 
223   subtest = 4;
224 
225   if (signal(sigs[timer], got_alarm) == SIG_ERR) my_e(1);
226 
227   FILLITIMER(it, 0, 100000, 0, 100000);
228 
229   if (setitimer(timer, &it, NULL)) my_e(2);
230 
231   signals = 0;
232   busy_wait(1);
233 
234   FILLITIMER(it, 0, 0, 0, 0);
235   if (setitimer(timer, &it, NULL)) my_e(3);
236 
237   /* we don't know how many signals we'll actually get in practice,
238    * so these checks more or less cover the extremes of the acceptable */
239   if (signals < 2) my_e(4);
240   if (signals > system_hz * 2) my_e(5);
241 
242   /* only for REAL timer can we check against the clock */
243   if (timer == ITIMER_REAL) {
244 	FILLITIMER(it, 1, 0, 0, 0);
245 	if (setitimer(timer, &it, NULL)) my_e(6);
246 
247 	signals = 0;
248 	busy_wait(1);
249 
250   	FILLITIMER(it, 0, 0, 0, 0);
251   	if (setitimer(timer, &it, NULL)) my_e(7);
252 
253 	if (signals != 1) my_e(8);
254   }
255 
256   signals = 0;
257   busy_wait(1);
258 
259   if (signals != 0) my_e(9);
260 }
261 
262 /* test itimer/alarm interaction */
263 void test_alarm(void) {
264   struct itimerval it;
265 
266   /* only applicable for ITIMER_REAL */
267   if (timer != ITIMER_REAL) return;
268 
269   subtest = 5;
270 
271   if (signal(SIGALRM, got_alarm) == SIG_ERR) my_e(1);
272 
273   FILLITIMER(it, 3, 0, 1, 0);
274   if (setitimer(timer, &it, NULL)) my_e(2);
275 
276   if (alarm(2) != 3) my_e(3);
277 
278   if (getitimer(timer, &it)) my_e(4);
279   if (!LEITIMER(it, 2, 0, 0, 0)) my_e(5);
280 
281   signals = 0;
282   busy_wait(5);
283 
284   if (signals != 1) my_e(6);
285 
286   if (getitimer(timer, &it)) my_e(7);
287   if (!EQITIMER(it, 0, 0, 0, 0)) my_e(8);
288 }
289 
290 /* test that the timer is reset on forking */
291 void test_fork(void) {
292   struct itimerval it, oit;
293   pid_t pid;
294   int status;
295 
296   subtest = 6;
297 
298   FILLITIMER(it, 12, 34, 56, 78);
299 
300   if (setitimer(timer, &it, NULL)) my_e(1);
301 
302   pid = fork();
303   if (pid < 0) my_e(2);
304 
305   if (pid == 0) {
306     if (getitimer(timer, &it)) exit(5);
307     if (!EQITIMER(it, 0, 0, 0, 0)) exit(6);
308 
309     exit(0);
310   }
311 
312   if (wait(&status) != pid) my_e(3);
313   if (!WIFEXITED(status)) my_e(4);
314   if (WEXITSTATUS(status) != 0) my_e(WEXITSTATUS(status));
315 
316   FILLITIMER(it, 0, 0, 0, 0);
317   if (setitimer(timer, &it, &oit)) my_e(7);
318   if (!LEITIMER(oit, 12, 34, 56, 78)) my_e(8);
319 }
320 
321 /* test if timer is carried over to exec()'ed process */
322 void test_exec(void) {
323   struct itimerval it;
324   pid_t pid;
325   int status;
326   char buf[2];
327 
328   subtest = 7;
329 
330   pid = fork();
331   if (pid < 0) my_e(1);
332 
333   if (pid == 0) {
334     FILLITIMER(it, 3, 0, 1, 0);
335     if (setitimer(timer, &it, NULL)) exit(2);
336 
337     sprintf(buf, "%d", timer);
338     execl(executable, "DO CHECK", buf, NULL);
339 
340     exit(3);
341   }
342 
343   if (wait(&status) != pid) my_e(4);
344   if (WIFSIGNALED(status)) {
345     /* process should have died from corresponding signal */
346     if (WTERMSIG(status) != sigs[timer]) my_e(5);
347   }
348   else {
349     if (WIFEXITED(status)) my_e(WEXITSTATUS(status));
350     else my_e(6);
351   }
352 }
353 
354 /* procedure of the exec()'ed process */
355 int do_check()
356 {
357   struct itimerval it;
358 
359   if (getitimer(timer, &it)) return(81);
360   if (!LEITIMER(it, 3, 0, 1, 0)) return(82);
361 
362   busy_wait(60);
363 
364   return(83);
365 }
366 
367 void busy_wait(secs)
368 int secs;
369 {
370   time_t now, exp;
371   int i;
372 
373   exp = time(&now) + secs + 1;
374 
375   while (now < exp) {
376   	for (i = 0; i < 100000; i++);
377 
378 	time(&now);
379   }
380 }
381 
382 void got_alarm(sig)
383 int sig;
384 {
385   if (sig != sigs[timer]) my_e(1001);
386 
387   signals++;
388 }
389 
390