Remove building with NOCRYPTO option
[minix.git] / external / bsd / bind / dist / unit / atf-src / atf-c / tc.c
blob3e32702ca9db0911479d2d6af6e9a2494f012998
1 /* $NetBSD: tc.c,v 1.3 2014/12/10 04:38:03 christos Exp $ */
3 /*
4 * Automated Testing Framework (atf)
6 * Copyright (c) 2008 The NetBSD Foundation, Inc.
7 * All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
19 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
25 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
27 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
29 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <sys/uio.h>
36 #include <errno.h>
37 #include <fcntl.h>
38 #include <stdarg.h>
39 #include <stdbool.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <unistd.h>
45 #include "atf-c/defs.h"
46 #include "atf-c/error.h"
47 #include "atf-c/tc.h"
49 #include "detail/env.h"
50 #include "detail/fs.h"
51 #include "detail/map.h"
52 #include "detail/sanity.h"
53 #include "detail/text.h"
55 /* ---------------------------------------------------------------------
56 * Auxiliary functions.
57 * --------------------------------------------------------------------- */
59 enum expect_type {
60 EXPECT_PASS,
61 EXPECT_FAIL,
62 EXPECT_EXIT,
63 EXPECT_SIGNAL,
64 EXPECT_DEATH,
65 EXPECT_TIMEOUT,
68 struct context {
69 const atf_tc_t *tc;
70 const char *resfile;
71 size_t fail_count;
73 enum expect_type expect;
74 atf_dynstr_t expect_reason;
75 size_t expect_previous_fail_count;
76 size_t expect_fail_count;
77 int expect_exitcode;
78 int expect_signo;
81 static void context_init(struct context *, const atf_tc_t *, const char *);
82 static void check_fatal_error(atf_error_t);
83 static void report_fatal_error(const char *, ...)
84 ATF_DEFS_ATTRIBUTE_NORETURN;
85 static atf_error_t write_resfile(const int, const char *, const int,
86 const atf_dynstr_t *);
87 static void create_resfile(const char *, const char *, const int,
88 atf_dynstr_t *);
89 static void error_in_expect(struct context *, const char *, ...)
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 static void format_reason_fmt(atf_dynstr_t *, const char *, const size_t,
104 const char *, ...);
105 static void errno_test(struct context *, const char *, const size_t,
106 const int, const char *, const bool,
107 void (*)(struct context *, atf_dynstr_t *));
108 static atf_error_t check_prog_in_dir(const char *, void *);
109 static atf_error_t check_prog(struct context *, const char *);
111 static void
112 context_init(struct context *ctx, const atf_tc_t *tc, const char *resfile)
114 ctx->tc = tc;
115 ctx->resfile = resfile;
116 ctx->fail_count = 0;
117 ctx->expect = EXPECT_PASS;
118 check_fatal_error(atf_dynstr_init(&ctx->expect_reason));
119 ctx->expect_previous_fail_count = 0;
120 ctx->expect_fail_count = 0;
121 ctx->expect_exitcode = 0;
122 ctx->expect_signo = 0;
125 static void
126 check_fatal_error(atf_error_t err)
128 if (atf_is_error(err)) {
129 char buf[1024];
130 atf_error_format(err, buf, sizeof(buf));
131 fprintf(stderr, "FATAL ERROR: %s\n", buf);
132 atf_error_free(err);
133 abort();
137 static void
138 report_fatal_error(const char *msg, ...)
140 va_list ap;
141 fprintf(stderr, "FATAL ERROR: ");
143 va_start(ap, msg);
144 vfprintf(stderr, msg, ap);
145 va_end(ap);
147 fprintf(stderr, "\n");
148 abort();
151 /** Writes to a results file.
153 * The results file is supposed to be already open.
155 * This function returns an error code instead of exiting in case of error
156 * because the caller needs to clean up the reason object before terminating.
158 static atf_error_t
159 write_resfile(const int fd, const char *result, const int arg,
160 const atf_dynstr_t *reason)
162 static char NL[] = "\n", CS[] = ": ";
163 char buf[64];
164 const char *r;
165 struct iovec iov[5];
166 ssize_t ret;
167 int count = 0;
169 INV(arg == -1 || reason != NULL);
171 #define UNCONST(a) ((void *)(unsigned long)(const void *)(a))
172 iov[count].iov_base = UNCONST(result);
173 iov[count++].iov_len = strlen(result);
175 if (reason != NULL) {
176 if (arg != -1) {
177 iov[count].iov_base = buf;
178 iov[count++].iov_len = snprintf(buf, sizeof(buf), "(%d)", arg);
181 iov[count].iov_base = CS;
182 iov[count++].iov_len = sizeof(CS) - 1;
184 r = atf_dynstr_cstring(reason);
185 iov[count].iov_base = UNCONST(r);
186 iov[count++].iov_len = strlen(r);
188 #undef UNCONST
190 iov[count].iov_base = NL;
191 iov[count++].iov_len = sizeof(NL) - 1;
193 while ((ret = writev(fd, iov, count)) == -1 && errno == EINTR)
194 continue; /* Retry. */
195 if (ret != -1)
196 return atf_no_error();
198 return atf_libc_error(
199 errno, "Failed to write results file; result %s, reason %s", result,
200 reason == NULL ? "null" : atf_dynstr_cstring(reason));
203 /** Creates a results file.
205 * The input reason is released in all cases.
207 * An error in this function is considered to be fatal, hence why it does
208 * not return any error code.
210 static void
211 create_resfile(const char *resfile, const char *result, const int arg,
212 atf_dynstr_t *reason)
214 atf_error_t err;
216 if (strcmp("/dev/stdout", resfile) == 0) {
217 err = write_resfile(STDOUT_FILENO, result, arg, reason);
218 } else if (strcmp("/dev/stderr", resfile) == 0) {
219 err = write_resfile(STDERR_FILENO, result, arg, reason);
220 } else {
221 const int fd = open(resfile, O_WRONLY | O_CREAT | O_TRUNC,
222 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
223 if (fd == -1) {
224 err = atf_libc_error(errno, "Cannot create results file '%s'",
225 resfile);
226 } else {
227 err = write_resfile(fd, result, arg, reason);
228 close(fd);
232 if (reason != NULL)
233 atf_dynstr_fini(reason);
235 check_fatal_error(err);
238 /** Fails a test case if validate_expect fails. */
239 static void
240 error_in_expect(struct context *ctx, const char *fmt, ...)
242 atf_dynstr_t reason;
243 va_list ap;
245 va_start(ap, fmt);
246 format_reason_ap(&reason, NULL, 0, fmt, ap);
247 va_end(ap);
249 ctx->expect = EXPECT_PASS; /* Ensure fail_requirement really fails. */
250 fail_requirement(ctx, &reason);
253 /** Ensures that the "expect" state is correct.
255 * Call this function before modifying the current value of expect.
257 static void
258 validate_expect(struct context *ctx)
260 if (ctx->expect == EXPECT_DEATH) {
261 error_in_expect(ctx, "Test case was expected to terminate abruptly "
262 "but it continued execution");
263 } else if (ctx->expect == EXPECT_EXIT) {
264 error_in_expect(ctx, "Test case was expected to exit cleanly but it "
265 "continued execution");
266 } else if (ctx->expect == EXPECT_FAIL) {
267 if (ctx->expect_fail_count == ctx->expect_previous_fail_count)
268 error_in_expect(ctx, "Test case was expecting a failure but none "
269 "were raised");
270 else
271 INV(ctx->expect_fail_count > ctx->expect_previous_fail_count);
272 } else if (ctx->expect == EXPECT_PASS) {
273 /* Nothing to validate. */
274 } else if (ctx->expect == EXPECT_SIGNAL) {
275 error_in_expect(ctx, "Test case was expected to receive a termination "
276 "signal but it continued execution");
277 } else if (ctx->expect == EXPECT_TIMEOUT) {
278 error_in_expect(ctx, "Test case was expected to hang but it continued "
279 "execution");
280 } else
281 UNREACHABLE;
284 static void
285 expected_failure(struct context *ctx, atf_dynstr_t *reason)
287 check_fatal_error(atf_dynstr_prepend_fmt(reason, "%s: ",
288 atf_dynstr_cstring(&ctx->expect_reason)));
289 create_resfile(ctx->resfile, "expected_failure", -1, reason);
290 exit(EXIT_SUCCESS);
293 static void
294 fail_requirement(struct context *ctx, atf_dynstr_t *reason)
296 if (ctx->expect == EXPECT_FAIL) {
297 expected_failure(ctx, reason);
298 } else if (ctx->expect == EXPECT_PASS) {
299 create_resfile(ctx->resfile, "failed", -1, reason);
300 exit(EXIT_FAILURE);
301 } else {
302 error_in_expect(ctx, "Test case raised a failure but was not "
303 "expecting one; reason was %s", atf_dynstr_cstring(reason));
305 UNREACHABLE;
308 static void
309 fail_check(struct context *ctx, atf_dynstr_t *reason)
311 if (ctx->expect == EXPECT_FAIL) {
312 fprintf(stderr, "*** Expected check failure: %s: %s\n",
313 atf_dynstr_cstring(&ctx->expect_reason),
314 atf_dynstr_cstring(reason));
315 ctx->expect_fail_count++;
316 } else if (ctx->expect == EXPECT_PASS) {
317 fprintf(stderr, "*** Check failed: %s\n", atf_dynstr_cstring(reason));
318 ctx->fail_count++;
319 } else {
320 error_in_expect(ctx, "Test case raised a failure but was not "
321 "expecting one; reason was %s", atf_dynstr_cstring(reason));
324 atf_dynstr_fini(reason);
327 static void
328 pass(struct context *ctx)
330 if (ctx->expect == EXPECT_FAIL) {
331 error_in_expect(ctx, "Test case was expecting a failure but got "
332 "a pass instead");
333 } else if (ctx->expect == EXPECT_PASS) {
334 create_resfile(ctx->resfile, "passed", -1, NULL);
335 exit(EXIT_SUCCESS);
336 } else {
337 error_in_expect(ctx, "Test case asked to explicitly pass but was "
338 "not expecting such condition");
340 UNREACHABLE;
343 static void
344 skip(struct context *ctx, atf_dynstr_t *reason)
346 if (ctx->expect == EXPECT_PASS) {
347 create_resfile(ctx->resfile, "skipped", -1, reason);
348 exit(EXIT_SUCCESS);
349 } else {
350 error_in_expect(ctx, "Can only skip a test case when running in "
351 "expect pass mode");
353 UNREACHABLE;
356 /** Formats a failure/skip reason message.
358 * The formatted reason is stored in out_reason. out_reason is initialized
359 * in this function and is supposed to be released by the caller. In general,
360 * the reason will eventually be fed to create_resfile, which will release
361 * it.
363 * Errors in this function are fatal. Rationale being: reasons are used to
364 * create results files; if we can't format the reason correctly, the result
365 * of the test program will be bogus. So it's better to just exit with a
366 * fatal error.
368 static void
369 format_reason_ap(atf_dynstr_t *out_reason,
370 const char *source_file, const size_t source_line,
371 const char *reason, va_list ap)
373 atf_error_t err;
375 if (source_file != NULL) {
376 err = atf_dynstr_init_fmt(out_reason, "%s:%zd: ", source_file,
377 source_line);
378 } else {
379 PRE(source_line == 0);
380 err = atf_dynstr_init(out_reason);
383 if (!atf_is_error(err)) {
384 va_list ap2;
385 va_copy(ap2, ap);
386 err = atf_dynstr_append_ap(out_reason, reason, ap2);
387 va_end(ap2);
390 check_fatal_error(err);
393 static void
394 format_reason_fmt(atf_dynstr_t *out_reason,
395 const char *source_file, const size_t source_line,
396 const char *reason, ...)
398 va_list ap;
400 va_start(ap, reason);
401 format_reason_ap(out_reason, source_file, source_line, reason, ap);
402 va_end(ap);
405 static void
406 errno_test(struct context *ctx, const char *file, const size_t line,
407 const int exp_errno, const char *expr_str,
408 const bool expr_result,
409 void (*fail_func)(struct context *, atf_dynstr_t *))
411 const int actual_errno = errno;
413 if (expr_result) {
414 if (exp_errno != actual_errno) {
415 atf_dynstr_t reason;
417 format_reason_fmt(&reason, file, line, "Expected errno %d, got %d, "
418 "in %s", exp_errno, actual_errno, expr_str);
419 fail_func(ctx, &reason);
421 } else {
422 atf_dynstr_t reason;
424 format_reason_fmt(&reason, file, line, "Expected true value in %s",
425 expr_str);
426 fail_func(ctx, &reason);
430 struct prog_found_pair {
431 const char *prog;
432 bool found;
435 static atf_error_t
436 check_prog_in_dir(const char *dir, void *data)
438 struct prog_found_pair *pf = data;
439 atf_error_t err;
441 if (pf->found)
442 err = atf_no_error();
443 else {
444 atf_fs_path_t p;
446 err = atf_fs_path_init_fmt(&p, "%s/%s", dir, pf->prog);
447 if (atf_is_error(err))
448 goto out_p;
450 err = atf_fs_eaccess(&p, atf_fs_access_x);
451 if (!atf_is_error(err))
452 pf->found = true;
453 else {
454 atf_error_free(err);
455 INV(!pf->found);
456 err = atf_no_error();
459 out_p:
460 atf_fs_path_fini(&p);
463 return err;
466 static atf_error_t
467 check_prog(struct context *ctx, const char *prog)
469 atf_error_t err;
470 atf_fs_path_t p;
472 err = atf_fs_path_init_fmt(&p, "%s", prog);
473 if (atf_is_error(err))
474 goto out;
476 if (atf_fs_path_is_absolute(&p)) {
477 err = atf_fs_eaccess(&p, atf_fs_access_x);
478 if (atf_is_error(err)) {
479 atf_dynstr_t reason;
481 atf_error_free(err);
482 atf_fs_path_fini(&p);
483 format_reason_fmt(&reason, NULL, 0, "The required program %s could "
484 "not be found", prog);
485 skip(ctx, &reason);
487 } else {
488 const char *path = atf_env_get("PATH");
489 struct prog_found_pair pf;
490 atf_fs_path_t bp;
492 err = atf_fs_path_branch_path(&p, &bp);
493 if (atf_is_error(err))
494 goto out_p;
496 if (strcmp(atf_fs_path_cstring(&bp), ".") != 0) {
497 atf_fs_path_fini(&bp);
498 atf_fs_path_fini(&p);
500 report_fatal_error("Relative paths are not allowed when searching "
501 "for a program (%s)", prog);
502 UNREACHABLE;
505 pf.prog = prog;
506 pf.found = false;
507 err = atf_text_for_each_word(path, ":", check_prog_in_dir, &pf);
508 if (atf_is_error(err))
509 goto out_bp;
511 if (!pf.found) {
512 atf_dynstr_t reason;
514 atf_fs_path_fini(&bp);
515 atf_fs_path_fini(&p);
516 format_reason_fmt(&reason, NULL, 0, "The required program %s could "
517 "not be found in the PATH", prog);
518 fail_requirement(ctx, &reason);
521 out_bp:
522 atf_fs_path_fini(&bp);
525 out_p:
526 atf_fs_path_fini(&p);
527 out:
528 return err;
531 /* ---------------------------------------------------------------------
532 * The "atf_tc" type.
533 * --------------------------------------------------------------------- */
535 struct atf_tc_impl {
536 const char *m_ident;
538 atf_map_t m_vars;
539 atf_map_t m_config;
541 atf_tc_head_t m_head;
542 atf_tc_body_t m_body;
543 atf_tc_cleanup_t m_cleanup;
547 * Constructors/destructors.
550 atf_error_t
551 atf_tc_init(atf_tc_t *tc, const char *ident, atf_tc_head_t head,
552 atf_tc_body_t body, atf_tc_cleanup_t cleanup,
553 const char *const *config)
555 atf_error_t err;
557 tc->pimpl = malloc(sizeof(struct atf_tc_impl));
558 if (tc->pimpl == NULL) {
559 err = atf_no_memory_error();
560 goto err;
563 tc->pimpl->m_ident = ident;
564 tc->pimpl->m_head = head;
565 tc->pimpl->m_body = body;
566 tc->pimpl->m_cleanup = cleanup;
568 err = atf_map_init_charpp(&tc->pimpl->m_config, config);
569 if (atf_is_error(err))
570 goto err;
572 err = atf_map_init(&tc->pimpl->m_vars);
573 if (atf_is_error(err))
574 goto err_vars;
576 err = atf_tc_set_md_var(tc, "ident", ident);
577 if (atf_is_error(err))
578 goto err_map;
580 if (cleanup != NULL) {
581 err = atf_tc_set_md_var(tc, "has.cleanup", "true");
582 if (atf_is_error(err))
583 goto err_map;
586 /* XXX Should the head be able to return error codes? */
587 if (tc->pimpl->m_head != NULL)
588 tc->pimpl->m_head(tc);
590 if (strcmp(atf_tc_get_md_var(tc, "ident"), ident) != 0) {
591 report_fatal_error("Test case head modified the read-only 'ident' "
592 "property");
593 UNREACHABLE;
596 INV(!atf_is_error(err));
597 return err;
599 err_map:
600 atf_map_fini(&tc->pimpl->m_vars);
601 err_vars:
602 atf_map_fini(&tc->pimpl->m_config);
603 err:
604 return err;
607 atf_error_t
608 atf_tc_init_pack(atf_tc_t *tc, const atf_tc_pack_t *pack,
609 const char *const *config)
611 return atf_tc_init(tc, pack->m_ident, pack->m_head, pack->m_body,
612 pack->m_cleanup, config);
615 void
616 atf_tc_fini(atf_tc_t *tc)
618 atf_map_fini(&tc->pimpl->m_vars);
619 free(tc->pimpl);
623 * Getters.
626 const char *
627 atf_tc_get_ident(const atf_tc_t *tc)
629 return tc->pimpl->m_ident;
632 const char *
633 atf_tc_get_config_var(const atf_tc_t *tc, const char *name)
635 const char *val;
636 atf_map_citer_t iter;
638 PRE(atf_tc_has_config_var(tc, name));
639 iter = atf_map_find_c(&tc->pimpl->m_config, name);
640 val = atf_map_citer_data(iter);
641 INV(val != NULL);
643 return val;
646 const char *
647 atf_tc_get_config_var_wd(const atf_tc_t *tc, const char *name,
648 const char *defval)
650 const char *val;
652 if (!atf_tc_has_config_var(tc, name))
653 val = defval;
654 else
655 val = atf_tc_get_config_var(tc, name);
657 return val;
660 bool
661 atf_tc_get_config_var_as_bool(const atf_tc_t *tc, const char *name)
663 bool val;
664 const char *strval;
665 atf_error_t err;
667 strval = atf_tc_get_config_var(tc, name);
668 err = atf_text_to_bool(strval, &val);
669 if (atf_is_error(err)) {
670 atf_error_free(err);
671 atf_tc_fail("Configuration variable %s does not have a valid "
672 "boolean value; found %s", name, strval);
675 return val;
678 bool
679 atf_tc_get_config_var_as_bool_wd(const atf_tc_t *tc, const char *name,
680 const bool defval)
682 bool val;
684 if (!atf_tc_has_config_var(tc, name))
685 val = defval;
686 else
687 val = atf_tc_get_config_var_as_bool(tc, name);
689 return val;
692 long
693 atf_tc_get_config_var_as_long(const atf_tc_t *tc, const char *name)
695 long val;
696 const char *strval;
697 atf_error_t err;
699 strval = atf_tc_get_config_var(tc, name);
700 err = atf_text_to_long(strval, &val);
701 if (atf_is_error(err)) {
702 atf_error_free(err);
703 atf_tc_fail("Configuration variable %s does not have a valid "
704 "long value; found %s", name, strval);
707 return val;
710 long
711 atf_tc_get_config_var_as_long_wd(const atf_tc_t *tc, const char *name,
712 const long defval)
714 long val;
716 if (!atf_tc_has_config_var(tc, name))
717 val = defval;
718 else
719 val = atf_tc_get_config_var_as_long(tc, name);
721 return val;
724 const char *
725 atf_tc_get_md_var(const atf_tc_t *tc, const char *name)
727 const char *val;
728 atf_map_citer_t iter;
730 PRE(atf_tc_has_md_var(tc, name));
731 iter = atf_map_find_c(&tc->pimpl->m_vars, name);
732 val = atf_map_citer_data(iter);
733 INV(val != NULL);
735 return val;
738 char **
739 atf_tc_get_md_vars(const atf_tc_t *tc)
741 return atf_map_to_charpp(&tc->pimpl->m_vars);
744 bool
745 atf_tc_has_config_var(const atf_tc_t *tc, const char *name)
747 atf_map_citer_t end, iter;
749 iter = atf_map_find_c(&tc->pimpl->m_config, name);
750 end = atf_map_end_c(&tc->pimpl->m_config);
751 return !atf_equal_map_citer_map_citer(iter, end);
754 bool
755 atf_tc_has_md_var(const atf_tc_t *tc, const char *name)
757 atf_map_citer_t end, iter;
759 iter = atf_map_find_c(&tc->pimpl->m_vars, name);
760 end = atf_map_end_c(&tc->pimpl->m_vars);
761 return !atf_equal_map_citer_map_citer(iter, end);
765 * Modifiers.
768 atf_error_t
769 atf_tc_set_md_var(atf_tc_t *tc, const char *name, const char *fmt, ...)
771 atf_error_t err;
772 char *value;
773 va_list ap;
775 va_start(ap, fmt);
776 err = atf_text_format_ap(&value, fmt, ap);
777 va_end(ap);
779 if (!atf_is_error(err))
780 err = atf_map_insert(&tc->pimpl->m_vars, name, value, true);
781 else
782 free(value);
784 return err;
787 /* ---------------------------------------------------------------------
788 * Free functions, as they should be publicly but they can't.
789 * --------------------------------------------------------------------- */
791 static void _atf_tc_fail(struct context *, const char *, va_list)
792 ATF_DEFS_ATTRIBUTE_NORETURN;
793 static void _atf_tc_fail_nonfatal(struct context *, const char *, va_list);
794 static void _atf_tc_fail_check(struct context *, const char *, const size_t,
795 const char *, va_list);
796 static void _atf_tc_fail_requirement(struct context *, const char *,
797 const size_t, const char *, va_list) ATF_DEFS_ATTRIBUTE_NORETURN;
798 static void _atf_tc_pass(struct context *) ATF_DEFS_ATTRIBUTE_NORETURN;
799 static void _atf_tc_require_prog(struct context *, const char *);
800 static void _atf_tc_skip(struct context *, const char *, va_list)
801 ATF_DEFS_ATTRIBUTE_NORETURN;
802 static void _atf_tc_check_errno(struct context *, const char *, const size_t,
803 const int, const char *, const bool);
804 static void _atf_tc_require_errno(struct context *, const char *, const size_t,
805 const int, const char *, const bool);
806 static void _atf_tc_expect_pass(struct context *);
807 static void _atf_tc_expect_fail(struct context *, const char *, va_list);
808 static void _atf_tc_expect_exit(struct context *, const int, const char *,
809 va_list);
810 static void _atf_tc_expect_signal(struct context *, const int, const char *,
811 va_list);
812 static void _atf_tc_expect_death(struct context *, const char *,
813 va_list);
815 static void
816 _atf_tc_fail(struct context *ctx, const char *fmt, va_list ap)
818 va_list ap2;
819 atf_dynstr_t reason;
821 va_copy(ap2, ap);
822 format_reason_ap(&reason, NULL, 0, fmt, ap2);
823 va_end(ap2);
825 fail_requirement(ctx, &reason);
826 UNREACHABLE;
829 static void
830 _atf_tc_fail_nonfatal(struct context *ctx, const char *fmt, va_list ap)
832 va_list ap2;
833 atf_dynstr_t reason;
835 va_copy(ap2, ap);
836 format_reason_ap(&reason, NULL, 0, fmt, ap2);
837 va_end(ap2);
839 fail_check(ctx, &reason);
842 static void
843 _atf_tc_fail_check(struct context *ctx, const char *file, const size_t line,
844 const char *fmt, va_list ap)
846 va_list ap2;
847 atf_dynstr_t reason;
849 va_copy(ap2, ap);
850 format_reason_ap(&reason, file, line, fmt, ap2);
851 va_end(ap2);
853 fail_check(ctx, &reason);
856 static void
857 _atf_tc_fail_requirement(struct context *ctx, const char *file,
858 const size_t line, const char *fmt, va_list ap)
860 va_list ap2;
861 atf_dynstr_t reason;
863 va_copy(ap2, ap);
864 format_reason_ap(&reason, file, line, fmt, ap2);
865 va_end(ap2);
867 fail_requirement(ctx, &reason);
868 UNREACHABLE;
871 static void
872 _atf_tc_pass(struct context *ctx)
874 pass(ctx);
875 UNREACHABLE;
878 static void
879 _atf_tc_require_prog(struct context *ctx, const char *prog)
881 check_fatal_error(check_prog(ctx, prog));
884 static void
885 _atf_tc_skip(struct context *ctx, const char *fmt, va_list ap)
887 atf_dynstr_t reason;
888 va_list ap2;
890 va_copy(ap2, ap);
891 format_reason_ap(&reason, NULL, 0, fmt, ap2);
892 va_end(ap2);
894 skip(ctx, &reason);
897 static void
898 _atf_tc_check_errno(struct context *ctx, const char *file, const size_t line,
899 const int exp_errno, const char *expr_str,
900 const bool expr_result)
902 errno_test(ctx, file, line, exp_errno, expr_str, expr_result, fail_check);
905 static void
906 _atf_tc_require_errno(struct context *ctx, const char *file, const size_t line,
907 const int exp_errno, const char *expr_str,
908 const bool expr_result)
910 errno_test(ctx, file, line, exp_errno, expr_str, expr_result,
911 fail_requirement);
914 static void
915 _atf_tc_expect_pass(struct context *ctx)
917 validate_expect(ctx);
919 ctx->expect = EXPECT_PASS;
922 static void
923 _atf_tc_expect_fail(struct context *ctx, const char *reason, va_list ap)
925 va_list ap2;
927 validate_expect(ctx);
929 ctx->expect = EXPECT_FAIL;
930 atf_dynstr_fini(&ctx->expect_reason);
931 va_copy(ap2, ap);
932 check_fatal_error(atf_dynstr_init_ap(&ctx->expect_reason, reason, ap2));
933 va_end(ap2);
934 ctx->expect_previous_fail_count = ctx->expect_fail_count;
937 static void
938 _atf_tc_expect_exit(struct context *ctx, const int exitcode, const char *reason,
939 va_list ap)
941 va_list ap2;
942 atf_dynstr_t formatted;
944 validate_expect(ctx);
946 ctx->expect = EXPECT_EXIT;
947 va_copy(ap2, ap);
948 check_fatal_error(atf_dynstr_init_ap(&formatted, reason, ap2));
949 va_end(ap2);
951 create_resfile(ctx->resfile, "expected_exit", exitcode, &formatted);
954 static void
955 _atf_tc_expect_signal(struct context *ctx, const int signo, const char *reason,
956 va_list ap)
958 va_list ap2;
959 atf_dynstr_t formatted;
961 validate_expect(ctx);
963 ctx->expect = EXPECT_SIGNAL;
964 va_copy(ap2, ap);
965 check_fatal_error(atf_dynstr_init_ap(&formatted, reason, ap2));
966 va_end(ap2);
968 create_resfile(ctx->resfile, "expected_signal", signo, &formatted);
971 static void
972 _atf_tc_expect_death(struct context *ctx, const char *reason, va_list ap)
974 va_list ap2;
975 atf_dynstr_t formatted;
977 validate_expect(ctx);
979 ctx->expect = EXPECT_DEATH;
980 va_copy(ap2, ap);
981 check_fatal_error(atf_dynstr_init_ap(&formatted, reason, ap2));
982 va_end(ap2);
984 create_resfile(ctx->resfile, "expected_death", -1, &formatted);
987 static void
988 _atf_tc_expect_timeout(struct context *ctx, const char *reason, va_list ap)
990 va_list ap2;
991 atf_dynstr_t formatted;
993 validate_expect(ctx);
995 ctx->expect = EXPECT_TIMEOUT;
996 va_copy(ap2, ap);
997 check_fatal_error(atf_dynstr_init_ap(&formatted, reason, ap2));
998 va_end(ap2);
1000 create_resfile(ctx->resfile, "expected_timeout", -1, &formatted);
1003 /* ---------------------------------------------------------------------
1004 * Free functions.
1005 * --------------------------------------------------------------------- */
1007 static struct context Current;
1009 atf_error_t
1010 atf_tc_run(const atf_tc_t *tc, const char *resfile)
1012 context_init(&Current, tc, resfile);
1014 tc->pimpl->m_body(tc);
1016 validate_expect(&Current);
1018 if (Current.fail_count > 0) {
1019 atf_dynstr_t reason;
1021 format_reason_fmt(&reason, NULL, 0, "%d checks failed; see output for "
1022 "more details", Current.fail_count);
1023 fail_requirement(&Current, &reason);
1024 } else if (Current.expect_fail_count > 0) {
1025 atf_dynstr_t reason;
1027 format_reason_fmt(&reason, NULL, 0, "%d checks failed as expected; "
1028 "see output for more details", Current.expect_fail_count);
1029 expected_failure(&Current, &reason);
1030 } else {
1031 pass(&Current);
1033 UNREACHABLE;
1034 return atf_no_error();
1037 atf_error_t
1038 atf_tc_cleanup(const atf_tc_t *tc)
1040 if (tc->pimpl->m_cleanup != NULL)
1041 tc->pimpl->m_cleanup(tc);
1042 return atf_no_error(); /* XXX */
1045 /* ---------------------------------------------------------------------
1046 * Free functions that depend on Current.
1047 * --------------------------------------------------------------------- */
1050 * All the functions below provide delegates to other internal functions
1051 * (prefixed by _) that take the current test case as an argument to
1052 * prevent them from accessing global state. This is to keep the side-
1053 * effects of the internal functions clearer and easier to understand.
1055 * The public API should never have hid the fact that it needs access to
1056 * the current test case (other than maybe in the macros), but changing it
1057 * is hard. TODO: Revisit in the future.
1060 void
1061 atf_tc_fail(const char *fmt, ...)
1063 va_list ap;
1065 PRE(Current.tc != NULL);
1067 va_start(ap, fmt);
1068 _atf_tc_fail(&Current, fmt, ap);
1069 va_end(ap);
1072 void
1073 atf_tc_fail_nonfatal(const char *fmt, ...)
1075 va_list ap;
1077 PRE(Current.tc != NULL);
1079 va_start(ap, fmt);
1080 _atf_tc_fail_nonfatal(&Current, fmt, ap);
1081 va_end(ap);
1084 void
1085 atf_tc_fail_check(const char *file, const size_t line, const char *fmt, ...)
1087 va_list ap;
1089 PRE(Current.tc != NULL);
1091 va_start(ap, fmt);
1092 _atf_tc_fail_check(&Current, file, line, fmt, ap);
1093 va_end(ap);
1096 void
1097 atf_tc_fail_requirement(const char *file, const size_t line,
1098 const char *fmt, ...)
1100 va_list ap;
1102 PRE(Current.tc != NULL);
1104 va_start(ap, fmt);
1105 _atf_tc_fail_requirement(&Current, file, line, fmt, ap);
1106 va_end(ap);
1109 void
1110 atf_tc_pass(void)
1112 PRE(Current.tc != NULL);
1114 _atf_tc_pass(&Current);
1117 void
1118 atf_tc_require_prog(const char *prog)
1120 PRE(Current.tc != NULL);
1122 _atf_tc_require_prog(&Current, prog);
1125 void
1126 atf_tc_skip(const char *fmt, ...)
1128 va_list ap;
1130 PRE(Current.tc != NULL);
1132 va_start(ap, fmt);
1133 _atf_tc_skip(&Current, fmt, ap);
1134 va_end(ap);
1137 void
1138 atf_tc_check_errno(const char *file, const size_t line, const int exp_errno,
1139 const char *expr_str, const bool expr_result)
1141 PRE(Current.tc != NULL);
1143 _atf_tc_check_errno(&Current, file, line, exp_errno, expr_str,
1144 expr_result);
1147 void
1148 atf_tc_require_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_require_errno(&Current, file, line, exp_errno, expr_str,
1154 expr_result);
1157 void
1158 atf_tc_expect_pass(void)
1160 PRE(Current.tc != NULL);
1162 _atf_tc_expect_pass(&Current);
1165 void
1166 atf_tc_expect_fail(const char *reason, ...)
1168 va_list ap;
1170 PRE(Current.tc != NULL);
1172 va_start(ap, reason);
1173 _atf_tc_expect_fail(&Current, reason, ap);
1174 va_end(ap);
1177 void
1178 atf_tc_expect_exit(const int exitcode, const char *reason, ...)
1180 va_list ap;
1182 PRE(Current.tc != NULL);
1184 va_start(ap, reason);
1185 _atf_tc_expect_exit(&Current, exitcode, reason, ap);
1186 va_end(ap);
1189 void
1190 atf_tc_expect_signal(const int signo, const char *reason, ...)
1192 va_list ap;
1194 PRE(Current.tc != NULL);
1196 va_start(ap, reason);
1197 _atf_tc_expect_signal(&Current, signo, reason, ap);
1198 va_end(ap);
1201 void
1202 atf_tc_expect_death(const char *reason, ...)
1204 va_list ap;
1206 PRE(Current.tc != NULL);
1208 va_start(ap, reason);
1209 _atf_tc_expect_death(&Current, reason, ap);
1210 va_end(ap);
1213 void
1214 atf_tc_expect_timeout(const char *reason, ...)
1216 va_list ap;
1218 PRE(Current.tc != NULL);
1220 va_start(ap, reason);
1221 _atf_tc_expect_timeout(&Current, reason, ap);
1222 va_end(ap);