1 /* Copyright (c) 2008 The NetBSD Foundation, Inc.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
14 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
15 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
20 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
24 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
28 #include <sys/types.h>
42 #include "atf-c/defs.h"
43 #include "atf-c/detail/env.h"
44 #include "atf-c/detail/fs.h"
45 #include "atf-c/detail/map.h"
46 #include "atf-c/detail/sanity.h"
47 #include "atf-c/detail/text.h"
48 #include "atf-c/error.h"
50 /* ---------------------------------------------------------------------
51 * Auxiliary functions.
52 * --------------------------------------------------------------------- */
69 enum expect_type expect;
70 atf_dynstr_t expect_reason;
71 size_t expect_previous_fail_count;
72 size_t expect_fail_count;
77 static void context_init(struct context *, const atf_tc_t *, const char *);
78 static void context_set_resfile(struct context *, const char *);
79 static void context_close_resfile(struct context *);
80 static void check_fatal_error(atf_error_t);
81 static void report_fatal_error(const char *, ...)
82 ATF_DEFS_ATTRIBUTE_NORETURN;
83 static atf_error_t write_resfile(const int, const char *, const int,
84 const atf_dynstr_t *);
85 static void create_resfile(struct context *, const char *, const int,
87 static void error_in_expect(struct context *, const char *, ...)
88 ATF_DEFS_ATTRIBUTE_NORETURN;
89 static void validate_expect(struct context *);
90 static void expected_failure(struct context *, atf_dynstr_t *)
91 ATF_DEFS_ATTRIBUTE_NORETURN;
92 static void fail_requirement(struct context *, atf_dynstr_t *)
93 ATF_DEFS_ATTRIBUTE_NORETURN;
94 static void fail_check(struct context *, atf_dynstr_t *);
95 static void pass(struct context *)
96 ATF_DEFS_ATTRIBUTE_NORETURN;
97 static void skip(struct context *, atf_dynstr_t *)
98 ATF_DEFS_ATTRIBUTE_NORETURN;
99 static void format_reason_ap(atf_dynstr_t *, const char *, const size_t,
100 const char *, va_list);
101 static void format_reason_fmt(atf_dynstr_t *, const char *, const size_t,
103 static void errno_test(struct context *, const char *, const size_t,
104 const int, const char *, const bool,
105 void (*)(struct context *, atf_dynstr_t *));
106 static atf_error_t check_prog_in_dir(const char *, void *);
107 static atf_error_t check_prog(struct context *, const char *);
109 /* No prototype in header for this one, it's a little sketchy (internal). */
110 void atf_tc_set_resultsfile(const char *);
113 context_init(struct context *ctx, const atf_tc_t *tc, const char *resfile)
118 context_set_resfile(ctx, resfile);
120 ctx->expect = EXPECT_PASS;
121 check_fatal_error(atf_dynstr_init(&ctx->expect_reason));
122 ctx->expect_previous_fail_count = 0;
123 ctx->expect_fail_count = 0;
124 ctx->expect_exitcode = 0;
125 ctx->expect_signo = 0;
129 context_set_resfile(struct context *ctx, const char *resfile)
133 context_close_resfile(ctx);
134 ctx->resfile = resfile;
135 if (strcmp(resfile, "/dev/stdout") == 0)
136 ctx->resfilefd = STDOUT_FILENO;
137 else if (strcmp(resfile, "/dev/stderr") == 0)
138 ctx->resfilefd = STDERR_FILENO;
140 ctx->resfilefd = open(resfile, O_WRONLY | O_CREAT | O_TRUNC,
141 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
142 if (ctx->resfilefd == -1) {
143 err = atf_libc_error(errno,
144 "Cannot create results file '%s'", resfile);
145 check_fatal_error(err);
148 ctx->resfile = resfile;
152 context_close_resfile(struct context *ctx)
155 if (ctx->resfilefd == -1)
157 if (ctx->resfilefd != STDOUT_FILENO && ctx->resfilefd != STDERR_FILENO)
158 close(ctx->resfilefd);
164 check_fatal_error(atf_error_t err)
166 if (atf_is_error(err)) {
168 atf_error_format(err, buf, sizeof(buf));
169 fprintf(stderr, "FATAL ERROR: %s\n", buf);
176 report_fatal_error(const char *msg, ...)
179 fprintf(stderr, "FATAL ERROR: ");
182 vfprintf(stderr, msg, ap);
185 fprintf(stderr, "\n");
189 /** Writes to a results file.
191 * The results file is supposed to be already open.
193 * This function returns an error code instead of exiting in case of error
194 * because the caller needs to clean up the reason object before terminating.
197 write_resfile(const int fd, const char *result, const int arg,
198 const atf_dynstr_t *reason)
200 static char NL[] = "\n", CS[] = ": ";
207 INV(arg == -1 || reason != NULL);
209 #define UNCONST(a) ((void *)(uintptr_t)(const void *)(a))
210 iov[count].iov_base = UNCONST(result);
211 iov[count++].iov_len = strlen(result);
213 if (reason != NULL) {
215 iov[count].iov_base = buf;
216 iov[count++].iov_len = snprintf(buf, sizeof(buf), "(%d)", arg);
219 iov[count].iov_base = CS;
220 iov[count++].iov_len = sizeof(CS) - 1;
222 r = atf_dynstr_cstring(reason);
223 iov[count].iov_base = UNCONST(r);
224 iov[count++].iov_len = strlen(r);
228 iov[count].iov_base = NL;
229 iov[count++].iov_len = sizeof(NL) - 1;
231 while ((ret = writev(fd, iov, count)) == -1 && errno == EINTR)
232 continue; /* Retry. */
234 return atf_no_error();
236 return atf_libc_error(
237 errno, "Failed to write results file; result %s, reason %s", result,
238 reason == NULL ? "null" : atf_dynstr_cstring(reason));
241 /** Creates a results file.
243 * The input reason is released in all cases.
245 * An error in this function is considered to be fatal, hence why it does
246 * not return any error code.
249 create_resfile(struct context *ctx, const char *result, const int arg,
250 atf_dynstr_t *reason)
255 * We'll attempt to truncate the results file, but only if it's not pointed
256 * at stdout/stderr. We could just blindly ftruncate() here, but it may
257 * be that stdout/stderr have been redirected to a file that we want to
258 * validate expectations on, for example. Kyua will want the truncation,
259 * but it will also redirect the results directly to some file and we'll
260 * have no issue here.
262 if (ctx->resfilefd != STDOUT_FILENO && ctx->resfilefd != STDERR_FILENO &&
263 ftruncate(ctx->resfilefd, 0) != -1)
264 lseek(ctx->resfilefd, 0, SEEK_SET);
265 err = write_resfile(ctx->resfilefd, result, arg, reason);
268 atf_dynstr_fini(reason);
270 check_fatal_error(err);
273 /** Fails a test case if validate_expect fails. */
275 error_in_expect(struct context *ctx, const char *fmt, ...)
281 format_reason_ap(&reason, NULL, 0, fmt, ap);
284 ctx->expect = EXPECT_PASS; /* Ensure fail_requirement really fails. */
285 fail_requirement(ctx, &reason);
288 /** Ensures that the "expect" state is correct.
290 * Call this function before modifying the current value of expect.
293 validate_expect(struct context *ctx)
295 if (ctx->expect == EXPECT_DEATH) {
296 error_in_expect(ctx, "Test case was expected to terminate abruptly "
297 "but it continued execution");
298 } else if (ctx->expect == EXPECT_EXIT) {
299 error_in_expect(ctx, "Test case was expected to exit cleanly but it "
300 "continued execution");
301 } else if (ctx->expect == EXPECT_FAIL) {
302 if (ctx->expect_fail_count == ctx->expect_previous_fail_count)
303 error_in_expect(ctx, "Test case was expecting a failure but none "
306 INV(ctx->expect_fail_count > ctx->expect_previous_fail_count);
307 } else if (ctx->expect == EXPECT_PASS) {
308 /* Nothing to validate. */
309 } else if (ctx->expect == EXPECT_SIGNAL) {
310 error_in_expect(ctx, "Test case was expected to receive a termination "
311 "signal but it continued execution");
312 } else if (ctx->expect == EXPECT_TIMEOUT) {
313 error_in_expect(ctx, "Test case was expected to hang but it continued "
320 expected_failure(struct context *ctx, atf_dynstr_t *reason)
322 check_fatal_error(atf_dynstr_prepend_fmt(reason, "%s: ",
323 atf_dynstr_cstring(&ctx->expect_reason)));
324 create_resfile(ctx, "expected_failure", -1, reason);
325 context_close_resfile(ctx);
330 fail_requirement(struct context *ctx, atf_dynstr_t *reason)
332 if (ctx->expect == EXPECT_FAIL) {
333 expected_failure(ctx, reason);
334 } else if (ctx->expect == EXPECT_PASS) {
335 create_resfile(ctx, "failed", -1, reason);
336 context_close_resfile(ctx);
339 error_in_expect(ctx, "Test case raised a failure but was not "
340 "expecting one; reason was %s", atf_dynstr_cstring(reason));
346 fail_check(struct context *ctx, atf_dynstr_t *reason)
348 if (ctx->expect == EXPECT_FAIL) {
349 fprintf(stderr, "*** Expected check failure: %s: %s\n",
350 atf_dynstr_cstring(&ctx->expect_reason),
351 atf_dynstr_cstring(reason));
352 ctx->expect_fail_count++;
353 } else if (ctx->expect == EXPECT_PASS) {
354 fprintf(stderr, "*** Check failed: %s\n", atf_dynstr_cstring(reason));
357 error_in_expect(ctx, "Test case raised a failure but was not "
358 "expecting one; reason was %s", atf_dynstr_cstring(reason));
361 atf_dynstr_fini(reason);
365 pass(struct context *ctx)
367 if (ctx->expect == EXPECT_FAIL) {
368 error_in_expect(ctx, "Test case was expecting a failure but got "
370 } else if (ctx->expect == EXPECT_PASS) {
371 create_resfile(ctx, "passed", -1, NULL);
372 context_close_resfile(ctx);
375 error_in_expect(ctx, "Test case asked to explicitly pass but was "
376 "not expecting such condition");
382 skip(struct context *ctx, atf_dynstr_t *reason)
384 create_resfile(ctx, "skipped", -1, reason);
385 context_close_resfile(ctx);
389 /** Formats a failure/skip reason message.
391 * The formatted reason is stored in out_reason. out_reason is initialized
392 * in this function and is supposed to be released by the caller. In general,
393 * the reason will eventually be fed to create_resfile, which will release
396 * Errors in this function are fatal. Rationale being: reasons are used to
397 * create results files; if we can't format the reason correctly, the result
398 * of the test program will be bogus. So it's better to just exit with a
402 format_reason_ap(atf_dynstr_t *out_reason,
403 const char *source_file, const size_t source_line,
404 const char *reason, va_list ap)
408 if (source_file != NULL) {
409 err = atf_dynstr_init_fmt(out_reason, "%s:%zd: ", source_file,
412 PRE(source_line == 0);
413 err = atf_dynstr_init(out_reason);
416 if (!atf_is_error(err)) {
419 err = atf_dynstr_append_ap(out_reason, reason, ap2);
423 check_fatal_error(err);
427 format_reason_fmt(atf_dynstr_t *out_reason,
428 const char *source_file, const size_t source_line,
429 const char *reason, ...)
433 va_start(ap, reason);
434 format_reason_ap(out_reason, source_file, source_line, reason, ap);
439 errno_test(struct context *ctx, const char *file, const size_t line,
440 const int exp_errno, const char *expr_str,
441 const bool expr_result,
442 void (*fail_func)(struct context *, atf_dynstr_t *))
444 const int actual_errno = errno;
447 if (exp_errno != actual_errno) {
450 format_reason_fmt(&reason, file, line, "Expected errno %d, got %d, "
451 "in %s", exp_errno, actual_errno, expr_str);
452 fail_func(ctx, &reason);
457 format_reason_fmt(&reason, file, line, "Expected true value in %s",
459 fail_func(ctx, &reason);
463 struct prog_found_pair {
469 check_prog_in_dir(const char *dir, void *data)
471 struct prog_found_pair *pf = data;
475 err = atf_no_error();
479 err = atf_fs_path_init_fmt(&p, "%s/%s", dir, pf->prog);
480 if (atf_is_error(err))
483 err = atf_fs_eaccess(&p, atf_fs_access_x);
484 if (!atf_is_error(err))
489 err = atf_no_error();
493 atf_fs_path_fini(&p);
500 check_prog(struct context *ctx, const char *prog)
505 err = atf_fs_path_init_fmt(&p, "%s", prog);
506 if (atf_is_error(err))
509 if (atf_fs_path_is_absolute(&p)) {
510 err = atf_fs_eaccess(&p, atf_fs_access_x);
511 if (atf_is_error(err)) {
515 atf_fs_path_fini(&p);
516 format_reason_fmt(&reason, NULL, 0, "The required program %s could "
517 "not be found", prog);
521 const char *path = atf_env_get("PATH");
522 struct prog_found_pair pf;
525 err = atf_fs_path_branch_path(&p, &bp);
526 if (atf_is_error(err))
529 if (strcmp(atf_fs_path_cstring(&bp), ".") != 0) {
530 atf_fs_path_fini(&bp);
531 atf_fs_path_fini(&p);
533 report_fatal_error("Relative paths are not allowed when searching "
534 "for a program (%s)", prog);
540 err = atf_text_for_each_word(path, ":", check_prog_in_dir, &pf);
541 if (atf_is_error(err))
547 atf_fs_path_fini(&bp);
548 atf_fs_path_fini(&p);
549 format_reason_fmt(&reason, NULL, 0, "The required program %s could "
550 "not be found in the PATH", prog);
551 fail_requirement(ctx, &reason);
555 atf_fs_path_fini(&bp);
559 atf_fs_path_fini(&p);
564 /* ---------------------------------------------------------------------
566 * --------------------------------------------------------------------- */
574 atf_tc_head_t m_head;
575 atf_tc_body_t m_body;
576 atf_tc_cleanup_t m_cleanup;
580 * Constructors/destructors.
584 atf_tc_init(atf_tc_t *tc, const char *ident, atf_tc_head_t head,
585 atf_tc_body_t body, atf_tc_cleanup_t cleanup,
586 const char *const *config)
590 tc->pimpl = malloc(sizeof(struct atf_tc_impl));
591 if (tc->pimpl == NULL) {
592 err = atf_no_memory_error();
596 tc->pimpl->m_ident = ident;
597 tc->pimpl->m_head = head;
598 tc->pimpl->m_body = body;
599 tc->pimpl->m_cleanup = cleanup;
601 err = atf_map_init_charpp(&tc->pimpl->m_config, config);
602 if (atf_is_error(err))
605 err = atf_map_init(&tc->pimpl->m_vars);
606 if (atf_is_error(err))
609 err = atf_tc_set_md_var(tc, "ident", ident);
610 if (atf_is_error(err))
613 if (cleanup != NULL) {
614 err = atf_tc_set_md_var(tc, "has.cleanup", "true");
615 if (atf_is_error(err))
619 /* XXX Should the head be able to return error codes? */
620 if (tc->pimpl->m_head != NULL)
621 tc->pimpl->m_head(tc);
623 if (strcmp(atf_tc_get_md_var(tc, "ident"), ident) != 0) {
624 report_fatal_error("Test case head modified the read-only 'ident' "
629 INV(!atf_is_error(err));
633 atf_map_fini(&tc->pimpl->m_vars);
635 atf_map_fini(&tc->pimpl->m_config);
641 atf_tc_init_pack(atf_tc_t *tc, const atf_tc_pack_t *pack,
642 const char *const *config)
644 return atf_tc_init(tc, pack->m_ident, pack->m_head, pack->m_body,
645 pack->m_cleanup, config);
649 atf_tc_fini(atf_tc_t *tc)
651 atf_map_fini(&tc->pimpl->m_vars);
660 atf_tc_get_ident(const atf_tc_t *tc)
662 return tc->pimpl->m_ident;
666 atf_tc_get_config_var(const atf_tc_t *tc, const char *name)
669 atf_map_citer_t iter;
671 PRE(atf_tc_has_config_var(tc, name));
672 iter = atf_map_find_c(&tc->pimpl->m_config, name);
673 val = atf_map_citer_data(iter);
680 atf_tc_get_config_var_wd(const atf_tc_t *tc, const char *name,
685 if (!atf_tc_has_config_var(tc, name))
688 val = atf_tc_get_config_var(tc, name);
694 atf_tc_get_config_var_as_bool(const atf_tc_t *tc, const char *name)
700 strval = atf_tc_get_config_var(tc, name);
701 err = atf_text_to_bool(strval, &val);
702 if (atf_is_error(err)) {
704 atf_tc_fail("Configuration variable %s does not have a valid "
705 "boolean value; found %s", name, strval);
712 atf_tc_get_config_var_as_bool_wd(const atf_tc_t *tc, const char *name,
717 if (!atf_tc_has_config_var(tc, name))
720 val = atf_tc_get_config_var_as_bool(tc, name);
726 atf_tc_get_config_var_as_long(const atf_tc_t *tc, const char *name)
732 strval = atf_tc_get_config_var(tc, name);
733 err = atf_text_to_long(strval, &val);
734 if (atf_is_error(err)) {
736 atf_tc_fail("Configuration variable %s does not have a valid "
737 "long value; found %s", name, strval);
744 atf_tc_get_config_var_as_long_wd(const atf_tc_t *tc, const char *name,
749 if (!atf_tc_has_config_var(tc, name))
752 val = atf_tc_get_config_var_as_long(tc, name);
758 atf_tc_get_md_var(const atf_tc_t *tc, const char *name)
761 atf_map_citer_t iter;
763 PRE(atf_tc_has_md_var(tc, name));
764 iter = atf_map_find_c(&tc->pimpl->m_vars, name);
765 val = atf_map_citer_data(iter);
772 atf_tc_get_md_vars(const atf_tc_t *tc)
774 return atf_map_to_charpp(&tc->pimpl->m_vars);
778 atf_tc_has_config_var(const atf_tc_t *tc, const char *name)
780 atf_map_citer_t end, iter;
782 iter = atf_map_find_c(&tc->pimpl->m_config, name);
783 end = atf_map_end_c(&tc->pimpl->m_config);
784 return !atf_equal_map_citer_map_citer(iter, end);
788 atf_tc_has_md_var(const atf_tc_t *tc, const char *name)
790 atf_map_citer_t end, iter;
792 iter = atf_map_find_c(&tc->pimpl->m_vars, name);
793 end = atf_map_end_c(&tc->pimpl->m_vars);
794 return !atf_equal_map_citer_map_citer(iter, end);
802 atf_tc_set_md_var(atf_tc_t *tc, const char *name, const char *fmt, ...)
809 err = atf_text_format_ap(&value, fmt, ap);
812 if (!atf_is_error(err))
813 err = atf_map_insert(&tc->pimpl->m_vars, name, value, true);
820 /* ---------------------------------------------------------------------
821 * Free functions, as they should be publicly but they can't.
822 * --------------------------------------------------------------------- */
824 static void _atf_tc_fail(struct context *, const char *, va_list)
825 ATF_DEFS_ATTRIBUTE_NORETURN;
826 static void _atf_tc_fail_nonfatal(struct context *, const char *, va_list);
827 static void _atf_tc_fail_check(struct context *, const char *, const size_t,
828 const char *, va_list);
829 static void _atf_tc_fail_requirement(struct context *, const char *,
830 const size_t, const char *, va_list) ATF_DEFS_ATTRIBUTE_NORETURN;
831 static void _atf_tc_pass(struct context *) ATF_DEFS_ATTRIBUTE_NORETURN;
832 static void _atf_tc_require_prog(struct context *, const char *);
833 static void _atf_tc_skip(struct context *, const char *, va_list)
834 ATF_DEFS_ATTRIBUTE_NORETURN;
835 static void _atf_tc_check_errno(struct context *, const char *, const size_t,
836 const int, const char *, const bool);
837 static void _atf_tc_require_errno(struct context *, const char *, const size_t,
838 const int, const char *, const bool);
839 static void _atf_tc_expect_pass(struct context *);
840 static void _atf_tc_expect_fail(struct context *, const char *, va_list);
841 static void _atf_tc_expect_exit(struct context *, const int, const char *,
843 static void _atf_tc_expect_signal(struct context *, const int, const char *,
845 static void _atf_tc_expect_death(struct context *, const char *,
849 _atf_tc_fail(struct context *ctx, const char *fmt, va_list ap)
855 format_reason_ap(&reason, NULL, 0, fmt, ap2);
858 fail_requirement(ctx, &reason);
863 _atf_tc_fail_nonfatal(struct context *ctx, const char *fmt, va_list ap)
869 format_reason_ap(&reason, NULL, 0, fmt, ap2);
872 fail_check(ctx, &reason);
876 _atf_tc_fail_check(struct context *ctx, const char *file, const size_t line,
877 const char *fmt, va_list ap)
883 format_reason_ap(&reason, file, line, fmt, ap2);
886 fail_check(ctx, &reason);
890 _atf_tc_fail_requirement(struct context *ctx, const char *file,
891 const size_t line, const char *fmt, va_list ap)
897 format_reason_ap(&reason, file, line, fmt, ap2);
900 fail_requirement(ctx, &reason);
905 _atf_tc_pass(struct context *ctx)
912 _atf_tc_require_prog(struct context *ctx, const char *prog)
914 check_fatal_error(check_prog(ctx, prog));
918 _atf_tc_skip(struct context *ctx, const char *fmt, va_list ap)
924 format_reason_ap(&reason, NULL, 0, fmt, ap2);
931 _atf_tc_check_errno(struct context *ctx, const char *file, const size_t line,
932 const int exp_errno, const char *expr_str,
933 const bool expr_result)
935 errno_test(ctx, file, line, exp_errno, expr_str, expr_result, fail_check);
939 _atf_tc_require_errno(struct context *ctx, const char *file, const size_t line,
940 const int exp_errno, const char *expr_str,
941 const bool expr_result)
943 errno_test(ctx, file, line, exp_errno, expr_str, expr_result,
948 _atf_tc_expect_pass(struct context *ctx)
950 validate_expect(ctx);
952 ctx->expect = EXPECT_PASS;
956 _atf_tc_expect_fail(struct context *ctx, const char *reason, va_list ap)
960 validate_expect(ctx);
962 ctx->expect = EXPECT_FAIL;
963 atf_dynstr_fini(&ctx->expect_reason);
965 check_fatal_error(atf_dynstr_init_ap(&ctx->expect_reason, reason, ap2));
967 ctx->expect_previous_fail_count = ctx->expect_fail_count;
971 _atf_tc_expect_exit(struct context *ctx, const int exitcode, const char *reason,
975 atf_dynstr_t formatted;
977 validate_expect(ctx);
979 ctx->expect = EXPECT_EXIT;
981 check_fatal_error(atf_dynstr_init_ap(&formatted, reason, ap2));
984 create_resfile(ctx, "expected_exit", exitcode, &formatted);
988 _atf_tc_expect_signal(struct context *ctx, const int signo, const char *reason,
992 atf_dynstr_t formatted;
994 validate_expect(ctx);
996 ctx->expect = EXPECT_SIGNAL;
998 check_fatal_error(atf_dynstr_init_ap(&formatted, reason, ap2));
1001 create_resfile(ctx, "expected_signal", signo, &formatted);
1005 _atf_tc_expect_death(struct context *ctx, const char *reason, va_list ap)
1008 atf_dynstr_t formatted;
1010 validate_expect(ctx);
1012 ctx->expect = EXPECT_DEATH;
1014 check_fatal_error(atf_dynstr_init_ap(&formatted, reason, ap2));
1017 create_resfile(ctx, "expected_death", -1, &formatted);
1021 _atf_tc_expect_timeout(struct context *ctx, const char *reason, va_list ap)
1024 atf_dynstr_t formatted;
1026 validate_expect(ctx);
1028 ctx->expect = EXPECT_TIMEOUT;
1030 check_fatal_error(atf_dynstr_init_ap(&formatted, reason, ap2));
1033 create_resfile(ctx, "expected_timeout", -1, &formatted);
1037 _atf_tc_set_resultsfile(struct context *ctx, const char *file)
1040 context_set_resfile(ctx, file);
1043 /* ---------------------------------------------------------------------
1045 * --------------------------------------------------------------------- */
1047 static struct context Current;
1050 atf_tc_run(const atf_tc_t *tc, const char *resfile)
1052 context_init(&Current, tc, resfile);
1054 tc->pimpl->m_body(tc);
1056 validate_expect(&Current);
1058 if (Current.fail_count > 0) {
1059 atf_dynstr_t reason;
1061 format_reason_fmt(&reason, NULL, 0, "%d checks failed; see output for "
1062 "more details", Current.fail_count);
1063 fail_requirement(&Current, &reason);
1064 } else if (Current.expect_fail_count > 0) {
1065 atf_dynstr_t reason;
1067 format_reason_fmt(&reason, NULL, 0, "%d checks failed as expected; "
1068 "see output for more details", Current.expect_fail_count);
1069 expected_failure(&Current, &reason);
1074 return atf_no_error();
1078 atf_tc_cleanup(const atf_tc_t *tc)
1080 if (tc->pimpl->m_cleanup != NULL)
1081 tc->pimpl->m_cleanup(tc);
1082 return atf_no_error(); /* XXX */
1085 /* ---------------------------------------------------------------------
1086 * Free functions that depend on Current.
1087 * --------------------------------------------------------------------- */
1090 * All the functions below provide delegates to other internal functions
1091 * (prefixed by _) that take the current test case as an argument to
1092 * prevent them from accessing global state. This is to keep the side-
1093 * effects of the internal functions clearer and easier to understand.
1095 * The public API should never have hid the fact that it needs access to
1096 * the current test case (other than maybe in the macros), but changing it
1097 * is hard. TODO: Revisit in the future.
1101 atf_tc_fail(const char *fmt, ...)
1105 PRE(Current.tc != NULL);
1108 _atf_tc_fail(&Current, fmt, ap);
1113 atf_tc_fail_nonfatal(const char *fmt, ...)
1117 PRE(Current.tc != NULL);
1120 _atf_tc_fail_nonfatal(&Current, fmt, ap);
1125 atf_tc_fail_check(const char *file, const size_t line, const char *fmt, ...)
1129 PRE(Current.tc != NULL);
1132 _atf_tc_fail_check(&Current, file, line, fmt, ap);
1137 atf_tc_fail_requirement(const char *file, const size_t line,
1138 const char *fmt, ...)
1142 PRE(Current.tc != NULL);
1145 _atf_tc_fail_requirement(&Current, file, line, fmt, ap);
1152 PRE(Current.tc != NULL);
1154 _atf_tc_pass(&Current);
1158 atf_tc_require_prog(const char *prog)
1160 PRE(Current.tc != NULL);
1162 _atf_tc_require_prog(&Current, prog);
1166 atf_tc_skip(const char *fmt, ...)
1170 PRE(Current.tc != NULL);
1173 _atf_tc_skip(&Current, fmt, ap);
1178 atf_tc_check_errno(const char *file, const size_t line, const int exp_errno,
1179 const char *expr_str, const bool expr_result)
1181 PRE(Current.tc != NULL);
1183 _atf_tc_check_errno(&Current, file, line, exp_errno, expr_str,
1188 atf_tc_require_errno(const char *file, const size_t line, const int exp_errno,
1189 const char *expr_str, const bool expr_result)
1191 PRE(Current.tc != NULL);
1193 _atf_tc_require_errno(&Current, file, line, exp_errno, expr_str,
1198 atf_tc_expect_pass(void)
1200 PRE(Current.tc != NULL);
1202 _atf_tc_expect_pass(&Current);
1206 atf_tc_expect_fail(const char *reason, ...)
1210 PRE(Current.tc != NULL);
1212 va_start(ap, reason);
1213 _atf_tc_expect_fail(&Current, reason, ap);
1218 atf_tc_expect_exit(const int exitcode, const char *reason, ...)
1222 PRE(Current.tc != NULL);
1224 va_start(ap, reason);
1225 _atf_tc_expect_exit(&Current, exitcode, reason, ap);
1230 atf_tc_expect_signal(const int signo, const char *reason, ...)
1234 PRE(Current.tc != NULL);
1236 va_start(ap, reason);
1237 _atf_tc_expect_signal(&Current, signo, reason, ap);
1242 atf_tc_expect_death(const char *reason, ...)
1246 PRE(Current.tc != NULL);
1248 va_start(ap, reason);
1249 _atf_tc_expect_death(&Current, reason, ap);
1254 atf_tc_expect_timeout(const char *reason, ...)
1258 PRE(Current.tc != NULL);
1260 va_start(ap, reason);
1261 _atf_tc_expect_timeout(&Current, reason, ap);
1267 atf_tc_set_resultsfile(const char *file)
1270 PRE(Current.tc != NULL);
1272 _atf_tc_set_resultsfile(&Current, file);