Remove building with NOCRYPTO option
[minix3.git] / external / bsd / atf / dist / atf-c / tc.c
blob72151509f09e25247e85e44d65d414af676e4a64
1 /*
2 * Automated Testing Framework (atf)
4 * Copyright (c) 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <sys/uio.h>
34 #include <errno.h>
35 #include <fcntl.h>
36 #include <stdarg.h>
37 #include <stdbool.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <unistd.h>
43 #include "atf-c/defs.h"
44 #include "atf-c/error.h"
45 #include "atf-c/tc.h"
47 #include "detail/env.h"
48 #include "detail/fs.h"
49 #include "detail/map.h"
50 #include "detail/sanity.h"
51 #include "detail/text.h"
53 /* ---------------------------------------------------------------------
54 * Auxiliary functions.
55 * --------------------------------------------------------------------- */
57 enum expect_type {
58 EXPECT_PASS,
59 EXPECT_FAIL,
60 EXPECT_EXIT,
61 EXPECT_SIGNAL,
62 EXPECT_DEATH,
63 EXPECT_TIMEOUT,
66 struct context {
67 const atf_tc_t *tc;
68 const char *resfile;
69 size_t fail_count;
71 enum expect_type expect;
72 atf_dynstr_t expect_reason;
73 size_t expect_previous_fail_count;
74 size_t expect_fail_count;
75 int expect_exitcode;
76 int expect_signo;
79 static void context_init(struct context *, const atf_tc_t *, const char *);
80 static void check_fatal_error(atf_error_t);
81 static void report_fatal_error(const char *, ...)
82 ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(1, 2)
83 ATF_DEFS_ATTRIBUTE_NORETURN;
84 static atf_error_t write_resfile(const int, const char *, const int,
85 const atf_dynstr_t *);
86 static void create_resfile(const char *, const char *, const int,
87 atf_dynstr_t *);
88 static void error_in_expect(struct context *, const char *, ...)
89 ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(2, 3)
90 ATF_DEFS_ATTRIBUTE_NORETURN;
91 static void validate_expect(struct context *);
92 static void expected_failure(struct context *, atf_dynstr_t *)
93 ATF_DEFS_ATTRIBUTE_NORETURN;
94 static void fail_requirement(struct context *, atf_dynstr_t *)
95 ATF_DEFS_ATTRIBUTE_NORETURN;
96 static void fail_check(struct context *, atf_dynstr_t *);
97 static void pass(struct context *)
98 ATF_DEFS_ATTRIBUTE_NORETURN;
99 static void skip(struct context *, atf_dynstr_t *)
100 ATF_DEFS_ATTRIBUTE_NORETURN;
101 static void format_reason_ap(atf_dynstr_t *, const char *, const size_t,
102 const char *, va_list)
103 ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(4, 0);
104 static void format_reason_fmt(atf_dynstr_t *, const char *, const size_t,
105 const char *, ...)
106 ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(4, 5);
107 static void errno_test(struct context *, const char *, const size_t,
108 const int, const char *, const bool,
109 void (*)(struct context *, atf_dynstr_t *));
110 static atf_error_t check_prog_in_dir(const char *, void *);
111 static atf_error_t check_prog(struct context *, const char *);
113 static void
114 context_init(struct context *ctx, const atf_tc_t *tc, const char *resfile)
116 ctx->tc = tc;
117 ctx->resfile = resfile;
118 ctx->fail_count = 0;
119 ctx->expect = EXPECT_PASS;
120 check_fatal_error(atf_dynstr_init(&ctx->expect_reason));
121 ctx->expect_previous_fail_count = 0;
122 ctx->expect_fail_count = 0;
123 ctx->expect_exitcode = 0;
124 ctx->expect_signo = 0;
127 static void
128 check_fatal_error(atf_error_t err)
130 if (atf_is_error(err)) {
131 char buf[1024];
132 atf_error_format(err, buf, sizeof(buf));
133 fprintf(stderr, "FATAL ERROR: %s\n", buf);
134 atf_error_free(err);
135 abort();
139 static void
140 report_fatal_error(const char *msg, ...)
142 va_list ap;
143 fprintf(stderr, "FATAL ERROR: ");
145 va_start(ap, msg);
146 vfprintf(stderr, msg, ap);
147 va_end(ap);
149 fprintf(stderr, "\n");
150 abort();
153 /** Writes to a results file.
155 * The results file is supposed to be already open.
157 * This function returns an error code instead of exiting in case of error
158 * because the caller needs to clean up the reason object before terminating.
160 static atf_error_t
161 write_resfile(const int fd, const char *result, const int arg,
162 const atf_dynstr_t *reason)
164 static char NL[] = "\n", CS[] = ": ";
165 char buf[64];
166 const char *r;
167 struct iovec iov[5];
168 ssize_t ret;
169 int count = 0;
171 INV(arg == -1 || reason != NULL);
173 #define UNCONST(a) ((void *)(unsigned long)(const void *)(a))
174 iov[count].iov_base = UNCONST(result);
175 iov[count++].iov_len = strlen(result);
177 if (reason != NULL) {
178 if (arg != -1) {
179 iov[count].iov_base = buf;
180 iov[count++].iov_len = snprintf(buf, sizeof(buf), "(%d)", arg);
183 iov[count].iov_base = CS;
184 iov[count++].iov_len = sizeof(CS) - 1;
186 r = atf_dynstr_cstring(reason);
187 iov[count].iov_base = UNCONST(r);
188 iov[count++].iov_len = strlen(r);
190 #undef UNCONST
192 iov[count].iov_base = NL;
193 iov[count++].iov_len = sizeof(NL) - 1;
195 while ((ret = writev(fd, iov, count)) == -1 && errno == EINTR)
196 continue; /* Retry. */
197 if (ret != -1)
198 return atf_no_error();
200 return atf_libc_error(
201 errno, "Failed to write results file; result %s, reason %s", result,
202 reason == NULL ? "null" : atf_dynstr_cstring(reason));
205 /** Creates a results file.
207 * The input reason is released in all cases.
209 * An error in this function is considered to be fatal, hence why it does
210 * not return any error code.
212 static void
213 create_resfile(const char *resfile, const char *result, const int arg,
214 atf_dynstr_t *reason)
216 atf_error_t err;
218 if (strcmp("/dev/stdout", resfile) == 0) {
219 err = write_resfile(STDOUT_FILENO, result, arg, reason);
220 } else if (strcmp("/dev/stderr", resfile) == 0) {
221 err = write_resfile(STDERR_FILENO, result, arg, reason);
222 } else {
223 const int fd = open(resfile, O_WRONLY | O_CREAT | O_TRUNC,
224 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
225 if (fd == -1) {
226 err = atf_libc_error(errno, "Cannot create results file '%s'",
227 resfile);
228 } else {
229 err = write_resfile(fd, result, arg, reason);
230 close(fd);
234 if (reason != NULL)
235 atf_dynstr_fini(reason);
237 check_fatal_error(err);
240 /** Fails a test case if validate_expect fails. */
241 static void
242 error_in_expect(struct context *ctx, const char *fmt, ...)
244 atf_dynstr_t reason;
245 va_list ap;
247 va_start(ap, fmt);
248 format_reason_ap(&reason, NULL, 0, fmt, ap);
249 va_end(ap);
251 ctx->expect = EXPECT_PASS; /* Ensure fail_requirement really fails. */
252 fail_requirement(ctx, &reason);
255 /** Ensures that the "expect" state is correct.
257 * Call this function before modifying the current value of expect.
259 static void
260 validate_expect(struct context *ctx)
262 if (ctx->expect == EXPECT_DEATH) {
263 error_in_expect(ctx, "Test case was expected to terminate abruptly "
264 "but it continued execution");
265 } else if (ctx->expect == EXPECT_EXIT) {
266 error_in_expect(ctx, "Test case was expected to exit cleanly but it "
267 "continued execution");
268 } else if (ctx->expect == EXPECT_FAIL) {
269 if (ctx->expect_fail_count == ctx->expect_previous_fail_count)
270 error_in_expect(ctx, "Test case was expecting a failure but none "
271 "were raised");
272 else
273 INV(ctx->expect_fail_count > ctx->expect_previous_fail_count);
274 } else if (ctx->expect == EXPECT_PASS) {
275 /* Nothing to validate. */
276 } else if (ctx->expect == EXPECT_SIGNAL) {
277 error_in_expect(ctx, "Test case was expected to receive a termination "
278 "signal but it continued execution");
279 } else if (ctx->expect == EXPECT_TIMEOUT) {
280 error_in_expect(ctx, "Test case was expected to hang but it continued "
281 "execution");
282 } else
283 UNREACHABLE;
286 static void
287 expected_failure(struct context *ctx, atf_dynstr_t *reason)
289 check_fatal_error(atf_dynstr_prepend_fmt(reason, "%s: ",
290 atf_dynstr_cstring(&ctx->expect_reason)));
291 create_resfile(ctx->resfile, "expected_failure", -1, reason);
292 exit(EXIT_SUCCESS);
295 static void
296 fail_requirement(struct context *ctx, atf_dynstr_t *reason)
298 if (ctx->expect == EXPECT_FAIL) {
299 expected_failure(ctx, reason);
300 } else if (ctx->expect == EXPECT_PASS) {
301 create_resfile(ctx->resfile, "failed", -1, reason);
302 exit(EXIT_FAILURE);
303 } else {
304 error_in_expect(ctx, "Test case raised a failure but was not "
305 "expecting one; reason was %s", atf_dynstr_cstring(reason));
307 UNREACHABLE;
310 static void
311 fail_check(struct context *ctx, atf_dynstr_t *reason)
313 if (ctx->expect == EXPECT_FAIL) {
314 fprintf(stderr, "*** Expected check failure: %s: %s\n",
315 atf_dynstr_cstring(&ctx->expect_reason),
316 atf_dynstr_cstring(reason));
317 ctx->expect_fail_count++;
318 } else if (ctx->expect == EXPECT_PASS) {
319 fprintf(stderr, "*** Check failed: %s\n", atf_dynstr_cstring(reason));
320 ctx->fail_count++;
321 } else {
322 error_in_expect(ctx, "Test case raised a failure but was not "
323 "expecting one; reason was %s", atf_dynstr_cstring(reason));
326 atf_dynstr_fini(reason);
329 static void
330 pass(struct context *ctx)
332 if (ctx->expect == EXPECT_FAIL) {
333 error_in_expect(ctx, "Test case was expecting a failure but got "
334 "a pass instead");
335 } else if (ctx->expect == EXPECT_PASS) {
336 create_resfile(ctx->resfile, "passed", -1, NULL);
337 exit(EXIT_SUCCESS);
338 } else {
339 error_in_expect(ctx, "Test case asked to explicitly pass but was "
340 "not expecting such condition");
342 UNREACHABLE;
345 static void
346 skip(struct context *ctx, atf_dynstr_t *reason)
348 if (ctx->expect == EXPECT_PASS) {
349 create_resfile(ctx->resfile, "skipped", -1, reason);
350 exit(EXIT_SUCCESS);
351 } else {
352 error_in_expect(ctx, "Can only skip a test case when running in "
353 "expect pass mode");
355 UNREACHABLE;
358 /** Formats a failure/skip reason message.
360 * The formatted reason is stored in out_reason. out_reason is initialized
361 * in this function and is supposed to be released by the caller. In general,
362 * the reason will eventually be fed to create_resfile, which will release
363 * it.
365 * Errors in this function are fatal. Rationale being: reasons are used to
366 * create results files; if we can't format the reason correctly, the result
367 * of the test program will be bogus. So it's better to just exit with a
368 * fatal error.
370 static void
371 format_reason_ap(atf_dynstr_t *out_reason,
372 const char *source_file, const size_t source_line,
373 const char *reason, va_list ap)
375 atf_error_t err;
377 if (source_file != NULL) {
378 err = atf_dynstr_init_fmt(out_reason, "%s:%zd: ", source_file,
379 source_line);
380 } else {
381 PRE(source_line == 0);
382 err = atf_dynstr_init(out_reason);
385 if (!atf_is_error(err)) {
386 va_list ap2;
387 va_copy(ap2, ap);
388 err = atf_dynstr_append_ap(out_reason, reason, ap2);
389 va_end(ap2);
392 check_fatal_error(err);
395 static void
396 format_reason_fmt(atf_dynstr_t *out_reason,
397 const char *source_file, const size_t source_line,
398 const char *reason, ...)
400 va_list ap;
402 va_start(ap, reason);
403 format_reason_ap(out_reason, source_file, source_line, reason, ap);
404 va_end(ap);
407 static void
408 errno_test(struct context *ctx, const char *file, const size_t line,
409 const int exp_errno, const char *expr_str,
410 const bool expr_result,
411 void (*fail_func)(struct context *, atf_dynstr_t *))
413 const int actual_errno = errno;
415 if (expr_result) {
416 if (exp_errno != actual_errno) {
417 atf_dynstr_t reason;
419 format_reason_fmt(&reason, file, line, "Expected errno %d, got %d, "
420 "in %s", exp_errno, actual_errno, expr_str);
421 fail_func(ctx, &reason);
423 } else {
424 atf_dynstr_t reason;
426 format_reason_fmt(&reason, file, line, "Expected true value in %s",
427 expr_str);
428 fail_func(ctx, &reason);
432 struct prog_found_pair {
433 const char *prog;
434 bool found;
437 static atf_error_t
438 check_prog_in_dir(const char *dir, void *data)
440 struct prog_found_pair *pf = data;
441 atf_error_t err;
443 if (pf->found)
444 err = atf_no_error();
445 else {
446 atf_fs_path_t p;
448 err = atf_fs_path_init_fmt(&p, "%s/%s", dir, pf->prog);
449 if (atf_is_error(err))
450 goto out_p;
452 err = atf_fs_eaccess(&p, atf_fs_access_x);
453 if (!atf_is_error(err))
454 pf->found = true;
455 else {
456 atf_error_free(err);
457 INV(!pf->found);
458 err = atf_no_error();
461 out_p:
462 atf_fs_path_fini(&p);
465 return err;
468 static atf_error_t
469 check_prog(struct context *ctx, const char *prog)
471 atf_error_t err;
472 atf_fs_path_t p;
474 err = atf_fs_path_init_fmt(&p, "%s", prog);
475 if (atf_is_error(err))
476 goto out;
478 if (atf_fs_path_is_absolute(&p)) {
479 err = atf_fs_eaccess(&p, atf_fs_access_x);
480 if (atf_is_error(err)) {
481 atf_dynstr_t reason;
483 atf_error_free(err);
484 atf_fs_path_fini(&p);
485 format_reason_fmt(&reason, NULL, 0, "The required program %s could "
486 "not be found", prog);
487 skip(ctx, &reason);
489 } else {
490 const char *path = atf_env_get("PATH");
491 struct prog_found_pair pf;
492 atf_fs_path_t bp;
494 err = atf_fs_path_branch_path(&p, &bp);
495 if (atf_is_error(err))
496 goto out_p;
498 if (strcmp(atf_fs_path_cstring(&bp), ".") != 0) {
499 atf_fs_path_fini(&bp);
500 atf_fs_path_fini(&p);
502 report_fatal_error("Relative paths are not allowed when searching "
503 "for a program (%s)", prog);
504 UNREACHABLE;
507 pf.prog = prog;
508 pf.found = false;
509 err = atf_text_for_each_word(path, ":", check_prog_in_dir, &pf);
510 if (atf_is_error(err))
511 goto out_bp;
513 if (!pf.found) {
514 atf_dynstr_t reason;
516 atf_fs_path_fini(&bp);
517 atf_fs_path_fini(&p);
518 format_reason_fmt(&reason, NULL, 0, "The required program %s could "
519 "not be found in the PATH", prog);
520 fail_requirement(ctx, &reason);
523 out_bp:
524 atf_fs_path_fini(&bp);
527 out_p:
528 atf_fs_path_fini(&p);
529 out:
530 return err;
533 /* ---------------------------------------------------------------------
534 * The "atf_tc" type.
535 * --------------------------------------------------------------------- */
537 struct atf_tc_impl {
538 const char *m_ident;
540 atf_map_t m_vars;
541 atf_map_t m_config;
543 atf_tc_head_t m_head;
544 atf_tc_body_t m_body;
545 atf_tc_cleanup_t m_cleanup;
549 * Constructors/destructors.
552 atf_error_t
553 atf_tc_init(atf_tc_t *tc, const char *ident, atf_tc_head_t head,
554 atf_tc_body_t body, atf_tc_cleanup_t cleanup,
555 const char *const *config)
557 atf_error_t err;
559 tc->pimpl = malloc(sizeof(struct atf_tc_impl));
560 if (tc->pimpl == NULL) {
561 err = atf_no_memory_error();
562 goto err;
565 tc->pimpl->m_ident = ident;
566 tc->pimpl->m_head = head;
567 tc->pimpl->m_body = body;
568 tc->pimpl->m_cleanup = cleanup;
570 err = atf_map_init_charpp(&tc->pimpl->m_config, config);
571 if (atf_is_error(err))
572 goto err;
574 err = atf_map_init(&tc->pimpl->m_vars);
575 if (atf_is_error(err))
576 goto err_vars;
578 err = atf_tc_set_md_var(tc, "ident", "%s", ident);
579 if (atf_is_error(err))
580 goto err_map;
582 if (cleanup != NULL) {
583 err = atf_tc_set_md_var(tc, "has.cleanup", "true");
584 if (atf_is_error(err))
585 goto err_map;
588 /* XXX Should the head be able to return error codes? */
589 if (tc->pimpl->m_head != NULL)
590 tc->pimpl->m_head(tc);
592 if (strcmp(atf_tc_get_md_var(tc, "ident"), ident) != 0) {
593 report_fatal_error("Test case head modified the read-only 'ident' "
594 "property");
595 UNREACHABLE;
598 INV(!atf_is_error(err));
599 return err;
601 err_map:
602 atf_map_fini(&tc->pimpl->m_vars);
603 err_vars:
604 atf_map_fini(&tc->pimpl->m_config);
605 err:
606 return err;
609 atf_error_t
610 atf_tc_init_pack(atf_tc_t *tc, const atf_tc_pack_t *pack,
611 const char *const *config)
613 return atf_tc_init(tc, pack->m_ident, pack->m_head, pack->m_body,
614 pack->m_cleanup, config);
617 void
618 atf_tc_fini(atf_tc_t *tc)
620 atf_map_fini(&tc->pimpl->m_vars);
621 free(tc->pimpl);
625 * Getters.
628 const char *
629 atf_tc_get_ident(const atf_tc_t *tc)
631 return tc->pimpl->m_ident;
634 const char *
635 atf_tc_get_config_var(const atf_tc_t *tc, const char *name)
637 const char *val;
638 atf_map_citer_t iter;
640 PRE(atf_tc_has_config_var(tc, name));
641 iter = atf_map_find_c(&tc->pimpl->m_config, name);
642 val = atf_map_citer_data(iter);
643 INV(val != NULL);
645 return val;
648 const char *
649 atf_tc_get_config_var_wd(const atf_tc_t *tc, const char *name,
650 const char *defval)
652 const char *val;
654 if (!atf_tc_has_config_var(tc, name))
655 val = defval;
656 else
657 val = atf_tc_get_config_var(tc, name);
659 return val;
662 bool
663 atf_tc_get_config_var_as_bool(const atf_tc_t *tc, const char *name)
665 bool val;
666 const char *strval;
667 atf_error_t err;
669 strval = atf_tc_get_config_var(tc, name);
670 err = atf_text_to_bool(strval, &val);
671 if (atf_is_error(err)) {
672 atf_error_free(err);
673 atf_tc_fail("Configuration variable %s does not have a valid "
674 "boolean value; found %s", name, strval);
677 return val;
680 bool
681 atf_tc_get_config_var_as_bool_wd(const atf_tc_t *tc, const char *name,
682 const bool defval)
684 bool val;
686 if (!atf_tc_has_config_var(tc, name))
687 val = defval;
688 else
689 val = atf_tc_get_config_var_as_bool(tc, name);
691 return val;
694 long
695 atf_tc_get_config_var_as_long(const atf_tc_t *tc, const char *name)
697 long val;
698 const char *strval;
699 atf_error_t err;
701 strval = atf_tc_get_config_var(tc, name);
702 err = atf_text_to_long(strval, &val);
703 if (atf_is_error(err)) {
704 atf_error_free(err);
705 atf_tc_fail("Configuration variable %s does not have a valid "
706 "long value; found %s", name, strval);
709 return val;
712 long
713 atf_tc_get_config_var_as_long_wd(const atf_tc_t *tc, const char *name,
714 const long defval)
716 long val;
718 if (!atf_tc_has_config_var(tc, name))
719 val = defval;
720 else
721 val = atf_tc_get_config_var_as_long(tc, name);
723 return val;
726 const char *
727 atf_tc_get_md_var(const atf_tc_t *tc, const char *name)
729 const char *val;
730 atf_map_citer_t iter;
732 PRE(atf_tc_has_md_var(tc, name));
733 iter = atf_map_find_c(&tc->pimpl->m_vars, name);
734 val = atf_map_citer_data(iter);
735 INV(val != NULL);
737 return val;
740 char **
741 atf_tc_get_md_vars(const atf_tc_t *tc)
743 return atf_map_to_charpp(&tc->pimpl->m_vars);
746 bool
747 atf_tc_has_config_var(const atf_tc_t *tc, const char *name)
749 atf_map_citer_t end, iter;
751 iter = atf_map_find_c(&tc->pimpl->m_config, name);
752 end = atf_map_end_c(&tc->pimpl->m_config);
753 return !atf_equal_map_citer_map_citer(iter, end);
756 bool
757 atf_tc_has_md_var(const atf_tc_t *tc, const char *name)
759 atf_map_citer_t end, iter;
761 iter = atf_map_find_c(&tc->pimpl->m_vars, name);
762 end = atf_map_end_c(&tc->pimpl->m_vars);
763 return !atf_equal_map_citer_map_citer(iter, end);
767 * Modifiers.
770 atf_error_t
771 atf_tc_set_md_var(atf_tc_t *tc, const char *name, const char *fmt, ...)
773 atf_error_t err;
774 char *value;
775 va_list ap;
777 va_start(ap, fmt);
778 err = atf_text_format_ap(&value, fmt, ap);
779 va_end(ap);
781 if (!atf_is_error(err))
782 err = atf_map_insert(&tc->pimpl->m_vars, name, value, true);
783 else
784 free(value);
786 return err;
789 /* ---------------------------------------------------------------------
790 * Free functions, as they should be publicly but they can't.
791 * --------------------------------------------------------------------- */
793 static void _atf_tc_fail(struct context *, const char *, va_list)
794 ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(2, 0)
795 ATF_DEFS_ATTRIBUTE_NORETURN;
796 static void _atf_tc_fail_nonfatal(struct context *, const char *, va_list)
797 ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(2, 0);
798 static void _atf_tc_fail_check(struct context *, const char *, const size_t,
799 const char *, va_list)
800 ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(4, 0);
801 static void _atf_tc_fail_requirement(struct context *, const char *,
802 const size_t, const char *, va_list)
803 ATF_DEFS_ATTRIBUTE_NORETURN
804 ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(4, 0);
805 static void _atf_tc_pass(struct context *) ATF_DEFS_ATTRIBUTE_NORETURN;
806 static void _atf_tc_require_prog(struct context *, const char *);
807 static void _atf_tc_skip(struct context *, const char *, va_list)
808 ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(2, 0)
809 ATF_DEFS_ATTRIBUTE_NORETURN;
810 static void _atf_tc_check_errno(struct context *, const char *, const size_t,
811 const int, const char *, const bool);
812 static void _atf_tc_require_errno(struct context *, const char *, const size_t,
813 const int, const char *, const bool);
814 static void _atf_tc_expect_pass(struct context *);
815 static void _atf_tc_expect_fail(struct context *, const char *, va_list)
816 ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(2, 0);
817 static void _atf_tc_expect_exit(struct context *, const int, const char *,
818 va_list) ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(3, 0);
819 static void _atf_tc_expect_signal(struct context *, const int, const char *,
820 va_list) ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(3, 0);
821 static void _atf_tc_expect_death(struct context *, const char *,
822 va_list) ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(2, 0);
824 static void
825 _atf_tc_fail(struct context *ctx, const char *fmt, va_list ap)
827 va_list ap2;
828 atf_dynstr_t reason;
830 va_copy(ap2, ap);
831 format_reason_ap(&reason, NULL, 0, fmt, ap2);
832 va_end(ap2);
834 fail_requirement(ctx, &reason);
835 UNREACHABLE;
838 static void
839 _atf_tc_fail_nonfatal(struct context *ctx, const char *fmt, va_list ap)
841 va_list ap2;
842 atf_dynstr_t reason;
844 va_copy(ap2, ap);
845 format_reason_ap(&reason, NULL, 0, fmt, ap2);
846 va_end(ap2);
848 fail_check(ctx, &reason);
851 static void
852 _atf_tc_fail_check(struct context *ctx, const char *file, const size_t line,
853 const char *fmt, va_list ap)
855 va_list ap2;
856 atf_dynstr_t reason;
858 va_copy(ap2, ap);
859 format_reason_ap(&reason, file, line, fmt, ap2);
860 va_end(ap2);
862 fail_check(ctx, &reason);
865 static void
866 _atf_tc_fail_requirement(struct context *ctx, const char *file,
867 const size_t line, const char *fmt, va_list ap)
869 va_list ap2;
870 atf_dynstr_t reason;
872 va_copy(ap2, ap);
873 format_reason_ap(&reason, file, line, fmt, ap2);
874 va_end(ap2);
876 fail_requirement(ctx, &reason);
877 UNREACHABLE;
880 static void
881 _atf_tc_pass(struct context *ctx)
883 pass(ctx);
884 UNREACHABLE;
887 static void
888 _atf_tc_require_prog(struct context *ctx, const char *prog)
890 check_fatal_error(check_prog(ctx, prog));
893 static void
894 _atf_tc_skip(struct context *ctx, const char *fmt, va_list ap)
896 atf_dynstr_t reason;
897 va_list ap2;
899 va_copy(ap2, ap);
900 format_reason_ap(&reason, NULL, 0, fmt, ap2);
901 va_end(ap2);
903 skip(ctx, &reason);
906 static void
907 _atf_tc_check_errno(struct context *ctx, const char *file, const size_t line,
908 const int exp_errno, const char *expr_str,
909 const bool expr_result)
911 errno_test(ctx, file, line, exp_errno, expr_str, expr_result, fail_check);
914 static void
915 _atf_tc_require_errno(struct context *ctx, const char *file, const size_t line,
916 const int exp_errno, const char *expr_str,
917 const bool expr_result)
919 errno_test(ctx, file, line, exp_errno, expr_str, expr_result,
920 fail_requirement);
923 static void
924 _atf_tc_expect_pass(struct context *ctx)
926 validate_expect(ctx);
928 ctx->expect = EXPECT_PASS;
931 static void
932 _atf_tc_expect_fail(struct context *ctx, const char *reason, va_list ap)
934 va_list ap2;
936 validate_expect(ctx);
938 ctx->expect = EXPECT_FAIL;
939 atf_dynstr_fini(&ctx->expect_reason);
940 va_copy(ap2, ap);
941 check_fatal_error(atf_dynstr_init_ap(&ctx->expect_reason, reason, ap2));
942 va_end(ap2);
943 ctx->expect_previous_fail_count = ctx->expect_fail_count;
946 static void
947 _atf_tc_expect_exit(struct context *ctx, const int exitcode, const char *reason,
948 va_list ap)
950 va_list ap2;
951 atf_dynstr_t formatted;
953 validate_expect(ctx);
955 ctx->expect = EXPECT_EXIT;
956 va_copy(ap2, ap);
957 check_fatal_error(atf_dynstr_init_ap(&formatted, reason, ap2));
958 va_end(ap2);
960 create_resfile(ctx->resfile, "expected_exit", exitcode, &formatted);
963 static void
964 _atf_tc_expect_signal(struct context *ctx, const int signo, const char *reason,
965 va_list ap)
967 va_list ap2;
968 atf_dynstr_t formatted;
970 validate_expect(ctx);
972 ctx->expect = EXPECT_SIGNAL;
973 va_copy(ap2, ap);
974 check_fatal_error(atf_dynstr_init_ap(&formatted, reason, ap2));
975 va_end(ap2);
977 create_resfile(ctx->resfile, "expected_signal", signo, &formatted);
980 static void
981 _atf_tc_expect_death(struct context *ctx, const char *reason, va_list ap)
983 va_list ap2;
984 atf_dynstr_t formatted;
986 validate_expect(ctx);
988 ctx->expect = EXPECT_DEATH;
989 va_copy(ap2, ap);
990 check_fatal_error(atf_dynstr_init_ap(&formatted, reason, ap2));
991 va_end(ap2);
993 create_resfile(ctx->resfile, "expected_death", -1, &formatted);
996 ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(2, 0)
997 static void
998 _atf_tc_expect_timeout(struct context *ctx, const char *reason, va_list ap)
1000 va_list ap2;
1001 atf_dynstr_t formatted;
1003 validate_expect(ctx);
1005 ctx->expect = EXPECT_TIMEOUT;
1006 va_copy(ap2, ap);
1007 check_fatal_error(atf_dynstr_init_ap(&formatted, reason, ap2));
1008 va_end(ap2);
1010 create_resfile(ctx->resfile, "expected_timeout", -1, &formatted);
1013 /* ---------------------------------------------------------------------
1014 * Free functions.
1015 * --------------------------------------------------------------------- */
1017 static struct context Current;
1019 atf_error_t
1020 atf_tc_run(const atf_tc_t *tc, const char *resfile)
1022 context_init(&Current, tc, resfile);
1024 tc->pimpl->m_body(tc);
1026 validate_expect(&Current);
1028 if (Current.fail_count > 0) {
1029 atf_dynstr_t reason;
1031 format_reason_fmt(&reason, NULL, 0, "%zu checks failed; see output for "
1032 "more details", Current.fail_count);
1033 fail_requirement(&Current, &reason);
1034 } else if (Current.expect_fail_count > 0) {
1035 atf_dynstr_t reason;
1037 format_reason_fmt(&reason, NULL, 0, "%zu checks failed as expected; "
1038 "see output for more details", Current.expect_fail_count);
1039 expected_failure(&Current, &reason);
1040 } else {
1041 pass(&Current);
1043 UNREACHABLE;
1044 return atf_no_error();
1047 atf_error_t
1048 atf_tc_cleanup(const atf_tc_t *tc)
1050 if (tc->pimpl->m_cleanup != NULL)
1051 tc->pimpl->m_cleanup(tc);
1052 return atf_no_error(); /* XXX */
1055 /* ---------------------------------------------------------------------
1056 * Free functions that depend on Current.
1057 * --------------------------------------------------------------------- */
1060 * All the functions below provide delegates to other internal functions
1061 * (prefixed by _) that take the current test case as an argument to
1062 * prevent them from accessing global state. This is to keep the side-
1063 * effects of the internal functions clearer and easier to understand.
1065 * The public API should never have hid the fact that it needs access to
1066 * the current test case (other than maybe in the macros), but changing it
1067 * is hard. TODO: Revisit in the future.
1070 void
1071 atf_tc_fail(const char *fmt, ...)
1073 va_list ap;
1075 PRE(Current.tc != NULL);
1077 va_start(ap, fmt);
1078 _atf_tc_fail(&Current, fmt, ap);
1079 va_end(ap);
1082 void
1083 atf_tc_fail_nonfatal(const char *fmt, ...)
1085 va_list ap;
1087 PRE(Current.tc != NULL);
1089 va_start(ap, fmt);
1090 _atf_tc_fail_nonfatal(&Current, fmt, ap);
1091 va_end(ap);
1094 void
1095 atf_tc_fail_check(const char *file, const size_t line, const char *fmt, ...)
1097 va_list ap;
1099 PRE(Current.tc != NULL);
1101 va_start(ap, fmt);
1102 _atf_tc_fail_check(&Current, file, line, fmt, ap);
1103 va_end(ap);
1106 void
1107 atf_tc_fail_requirement(const char *file, const size_t line,
1108 const char *fmt, ...)
1110 va_list ap;
1112 PRE(Current.tc != NULL);
1114 va_start(ap, fmt);
1115 _atf_tc_fail_requirement(&Current, file, line, fmt, ap);
1116 va_end(ap);
1119 void
1120 atf_tc_pass(void)
1122 PRE(Current.tc != NULL);
1124 _atf_tc_pass(&Current);
1127 void
1128 atf_tc_require_prog(const char *prog)
1130 PRE(Current.tc != NULL);
1132 _atf_tc_require_prog(&Current, prog);
1135 void
1136 atf_tc_skip(const char *fmt, ...)
1138 va_list ap;
1140 PRE(Current.tc != NULL);
1142 va_start(ap, fmt);
1143 _atf_tc_skip(&Current, fmt, ap);
1144 va_end(ap);
1147 void
1148 atf_tc_check_errno(const char *file, const size_t line, const int exp_errno,
1149 const char *expr_str, const bool expr_result)
1151 PRE(Current.tc != NULL);
1153 _atf_tc_check_errno(&Current, file, line, exp_errno, expr_str,
1154 expr_result);
1157 void
1158 atf_tc_require_errno(const char *file, const size_t line, const int exp_errno,
1159 const char *expr_str, const bool expr_result)
1161 PRE(Current.tc != NULL);
1163 _atf_tc_require_errno(&Current, file, line, exp_errno, expr_str,
1164 expr_result);
1167 void
1168 atf_tc_expect_pass(void)
1170 PRE(Current.tc != NULL);
1172 _atf_tc_expect_pass(&Current);
1175 void
1176 atf_tc_expect_fail(const char *reason, ...)
1178 va_list ap;
1180 PRE(Current.tc != NULL);
1182 va_start(ap, reason);
1183 _atf_tc_expect_fail(&Current, reason, ap);
1184 va_end(ap);
1187 void
1188 atf_tc_expect_exit(const int exitcode, const char *reason, ...)
1190 va_list ap;
1192 PRE(Current.tc != NULL);
1194 va_start(ap, reason);
1195 _atf_tc_expect_exit(&Current, exitcode, reason, ap);
1196 va_end(ap);
1199 void
1200 atf_tc_expect_signal(const int signo, const char *reason, ...)
1202 va_list ap;
1204 PRE(Current.tc != NULL);
1206 va_start(ap, reason);
1207 _atf_tc_expect_signal(&Current, signo, reason, ap);
1208 va_end(ap);
1211 void
1212 atf_tc_expect_death(const char *reason, ...)
1214 va_list ap;
1216 PRE(Current.tc != NULL);
1218 va_start(ap, reason);
1219 _atf_tc_expect_death(&Current, reason, ap);
1220 va_end(ap);
1223 void
1224 atf_tc_expect_timeout(const char *reason, ...)
1226 va_list ap;
1228 PRE(Current.tc != NULL);
1230 va_start(ap, reason);
1231 _atf_tc_expect_timeout(&Current, reason, ap);
1232 va_end(ap);