]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/msun/tests/fenv_test.c
contrib/tzdata: import tzdata 2023c
[FreeBSD/FreeBSD.git] / lib / msun / tests / fenv_test.c
1 /*-
2  * Copyright (c) 2004 David Schultz <das@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 /*
28  * Test the correctness and C99-compliance of various fenv.h features.
29  */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include <sys/types.h>
35 #include <sys/wait.h>
36 #include <assert.h>
37 #include <err.h>
38 #include <fenv.h>
39 #include <float.h>
40 #include <libutil.h>
41 #include <math.h>
42 #include <signal.h>
43 #include <stdio.h>
44 #include <string.h>
45 #include <unistd.h>
46
47 #include "test-utils.h"
48
49 #define NEXCEPTS        (sizeof(std_excepts) / sizeof(std_excepts[0]))
50
51 static const int std_excepts[] = {
52         FE_INVALID,
53         FE_DIVBYZERO,
54         FE_OVERFLOW,
55         FE_UNDERFLOW,
56         FE_INEXACT,
57 };
58
59 /* init_exceptsets() initializes this to the power set of std_excepts[] */
60 static int std_except_sets[1 << NEXCEPTS];
61
62 #pragma STDC FENV_ACCESS ON
63
64 /*
65  * Initialize std_except_sets[] to the power set of std_excepts[]
66  */
67 static __attribute__((constructor)) void
68 do_setup(void)
69 {
70         unsigned i, j, sr;
71
72         /* Avoid double output after fork() */
73         setvbuf(stdout, NULL, _IONBF, 0);
74
75         for (i = 0; i < 1 << NEXCEPTS; i++) {
76                 for (sr = i, j = 0; sr != 0; sr >>= 1, j++)
77                         std_except_sets[i] |= std_excepts[j] & ((~sr & 1) - 1);
78         }
79 }
80
81 /*
82  * Raise a floating-point exception without relying on the standard
83  * library routines, which we are trying to test.
84  *
85  * XXX We can't raise an {over,under}flow without also raising an
86  * inexact exception.
87  */
88 static void
89 raiseexcept(int excepts)
90 {
91         volatile double d;
92
93         /*
94          * With a compiler that supports the FENV_ACCESS pragma
95          * properly, simple expressions like '0.0 / 0.0' should
96          * be sufficient to generate traps.  Unfortunately, we
97          * need to bring a volatile variable into the equation
98          * to prevent incorrect optimizations.
99          */
100         if (excepts & FE_INVALID) {
101                 d = 0.0;
102                 d = 0.0 / d;
103         }
104         if (excepts & FE_DIVBYZERO) {
105                 d = 0.0;
106                 d = 1.0 / d;
107         }
108         if (excepts & FE_OVERFLOW) {
109                 d = DBL_MAX;
110                 d *= 2.0;
111         }
112         if (excepts & FE_UNDERFLOW) {
113                 d = DBL_MIN;
114                 d /= DBL_MAX;
115         }
116         if (excepts & FE_INEXACT) {
117                 d = DBL_MIN;
118                 d += 1.0;
119         }
120
121         /*
122          * On the x86 (and some other architectures?) the FPU and
123          * integer units are decoupled.  We need to execute an FWAIT
124          * or a floating-point instruction to get synchronous exceptions.
125          */
126         d = 1.0;
127         d += 1.0;
128 }
129
130 /*
131  * Determine the current rounding mode without relying on the fenv
132  * routines.  This function may raise an inexact exception.
133  */
134 static int
135 getround(void)
136 {
137         volatile double d;
138
139         /*
140          * This test works just as well with 0.0 - 0.0, except on ia64
141          * where 0.0 - 0.0 gives the wrong sign when rounding downwards.
142          */
143         d = 1.0;
144         d -= 1.0;
145         if (copysign(1.0, d) < 0.0)
146                 return (FE_DOWNWARD);
147
148         d = 1.0;
149         if (d + (DBL_EPSILON * 3.0 / 4.0) == 1.0)
150                 return (FE_TOWARDZERO);
151         if (d + (DBL_EPSILON * 1.0 / 4.0) > 1.0)
152                 return (FE_UPWARD);
153
154         return (FE_TONEAREST);
155 }
156
157 static void
158 trap_handler(int sig)
159 {
160
161         ATF_CHECK_EQ(SIGFPE, sig);
162         _exit(0);
163 }
164
165 /*
166  * This tests checks the default FP environment, so it must be first.
167  * The memcmp() test below may be too much to ask for, since there
168  * could be multiple machine-specific default environments.
169  */
170 ATF_TC_WITHOUT_HEAD(dfl_env);
171 ATF_TC_BODY(dfl_env, tc)
172 {
173 #ifndef NO_STRICT_DFL_ENV
174         fenv_t env;
175
176         fegetenv(&env);
177         /* Print the default environment for debugging purposes. */
178         hexdump(&env, sizeof(env), "current fenv ", HD_OMIT_CHARS);
179         hexdump(FE_DFL_ENV, sizeof(env), "default fenv ", HD_OMIT_CHARS);
180         CHECK_FP_EXCEPTIONS(0, FE_ALL_EXCEPT);
181 #ifdef __amd64__
182         /*
183          * Compare the fields that the AMD [1] and Intel [2] specs say will be
184          * set once fnstenv returns.
185          *
186          * Not all amd64 capable processors implement the fnstenv instruction
187          * by zero'ing out the env.__x87.__other field (example: AMD Opteron
188          * 6308). The AMD64/x64 specs aren't explicit on what the
189          * env.__x87.__other field will contain after fnstenv is executed, so
190          * the values in env.__x87.__other could be filled with arbitrary
191          * data depending on how the CPU implements fnstenv.
192          *
193          * 1. http://support.amd.com/TechDocs/26569_APM_v5.pdf
194          * 2. http://www.intel.com/Assets/en_US/PDF/manual/253666.pdf
195          */
196         ATF_CHECK(memcmp(&env.__mxcsr, &FE_DFL_ENV->__mxcsr,
197             sizeof(env.__mxcsr)) == 0);
198         ATF_CHECK(memcmp(&env.__x87.__control, &FE_DFL_ENV->__x87.__control,
199             sizeof(env.__x87.__control)) == 0);
200         ATF_CHECK(memcmp(&env.__x87.__status, &FE_DFL_ENV->__x87.__status,
201             sizeof(env.__x87.__status)) == 0);
202         ATF_CHECK(memcmp(&env.__x87.__tag, &FE_DFL_ENV->__x87.__tag,
203             sizeof(env.__x87.__tag)) == 0);
204 #else
205         ATF_CHECK_EQ(0, memcmp(&env, FE_DFL_ENV, sizeof(env)));
206 #endif
207
208 #endif
209         CHECK_FP_EXCEPTIONS(0, FE_ALL_EXCEPT);
210 }
211
212 /*
213  * Test fetestexcept() and feclearexcept().
214  */
215 ATF_TC_WITHOUT_HEAD(fetestclearexcept);
216 ATF_TC_BODY(fetestclearexcept, tc)
217 {
218         int excepts, i;
219
220         for (i = 0; i < 1 << NEXCEPTS; i++)
221                 ATF_CHECK_EQ(0, fetestexcept(std_except_sets[i]));
222         for (i = 0; i < 1 << NEXCEPTS; i++) {
223                 excepts = std_except_sets[i];
224
225                 /* FE_ALL_EXCEPT might be special-cased, as on i386. */
226                 raiseexcept(excepts);
227                 ATF_CHECK_EQ(excepts, fetestexcept(excepts));
228                 ATF_REQUIRE_EQ(0, feclearexcept(FE_ALL_EXCEPT));
229                 ATF_CHECK_EQ(0, fetestexcept(FE_ALL_EXCEPT));
230
231                 raiseexcept(excepts);
232                 ATF_CHECK_EQ(excepts, fetestexcept(excepts));
233                 if ((excepts & (FE_UNDERFLOW | FE_OVERFLOW)) != 0) {
234                         excepts |= FE_INEXACT;
235                         ATF_CHECK_EQ(excepts, (fetestexcept(ALL_STD_EXCEPT) | FE_INEXACT));
236                 } else {
237                         ATF_CHECK_EQ(excepts, fetestexcept(ALL_STD_EXCEPT));
238                 }
239                 ATF_CHECK_EQ(0, feclearexcept(excepts));
240                 ATF_CHECK_EQ(0, fetestexcept(ALL_STD_EXCEPT));
241         }
242 }
243
244 /*
245  * Test fegetexceptflag() and fesetexceptflag().
246  *
247  * Prerequisites: fetestexcept(), feclearexcept()
248  */
249 ATF_TC_WITHOUT_HEAD(fegsetexceptflag);
250 ATF_TC_BODY(fegsetexceptflag, tc)
251 {
252         fexcept_t flag;
253         int excepts, i;
254
255         CHECK_FP_EXCEPTIONS(0, FE_ALL_EXCEPT);
256         for (i = 0; i < 1 << NEXCEPTS; i++) {
257                 excepts = std_except_sets[i];
258
259                 ATF_CHECK_EQ(0, fegetexceptflag(&flag, excepts));
260                 raiseexcept(ALL_STD_EXCEPT);
261                 ATF_CHECK_EQ(0, fesetexceptflag(&flag, excepts));
262                 ATF_CHECK_EQ((ALL_STD_EXCEPT ^ excepts), fetestexcept(ALL_STD_EXCEPT));
263
264                 ATF_CHECK_EQ(0, fegetexceptflag(&flag, FE_ALL_EXCEPT));
265                 ATF_REQUIRE_EQ(0, feclearexcept(FE_ALL_EXCEPT));
266                 ATF_CHECK_EQ(0, fesetexceptflag(&flag, excepts));
267                 ATF_CHECK_EQ(0, fetestexcept(ALL_STD_EXCEPT));
268                 ATF_CHECK_EQ(0, fesetexceptflag(&flag, ALL_STD_EXCEPT ^ excepts));
269                 ATF_CHECK_EQ((ALL_STD_EXCEPT ^ excepts), fetestexcept(ALL_STD_EXCEPT));
270
271                 ATF_REQUIRE_EQ(0, feclearexcept(FE_ALL_EXCEPT));
272         }
273 }
274
275 /*
276  * Test feraiseexcept().
277  *
278  * Prerequisites: fetestexcept(), feclearexcept()
279  */
280 ATF_TC_WITHOUT_HEAD(feraiseexcept);
281 ATF_TC_BODY(feraiseexcept, tc)
282 {
283         int excepts, i;
284
285         for (i = 0; i < 1 << NEXCEPTS; i++) {
286                 excepts = std_except_sets[i];
287
288                 ATF_CHECK_EQ(0, fetestexcept(FE_ALL_EXCEPT));
289                 ATF_CHECK_EQ(0, feraiseexcept(excepts));
290                 if ((excepts & (FE_UNDERFLOW | FE_OVERFLOW)) != 0) {
291                         excepts |= FE_INEXACT;
292                         ATF_CHECK_EQ(excepts, (fetestexcept(ALL_STD_EXCEPT) | FE_INEXACT));
293                 } else {
294                         ATF_CHECK_EQ(excepts, fetestexcept(ALL_STD_EXCEPT));
295                 }
296                 ATF_REQUIRE_EQ(0, feclearexcept(FE_ALL_EXCEPT));
297         }
298         ATF_CHECK_EQ(0, feraiseexcept(FE_INVALID | FE_DIVBYZERO));
299         ATF_CHECK_EQ((FE_INVALID | FE_DIVBYZERO), fetestexcept(ALL_STD_EXCEPT));
300         ATF_CHECK_EQ(0, feraiseexcept(FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT));
301         ATF_CHECK_EQ(ALL_STD_EXCEPT, fetestexcept(ALL_STD_EXCEPT));
302         ATF_REQUIRE_EQ(0, feclearexcept(FE_ALL_EXCEPT));
303 }
304
305 /*
306  * Test fegetround() and fesetround().
307  */
308 ATF_TC_WITHOUT_HEAD(fegsetround);
309 ATF_TC_BODY(fegsetround, tc)
310 {
311
312         ATF_CHECK_EQ(FE_TONEAREST, fegetround());
313         ATF_CHECK_EQ(FE_TONEAREST, getround());
314         ATF_CHECK_EQ(1, FLT_ROUNDS);
315
316         ATF_CHECK_EQ(0, fesetround(FE_DOWNWARD));
317         ATF_CHECK_EQ(FE_DOWNWARD, fegetround());
318         ATF_CHECK_EQ(FE_DOWNWARD, getround());
319         ATF_CHECK_EQ(3, FLT_ROUNDS);
320
321         ATF_CHECK_EQ(0, fesetround(FE_UPWARD));
322         ATF_CHECK_EQ(FE_UPWARD, getround());
323         ATF_CHECK_EQ(FE_UPWARD, fegetround());
324         ATF_CHECK_EQ(2, FLT_ROUNDS);
325
326         ATF_CHECK_EQ(0, fesetround(FE_TOWARDZERO));
327         ATF_CHECK_EQ(FE_TOWARDZERO, getround());
328         ATF_CHECK_EQ(FE_TOWARDZERO, fegetround());
329         ATF_CHECK_EQ(0, FLT_ROUNDS);
330
331         ATF_CHECK_EQ(0, fesetround(FE_TONEAREST));
332         ATF_CHECK_EQ(FE_TONEAREST, getround());
333         ATF_CHECK_EQ(1, FLT_ROUNDS);
334
335         ATF_REQUIRE_EQ(0, feclearexcept(FE_ALL_EXCEPT));
336 }
337
338 /*
339  * Test fegetenv() and fesetenv().
340  *
341  * Prerequisites: fetestexcept(), feclearexcept(), fegetround(), fesetround()
342  */
343 ATF_TC_WITHOUT_HEAD(fegsetenv);
344 ATF_TC_BODY(fegsetenv, tc)
345 {
346         fenv_t env1, env2;
347         int excepts, i;
348
349         for (i = 0; i < 1 << NEXCEPTS; i++) {
350                 excepts = std_except_sets[i];
351
352                 ATF_CHECK_EQ(0, fetestexcept(FE_ALL_EXCEPT));
353                 ATF_CHECK_EQ(FE_TONEAREST, fegetround());
354                 ATF_CHECK_EQ(0, fegetenv(&env1));
355
356                 /*
357                  * fe[gs]etenv() should be able to save and restore
358                  * exception flags without the spurious inexact
359                  * exceptions that afflict raiseexcept().
360                  */
361                 raiseexcept(excepts);
362                 if ((excepts & (FE_UNDERFLOW | FE_OVERFLOW)) != 0 &&
363                     (excepts & FE_INEXACT) == 0)
364                         ATF_CHECK_EQ(0, feclearexcept(FE_INEXACT));
365
366                 fesetround(FE_DOWNWARD);
367                 ATF_CHECK_EQ(0, fegetenv(&env2));
368                 ATF_CHECK_EQ(0, fesetenv(&env1));
369                 ATF_CHECK_EQ(0, fetestexcept(FE_ALL_EXCEPT));
370                 ATF_CHECK_EQ(FE_TONEAREST, fegetround());
371
372                 ATF_CHECK_EQ(0, fesetenv(&env2));
373
374                 /* 
375                  * Some platforms like powerpc may set extra exception bits. Since
376                  * only standard exceptions are tested, mask against ALL_STD_EXCEPT 
377                  */
378                 ATF_CHECK_EQ(excepts, (fetestexcept(FE_ALL_EXCEPT) & ALL_STD_EXCEPT));
379
380                 ATF_CHECK_EQ(FE_DOWNWARD, fegetround());
381                 ATF_CHECK_EQ(0, fesetenv(&env1));
382                 ATF_CHECK_EQ(0, fetestexcept(FE_ALL_EXCEPT));
383                 ATF_CHECK_EQ(FE_TONEAREST, fegetround());
384         }
385 }
386
387 /*
388  * Test fegetexcept(), fedisableexcept(), and feenableexcept().
389  *
390  * Prerequisites: fetestexcept(), feraiseexcept()
391  */
392 ATF_TC_WITHOUT_HEAD(masking);
393 ATF_TC_BODY(masking, tc)
394 {
395         struct sigaction act;
396         int except, pass, raise, status;
397         unsigned i;
398
399         ATF_REQUIRE_EQ(0, (fegetexcept() & ALL_STD_EXCEPT));
400
401         /*
402          * Some CPUs, e.g. AArch64 QEMU does not support trapping on FP
403          * exceptions. In that case the trap enable bits are all RAZ/WI, so
404          * writing to those bits will be ignored and the next read will
405          * return all zeroes for those bits. Skip the test if no floating
406          * point exceptions are supported and mark it XFAIL if some are missing.
407          */
408         ATF_REQUIRE_EQ(0, (feenableexcept(FE_ALL_EXCEPT)));
409         except = fegetexcept();
410         if (except == 0) {
411                 atf_tc_skip("CPU does not support trapping on floating point "
412                     "exceptions.");
413         } else if ((except & ALL_STD_EXCEPT) != ALL_STD_EXCEPT) {
414                 atf_tc_expect_fail("Not all floating point exceptions can be "
415                     "set to trap: %#x vs %#x", except, ALL_STD_EXCEPT);
416         }
417         fedisableexcept(FE_ALL_EXCEPT);
418
419
420         ATF_CHECK_EQ(0, (feenableexcept(FE_INVALID|FE_OVERFLOW) & ALL_STD_EXCEPT));
421         ATF_CHECK_EQ((FE_INVALID | FE_OVERFLOW), (feenableexcept(FE_UNDERFLOW) & ALL_STD_EXCEPT));
422         ATF_CHECK_EQ((FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW), (fedisableexcept(FE_OVERFLOW) & ALL_STD_EXCEPT));
423         ATF_CHECK_EQ((FE_INVALID | FE_UNDERFLOW), (fegetexcept() & ALL_STD_EXCEPT));
424         ATF_CHECK_EQ((FE_INVALID | FE_UNDERFLOW), (fedisableexcept(FE_ALL_EXCEPT) & ALL_STD_EXCEPT));
425         ATF_CHECK_EQ(0, (fegetexcept() & ALL_STD_EXCEPT));
426
427         sigemptyset(&act.sa_mask);
428         act.sa_flags = 0;
429         act.sa_handler = trap_handler;
430         for (pass = 0; pass < 2; pass++) {
431                 for (i = 0; i < NEXCEPTS; i++) {
432                         except = std_excepts[i];
433                         /* over/underflow may also raise inexact */
434                         if (except == FE_INEXACT)
435                                 raise = FE_DIVBYZERO | FE_INVALID;
436                         else
437                                 raise = ALL_STD_EXCEPT ^ except;
438
439                         /*
440                          * We need to fork a child process because
441                          * there isn't a portable way to recover from
442                          * a floating-point exception.
443                          */
444                         switch(fork()) {
445                         case 0:         /* child */
446                                 ATF_CHECK_EQ(0, (fegetexcept() & ALL_STD_EXCEPT));
447                                 ATF_REQUIRE_EQ(0, (feenableexcept(except) & ALL_STD_EXCEPT));
448                                 ATF_CHECK_EQ(except, fegetexcept());
449                                 raiseexcept(raise);
450                                 ATF_CHECK_EQ(0, feraiseexcept(raise));
451                                 ATF_CHECK_EQ(raise, fetestexcept(ALL_STD_EXCEPT));
452
453                                 ATF_CHECK_EQ(0, sigaction(SIGFPE, &act, NULL));
454                                 switch (pass) {
455                                 case 0:
456                                         raiseexcept(except);
457                                 case 1:
458                                         feraiseexcept(except);
459                                 default:
460                                         ATF_REQUIRE(0);
461                                 }
462                                 ATF_REQUIRE(0);
463                         default:        /* parent */
464                                 ATF_REQUIRE(wait(&status) > 0);
465                                 /*
466                                  * Avoid assert() here so that it's possible
467                                  * to examine a failed child's core dump.
468                                  */
469                                 if (!WIFEXITED(status))
470                                         errx(1, "child aborted\n");
471                                 ATF_CHECK_EQ(0, WEXITSTATUS(status));
472                                 break;
473                         case -1:        /* error */
474                                 ATF_REQUIRE(0);
475                         }
476                 }
477         }
478         ATF_CHECK_EQ(0, fetestexcept(FE_ALL_EXCEPT));
479 }
480
481 /*
482  * Test feholdexcept() and feupdateenv().
483  *
484  * Prerequisites: fetestexcept(), fegetround(), fesetround(),
485  *      fedisableexcept(), feenableexcept()
486  */
487 ATF_TC_WITHOUT_HEAD(feholdupdate);
488 ATF_TC_BODY(feholdupdate, tc)
489 {
490         fenv_t env;
491
492         struct sigaction act;
493         int except, pass, status, raise;
494         unsigned i;
495
496         sigemptyset(&act.sa_mask);
497         act.sa_flags = 0;
498         act.sa_handler = trap_handler;
499         for (pass = 0; pass < 2; pass++) {
500                 for (i = 0; i < NEXCEPTS; i++) {
501                         except = std_excepts[i];
502                         /* over/underflow may also raise inexact */
503                         if (except == FE_INEXACT)
504                                 raise = FE_DIVBYZERO | FE_INVALID;
505                         else
506                                 raise = ALL_STD_EXCEPT ^ except;
507
508                         /*
509                          * We need to fork a child process because
510                          * there isn't a portable way to recover from
511                          * a floating-point exception.
512                          */
513                         switch(fork()) {
514                         case 0:         /* child */
515                                 /*
516                                  * We don't want to cause a fatal exception in
517                                  * the child until the second pass, so we can
518                                  * check other properties of feupdateenv().
519                                  */
520                                 if (pass == 1)
521                                         ATF_REQUIRE_EQ(0, feenableexcept(except) & ALL_STD_EXCEPT);
522                                 raiseexcept(raise);
523                                 ATF_CHECK_EQ(0, fesetround(FE_DOWNWARD));
524                                 ATF_CHECK_EQ(0, feholdexcept(&env));
525                                 ATF_CHECK_EQ(0, fetestexcept(FE_ALL_EXCEPT));
526                                 raiseexcept(except);
527                                 ATF_CHECK_EQ(0, fesetround(FE_UPWARD));
528
529                                 if (pass == 1)
530                                         ATF_CHECK_EQ(0, sigaction(SIGFPE, &act, NULL));
531                                 ATF_CHECK_EQ(0, feupdateenv(&env));
532                                 ATF_CHECK_EQ(FE_DOWNWARD, fegetround());
533                                 ATF_CHECK_EQ((except | raise), fetestexcept(ALL_STD_EXCEPT));
534
535                                 ATF_CHECK_EQ(0, pass);
536                                 _exit(0);
537                         default:        /* parent */
538                                 ATF_REQUIRE(wait(&status) > 0);
539                                 /*
540                                  * Avoid assert() here so that it's possible
541                                  * to examine a failed child's core dump.
542                                  */
543                                 if (!WIFEXITED(status))
544                                         errx(1, "child aborted\n");
545                                 ATF_CHECK_EQ(0, WEXITSTATUS(status));
546                                 break;
547                         case -1:        /* error */
548                                 ATF_REQUIRE(0);
549                         }
550                 }
551         }
552         ATF_CHECK_EQ(0, fetestexcept(FE_ALL_EXCEPT));
553 }
554
555 ATF_TP_ADD_TCS(tp)
556 {
557         ATF_TP_ADD_TC(tp, dfl_env);
558         ATF_TP_ADD_TC(tp, fetestclearexcept);
559         ATF_TP_ADD_TC(tp, fegsetexceptflag);
560         ATF_TP_ADD_TC(tp, feraiseexcept);
561         ATF_TP_ADD_TC(tp, fegsetround);
562         ATF_TP_ADD_TC(tp, fegsetenv);
563         ATF_TP_ADD_TC(tp, masking);
564         ATF_TP_ADD_TC(tp, feholdupdate);
565
566         return (atf_no_error());
567 }