2 * Automated Testing Framework (atf)
4 * Copyright (c) 2008 The NetBSD Foundation, Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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>
43 #include "atf-c/defs.h"
44 #include "atf-c/error.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 * --------------------------------------------------------------------- */
71 enum expect_type expect
;
72 atf_dynstr_t expect_reason
;
73 size_t expect_previous_fail_count
;
74 size_t expect_fail_count
;
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_NORETURN
;
83 static atf_error_t
write_resfile(const int, const char *, const int,
84 const atf_dynstr_t
*);
85 static void create_resfile(const char *, 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 *);
110 context_init(struct context
*ctx
, const atf_tc_t
*tc
, const char *resfile
)
113 ctx
->resfile
= resfile
;
115 ctx
->expect
= EXPECT_PASS
;
116 check_fatal_error(atf_dynstr_init(&ctx
->expect_reason
));
117 ctx
->expect_previous_fail_count
= 0;
118 ctx
->expect_fail_count
= 0;
119 ctx
->expect_exitcode
= 0;
120 ctx
->expect_signo
= 0;
124 check_fatal_error(atf_error_t err
)
126 if (atf_is_error(err
)) {
128 atf_error_format(err
, buf
, sizeof(buf
));
129 fprintf(stderr
, "FATAL ERROR: %s\n", buf
);
136 report_fatal_error(const char *msg
, ...)
139 fprintf(stderr
, "FATAL ERROR: ");
142 vfprintf(stderr
, msg
, ap
);
145 fprintf(stderr
, "\n");
149 /** Writes to a results file.
151 * The results file is supposed to be already open.
153 * This function returns an error code instead of exiting in case of error
154 * because the caller needs to clean up the reason object before terminating.
157 write_resfile(const int fd
, const char *result
, const int arg
,
158 const atf_dynstr_t
*reason
)
160 static char NL
[] = "\n", CS
[] = ": ";
167 INV(arg
== -1 || reason
!= NULL
);
169 #define UNCONST(a) ((void *)(unsigned long)(const void *)(a))
170 iov
[count
].iov_base
= UNCONST(result
);
171 iov
[count
++].iov_len
= strlen(result
);
173 if (reason
!= NULL
) {
175 iov
[count
].iov_base
= buf
;
176 iov
[count
++].iov_len
= snprintf(buf
, sizeof(buf
), "(%d)", arg
);
179 iov
[count
].iov_base
= CS
;
180 iov
[count
++].iov_len
= sizeof(CS
) - 1;
182 r
= atf_dynstr_cstring(reason
);
183 iov
[count
].iov_base
= UNCONST(r
);
184 iov
[count
++].iov_len
= strlen(r
);
188 iov
[count
].iov_base
= NL
;
189 iov
[count
++].iov_len
= sizeof(NL
) - 1;
191 while ((ret
= writev(fd
, iov
, count
)) == -1 && errno
== EINTR
)
192 continue; /* Retry. */
194 return atf_no_error();
196 return atf_libc_error(
197 errno
, "Failed to write results file; result %s, reason %s", result
,
198 reason
== NULL
? "null" : atf_dynstr_cstring(reason
));
201 /** Creates a results file.
203 * The input reason is released in all cases.
205 * An error in this function is considered to be fatal, hence why it does
206 * not return any error code.
209 create_resfile(const char *resfile
, const char *result
, const int arg
,
210 atf_dynstr_t
*reason
)
214 if (strcmp("/dev/stdout", resfile
) == 0) {
215 err
= write_resfile(STDOUT_FILENO
, result
, arg
, reason
);
216 } else if (strcmp("/dev/stderr", resfile
) == 0) {
217 err
= write_resfile(STDERR_FILENO
, result
, arg
, reason
);
219 const int fd
= open(resfile
, O_WRONLY
| O_CREAT
| O_TRUNC
,
220 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
);
222 err
= atf_libc_error(errno
, "Cannot create results file '%s'",
225 err
= write_resfile(fd
, result
, arg
, reason
);
231 atf_dynstr_fini(reason
);
233 check_fatal_error(err
);
236 /** Fails a test case if validate_expect fails. */
238 error_in_expect(struct context
*ctx
, const char *fmt
, ...)
244 format_reason_ap(&reason
, NULL
, 0, fmt
, ap
);
247 ctx
->expect
= EXPECT_PASS
; /* Ensure fail_requirement really fails. */
248 fail_requirement(ctx
, &reason
);
251 /** Ensures that the "expect" state is correct.
253 * Call this function before modifying the current value of expect.
256 validate_expect(struct context
*ctx
)
258 if (ctx
->expect
== EXPECT_DEATH
) {
259 error_in_expect(ctx
, "Test case was expected to terminate abruptly "
260 "but it continued execution");
261 } else if (ctx
->expect
== EXPECT_EXIT
) {
262 error_in_expect(ctx
, "Test case was expected to exit cleanly but it "
263 "continued execution");
264 } else if (ctx
->expect
== EXPECT_FAIL
) {
265 if (ctx
->expect_fail_count
== ctx
->expect_previous_fail_count
)
266 error_in_expect(ctx
, "Test case was expecting a failure but none "
269 INV(ctx
->expect_fail_count
> ctx
->expect_previous_fail_count
);
270 } else if (ctx
->expect
== EXPECT_PASS
) {
271 /* Nothing to validate. */
272 } else if (ctx
->expect
== EXPECT_SIGNAL
) {
273 error_in_expect(ctx
, "Test case was expected to receive a termination "
274 "signal but it continued execution");
275 } else if (ctx
->expect
== EXPECT_TIMEOUT
) {
276 error_in_expect(ctx
, "Test case was expected to hang but it continued "
283 expected_failure(struct context
*ctx
, atf_dynstr_t
*reason
)
285 check_fatal_error(atf_dynstr_prepend_fmt(reason
, "%s: ",
286 atf_dynstr_cstring(&ctx
->expect_reason
)));
287 create_resfile(ctx
->resfile
, "expected_failure", -1, reason
);
292 fail_requirement(struct context
*ctx
, atf_dynstr_t
*reason
)
294 if (ctx
->expect
== EXPECT_FAIL
) {
295 expected_failure(ctx
, reason
);
296 } else if (ctx
->expect
== EXPECT_PASS
) {
297 create_resfile(ctx
->resfile
, "failed", -1, reason
);
300 error_in_expect(ctx
, "Test case raised a failure but was not "
301 "expecting one; reason was %s", atf_dynstr_cstring(reason
));
307 fail_check(struct context
*ctx
, atf_dynstr_t
*reason
)
309 if (ctx
->expect
== EXPECT_FAIL
) {
310 fprintf(stderr
, "*** Expected check failure: %s: %s\n",
311 atf_dynstr_cstring(&ctx
->expect_reason
),
312 atf_dynstr_cstring(reason
));
313 ctx
->expect_fail_count
++;
314 } else if (ctx
->expect
== EXPECT_PASS
) {
315 fprintf(stderr
, "*** Check failed: %s\n", atf_dynstr_cstring(reason
));
318 error_in_expect(ctx
, "Test case raised a failure but was not "
319 "expecting one; reason was %s", atf_dynstr_cstring(reason
));
322 atf_dynstr_fini(reason
);
326 pass(struct context
*ctx
)
328 if (ctx
->expect
== EXPECT_FAIL
) {
329 error_in_expect(ctx
, "Test case was expecting a failure but got "
331 } else if (ctx
->expect
== EXPECT_PASS
) {
332 create_resfile(ctx
->resfile
, "passed", -1, NULL
);
335 error_in_expect(ctx
, "Test case asked to explicitly pass but was "
336 "not expecting such condition");
342 skip(struct context
*ctx
, atf_dynstr_t
*reason
)
344 if (ctx
->expect
== EXPECT_PASS
) {
345 create_resfile(ctx
->resfile
, "skipped", -1, reason
);
348 error_in_expect(ctx
, "Can only skip a test case when running in "
354 /** Formats a failure/skip reason message.
356 * The formatted reason is stored in out_reason. out_reason is initialized
357 * in this function and is supposed to be released by the caller. In general,
358 * the reason will eventually be fed to create_resfile, which will release
361 * Errors in this function are fatal. Rationale being: reasons are used to
362 * create results files; if we can't format the reason correctly, the result
363 * of the test program will be bogus. So it's better to just exit with a
367 format_reason_ap(atf_dynstr_t
*out_reason
,
368 const char *source_file
, const size_t source_line
,
369 const char *reason
, va_list ap
)
373 if (source_file
!= NULL
) {
374 err
= atf_dynstr_init_fmt(out_reason
, "%s:%zd: ", source_file
,
377 PRE(source_line
== 0);
378 err
= atf_dynstr_init(out_reason
);
381 if (!atf_is_error(err
)) {
384 err
= atf_dynstr_append_ap(out_reason
, reason
, ap2
);
388 check_fatal_error(err
);
392 format_reason_fmt(atf_dynstr_t
*out_reason
,
393 const char *source_file
, const size_t source_line
,
394 const char *reason
, ...)
398 va_start(ap
, reason
);
399 format_reason_ap(out_reason
, source_file
, source_line
, reason
, ap
);
404 errno_test(struct context
*ctx
, const char *file
, const size_t line
,
405 const int exp_errno
, const char *expr_str
,
406 const bool expr_result
,
407 void (*fail_func
)(struct context
*, atf_dynstr_t
*))
409 const int actual_errno
= errno
;
412 if (exp_errno
!= actual_errno
) {
415 format_reason_fmt(&reason
, file
, line
, "Expected errno %d, got %d, "
416 "in %s", exp_errno
, actual_errno
, expr_str
);
417 fail_func(ctx
, &reason
);
422 format_reason_fmt(&reason
, file
, line
, "Expected true value in %s",
424 fail_func(ctx
, &reason
);
428 struct prog_found_pair
{
434 check_prog_in_dir(const char *dir
, void *data
)
436 struct prog_found_pair
*pf
= data
;
440 err
= atf_no_error();
444 err
= atf_fs_path_init_fmt(&p
, "%s/%s", dir
, pf
->prog
);
445 if (atf_is_error(err
))
448 err
= atf_fs_eaccess(&p
, atf_fs_access_x
);
449 if (!atf_is_error(err
))
454 err
= atf_no_error();
458 atf_fs_path_fini(&p
);
465 check_prog(struct context
*ctx
, const char *prog
)
470 err
= atf_fs_path_init_fmt(&p
, "%s", prog
);
471 if (atf_is_error(err
))
474 if (atf_fs_path_is_absolute(&p
)) {
475 err
= atf_fs_eaccess(&p
, atf_fs_access_x
);
476 if (atf_is_error(err
)) {
480 atf_fs_path_fini(&p
);
481 format_reason_fmt(&reason
, NULL
, 0, "The required program %s could "
482 "not be found", prog
);
486 const char *path
= atf_env_get("PATH");
487 struct prog_found_pair pf
;
490 err
= atf_fs_path_branch_path(&p
, &bp
);
491 if (atf_is_error(err
))
494 if (strcmp(atf_fs_path_cstring(&bp
), ".") != 0) {
495 atf_fs_path_fini(&bp
);
496 atf_fs_path_fini(&p
);
498 report_fatal_error("Relative paths are not allowed when searching "
499 "for a program (%s)", prog
);
505 err
= atf_text_for_each_word(path
, ":", check_prog_in_dir
, &pf
);
506 if (atf_is_error(err
))
512 atf_fs_path_fini(&bp
);
513 atf_fs_path_fini(&p
);
514 format_reason_fmt(&reason
, NULL
, 0, "The required program %s could "
515 "not be found in the PATH", prog
);
516 fail_requirement(ctx
, &reason
);
520 atf_fs_path_fini(&bp
);
524 atf_fs_path_fini(&p
);
529 /* ---------------------------------------------------------------------
531 * --------------------------------------------------------------------- */
539 atf_tc_head_t m_head
;
540 atf_tc_body_t m_body
;
541 atf_tc_cleanup_t m_cleanup
;
545 * Constructors/destructors.
549 atf_tc_init(atf_tc_t
*tc
, const char *ident
, atf_tc_head_t head
,
550 atf_tc_body_t body
, atf_tc_cleanup_t cleanup
,
551 const char *const *config
)
555 tc
->pimpl
= malloc(sizeof(struct atf_tc_impl
));
556 if (tc
->pimpl
== NULL
) {
557 err
= atf_no_memory_error();
561 tc
->pimpl
->m_ident
= ident
;
562 tc
->pimpl
->m_head
= head
;
563 tc
->pimpl
->m_body
= body
;
564 tc
->pimpl
->m_cleanup
= cleanup
;
566 err
= atf_map_init_charpp(&tc
->pimpl
->m_config
, config
);
567 if (atf_is_error(err
))
570 err
= atf_map_init(&tc
->pimpl
->m_vars
);
571 if (atf_is_error(err
))
574 err
= atf_tc_set_md_var(tc
, "ident", ident
);
575 if (atf_is_error(err
))
578 if (cleanup
!= NULL
) {
579 err
= atf_tc_set_md_var(tc
, "has.cleanup", "true");
580 if (atf_is_error(err
))
584 /* XXX Should the head be able to return error codes? */
585 if (tc
->pimpl
->m_head
!= NULL
)
586 tc
->pimpl
->m_head(tc
);
588 if (strcmp(atf_tc_get_md_var(tc
, "ident"), ident
) != 0) {
589 report_fatal_error("Test case head modified the read-only 'ident' "
594 INV(!atf_is_error(err
));
598 atf_map_fini(&tc
->pimpl
->m_vars
);
600 atf_map_fini(&tc
->pimpl
->m_config
);
606 atf_tc_init_pack(atf_tc_t
*tc
, const atf_tc_pack_t
*pack
,
607 const char *const *config
)
609 return atf_tc_init(tc
, pack
->m_ident
, pack
->m_head
, pack
->m_body
,
610 pack
->m_cleanup
, config
);
614 atf_tc_fini(atf_tc_t
*tc
)
616 atf_map_fini(&tc
->pimpl
->m_vars
);
625 atf_tc_get_ident(const atf_tc_t
*tc
)
627 return tc
->pimpl
->m_ident
;
631 atf_tc_get_config_var(const atf_tc_t
*tc
, const char *name
)
634 atf_map_citer_t iter
;
636 PRE(atf_tc_has_config_var(tc
, name
));
637 iter
= atf_map_find_c(&tc
->pimpl
->m_config
, name
);
638 val
= atf_map_citer_data(iter
);
645 atf_tc_get_config_var_wd(const atf_tc_t
*tc
, const char *name
,
650 if (!atf_tc_has_config_var(tc
, name
))
653 val
= atf_tc_get_config_var(tc
, name
);
659 atf_tc_get_config_var_as_bool(const atf_tc_t
*tc
, const char *name
)
665 strval
= atf_tc_get_config_var(tc
, name
);
666 err
= atf_text_to_bool(strval
, &val
);
667 if (atf_is_error(err
)) {
669 atf_tc_fail("Configuration variable %s does not have a valid "
670 "boolean value; found %s", name
, strval
);
677 atf_tc_get_config_var_as_bool_wd(const atf_tc_t
*tc
, const char *name
,
682 if (!atf_tc_has_config_var(tc
, name
))
685 val
= atf_tc_get_config_var_as_bool(tc
, name
);
691 atf_tc_get_config_var_as_long(const atf_tc_t
*tc
, const char *name
)
697 strval
= atf_tc_get_config_var(tc
, name
);
698 err
= atf_text_to_long(strval
, &val
);
699 if (atf_is_error(err
)) {
701 atf_tc_fail("Configuration variable %s does not have a valid "
702 "long value; found %s", name
, strval
);
709 atf_tc_get_config_var_as_long_wd(const atf_tc_t
*tc
, const char *name
,
714 if (!atf_tc_has_config_var(tc
, name
))
717 val
= atf_tc_get_config_var_as_long(tc
, name
);
723 atf_tc_get_md_var(const atf_tc_t
*tc
, const char *name
)
726 atf_map_citer_t iter
;
728 PRE(atf_tc_has_md_var(tc
, name
));
729 iter
= atf_map_find_c(&tc
->pimpl
->m_vars
, name
);
730 val
= atf_map_citer_data(iter
);
737 atf_tc_get_md_vars(const atf_tc_t
*tc
)
739 return atf_map_to_charpp(&tc
->pimpl
->m_vars
);
743 atf_tc_has_config_var(const atf_tc_t
*tc
, const char *name
)
745 atf_map_citer_t end
, iter
;
747 iter
= atf_map_find_c(&tc
->pimpl
->m_config
, name
);
748 end
= atf_map_end_c(&tc
->pimpl
->m_config
);
749 return !atf_equal_map_citer_map_citer(iter
, end
);
753 atf_tc_has_md_var(const atf_tc_t
*tc
, const char *name
)
755 atf_map_citer_t end
, iter
;
757 iter
= atf_map_find_c(&tc
->pimpl
->m_vars
, name
);
758 end
= atf_map_end_c(&tc
->pimpl
->m_vars
);
759 return !atf_equal_map_citer_map_citer(iter
, end
);
767 atf_tc_set_md_var(atf_tc_t
*tc
, const char *name
, const char *fmt
, ...)
774 err
= atf_text_format_ap(&value
, fmt
, ap
);
777 if (!atf_is_error(err
))
778 err
= atf_map_insert(&tc
->pimpl
->m_vars
, name
, value
, true);
785 /* ---------------------------------------------------------------------
786 * Free functions, as they should be publicly but they can't.
787 * --------------------------------------------------------------------- */
789 static void _atf_tc_fail(struct context
*, const char *, va_list)
790 ATF_DEFS_ATTRIBUTE_NORETURN
;
791 static void _atf_tc_fail_nonfatal(struct context
*, const char *, va_list);
792 static void _atf_tc_fail_check(struct context
*, const char *, const size_t,
793 const char *, va_list);
794 static void _atf_tc_fail_requirement(struct context
*, const char *,
795 const size_t, const char *, va_list) ATF_DEFS_ATTRIBUTE_NORETURN
;
796 static void _atf_tc_pass(struct context
*) ATF_DEFS_ATTRIBUTE_NORETURN
;
797 static void _atf_tc_require_prog(struct context
*, const char *);
798 static void _atf_tc_skip(struct context
*, const char *, va_list)
799 ATF_DEFS_ATTRIBUTE_NORETURN
;
800 static void _atf_tc_check_errno(struct context
*, const char *, const size_t,
801 const int, const char *, const bool);
802 static void _atf_tc_require_errno(struct context
*, const char *, const size_t,
803 const int, const char *, const bool);
804 static void _atf_tc_expect_pass(struct context
*);
805 static void _atf_tc_expect_fail(struct context
*, const char *, va_list);
806 static void _atf_tc_expect_exit(struct context
*, const int, const char *,
808 static void _atf_tc_expect_signal(struct context
*, const int, const char *,
810 static void _atf_tc_expect_death(struct context
*, const char *,
814 _atf_tc_fail(struct context
*ctx
, const char *fmt
, va_list ap
)
820 format_reason_ap(&reason
, NULL
, 0, fmt
, ap2
);
823 fail_requirement(ctx
, &reason
);
828 _atf_tc_fail_nonfatal(struct context
*ctx
, const char *fmt
, va_list ap
)
834 format_reason_ap(&reason
, NULL
, 0, fmt
, ap2
);
837 fail_check(ctx
, &reason
);
841 _atf_tc_fail_check(struct context
*ctx
, const char *file
, const size_t line
,
842 const char *fmt
, va_list ap
)
848 format_reason_ap(&reason
, file
, line
, fmt
, ap2
);
851 fail_check(ctx
, &reason
);
855 _atf_tc_fail_requirement(struct context
*ctx
, const char *file
,
856 const size_t line
, const char *fmt
, va_list ap
)
862 format_reason_ap(&reason
, file
, line
, fmt
, ap2
);
865 fail_requirement(ctx
, &reason
);
870 _atf_tc_pass(struct context
*ctx
)
877 _atf_tc_require_prog(struct context
*ctx
, const char *prog
)
879 check_fatal_error(check_prog(ctx
, prog
));
883 _atf_tc_skip(struct context
*ctx
, const char *fmt
, va_list ap
)
889 format_reason_ap(&reason
, NULL
, 0, fmt
, ap2
);
896 _atf_tc_check_errno(struct context
*ctx
, const char *file
, const size_t line
,
897 const int exp_errno
, const char *expr_str
,
898 const bool expr_result
)
900 errno_test(ctx
, file
, line
, exp_errno
, expr_str
, expr_result
, fail_check
);
904 _atf_tc_require_errno(struct context
*ctx
, const char *file
, const size_t line
,
905 const int exp_errno
, const char *expr_str
,
906 const bool expr_result
)
908 errno_test(ctx
, file
, line
, exp_errno
, expr_str
, expr_result
,
913 _atf_tc_expect_pass(struct context
*ctx
)
915 validate_expect(ctx
);
917 ctx
->expect
= EXPECT_PASS
;
921 _atf_tc_expect_fail(struct context
*ctx
, const char *reason
, va_list ap
)
925 validate_expect(ctx
);
927 ctx
->expect
= EXPECT_FAIL
;
928 atf_dynstr_fini(&ctx
->expect_reason
);
930 check_fatal_error(atf_dynstr_init_ap(&ctx
->expect_reason
, reason
, ap2
));
932 ctx
->expect_previous_fail_count
= ctx
->expect_fail_count
;
936 _atf_tc_expect_exit(struct context
*ctx
, const int exitcode
, const char *reason
,
940 atf_dynstr_t formatted
;
942 validate_expect(ctx
);
944 ctx
->expect
= EXPECT_EXIT
;
946 check_fatal_error(atf_dynstr_init_ap(&formatted
, reason
, ap2
));
949 create_resfile(ctx
->resfile
, "expected_exit", exitcode
, &formatted
);
953 _atf_tc_expect_signal(struct context
*ctx
, const int signo
, const char *reason
,
957 atf_dynstr_t formatted
;
959 validate_expect(ctx
);
961 ctx
->expect
= EXPECT_SIGNAL
;
963 check_fatal_error(atf_dynstr_init_ap(&formatted
, reason
, ap2
));
966 create_resfile(ctx
->resfile
, "expected_signal", signo
, &formatted
);
970 _atf_tc_expect_death(struct context
*ctx
, const char *reason
, va_list ap
)
973 atf_dynstr_t formatted
;
975 validate_expect(ctx
);
977 ctx
->expect
= EXPECT_DEATH
;
979 check_fatal_error(atf_dynstr_init_ap(&formatted
, reason
, ap2
));
982 create_resfile(ctx
->resfile
, "expected_death", -1, &formatted
);
986 _atf_tc_expect_timeout(struct context
*ctx
, const char *reason
, va_list ap
)
989 atf_dynstr_t formatted
;
991 validate_expect(ctx
);
993 ctx
->expect
= EXPECT_TIMEOUT
;
995 check_fatal_error(atf_dynstr_init_ap(&formatted
, reason
, ap2
));
998 create_resfile(ctx
->resfile
, "expected_timeout", -1, &formatted
);
1001 /* ---------------------------------------------------------------------
1003 * --------------------------------------------------------------------- */
1005 static struct context Current
;
1008 atf_tc_run(const atf_tc_t
*tc
, const char *resfile
)
1010 context_init(&Current
, tc
, resfile
);
1012 tc
->pimpl
->m_body(tc
);
1014 validate_expect(&Current
);
1016 if (Current
.fail_count
> 0) {
1017 atf_dynstr_t reason
;
1019 format_reason_fmt(&reason
, NULL
, 0, "%d checks failed; see output for "
1020 "more details", Current
.fail_count
);
1021 fail_requirement(&Current
, &reason
);
1022 } else if (Current
.expect_fail_count
> 0) {
1023 atf_dynstr_t reason
;
1025 format_reason_fmt(&reason
, NULL
, 0, "%d checks failed as expected; "
1026 "see output for more details", Current
.expect_fail_count
);
1027 expected_failure(&Current
, &reason
);
1032 return atf_no_error();
1036 atf_tc_cleanup(const atf_tc_t
*tc
)
1038 if (tc
->pimpl
->m_cleanup
!= NULL
)
1039 tc
->pimpl
->m_cleanup(tc
);
1040 return atf_no_error(); /* XXX */
1043 /* ---------------------------------------------------------------------
1044 * Free functions that depend on Current.
1045 * --------------------------------------------------------------------- */
1048 * All the functions below provide delegates to other internal functions
1049 * (prefixed by _) that take the current test case as an argument to
1050 * prevent them from accessing global state. This is to keep the side-
1051 * effects of the internal functions clearer and easier to understand.
1053 * The public API should never have hid the fact that it needs access to
1054 * the current test case (other than maybe in the macros), but changing it
1055 * is hard. TODO: Revisit in the future.
1059 atf_tc_fail(const char *fmt
, ...)
1063 PRE(Current
.tc
!= NULL
);
1066 _atf_tc_fail(&Current
, fmt
, ap
);
1071 atf_tc_fail_nonfatal(const char *fmt
, ...)
1075 PRE(Current
.tc
!= NULL
);
1078 _atf_tc_fail_nonfatal(&Current
, fmt
, ap
);
1083 atf_tc_fail_check(const char *file
, const size_t line
, const char *fmt
, ...)
1087 PRE(Current
.tc
!= NULL
);
1090 _atf_tc_fail_check(&Current
, file
, line
, fmt
, ap
);
1095 atf_tc_fail_requirement(const char *file
, const size_t line
,
1096 const char *fmt
, ...)
1100 PRE(Current
.tc
!= NULL
);
1103 _atf_tc_fail_requirement(&Current
, file
, line
, fmt
, ap
);
1110 PRE(Current
.tc
!= NULL
);
1112 _atf_tc_pass(&Current
);
1116 atf_tc_require_prog(const char *prog
)
1118 PRE(Current
.tc
!= NULL
);
1120 _atf_tc_require_prog(&Current
, prog
);
1124 atf_tc_skip(const char *fmt
, ...)
1128 PRE(Current
.tc
!= NULL
);
1131 _atf_tc_skip(&Current
, fmt
, ap
);
1136 atf_tc_check_errno(const char *file
, const size_t line
, const int exp_errno
,
1137 const char *expr_str
, const bool expr_result
)
1139 PRE(Current
.tc
!= NULL
);
1141 _atf_tc_check_errno(&Current
, file
, line
, exp_errno
, expr_str
,
1146 atf_tc_require_errno(const char *file
, const size_t line
, const int exp_errno
,
1147 const char *expr_str
, const bool expr_result
)
1149 PRE(Current
.tc
!= NULL
);
1151 _atf_tc_require_errno(&Current
, file
, line
, exp_errno
, expr_str
,
1156 atf_tc_expect_pass(void)
1158 PRE(Current
.tc
!= NULL
);
1160 _atf_tc_expect_pass(&Current
);
1164 atf_tc_expect_fail(const char *reason
, ...)
1168 PRE(Current
.tc
!= NULL
);
1170 va_start(ap
, reason
);
1171 _atf_tc_expect_fail(&Current
, reason
, ap
);
1176 atf_tc_expect_exit(const int exitcode
, const char *reason
, ...)
1180 PRE(Current
.tc
!= NULL
);
1182 va_start(ap
, reason
);
1183 _atf_tc_expect_exit(&Current
, exitcode
, reason
, ap
);
1188 atf_tc_expect_signal(const int signo
, const char *reason
, ...)
1192 PRE(Current
.tc
!= NULL
);
1194 va_start(ap
, reason
);
1195 _atf_tc_expect_signal(&Current
, signo
, reason
, ap
);
1200 atf_tc_expect_death(const char *reason
, ...)
1204 PRE(Current
.tc
!= NULL
);
1206 va_start(ap
, reason
);
1207 _atf_tc_expect_death(&Current
, reason
, ap
);
1212 atf_tc_expect_timeout(const char *reason
, ...)
1216 PRE(Current
.tc
!= NULL
);
1218 va_start(ap
, reason
);
1219 _atf_tc_expect_timeout(&Current
, reason
, ap
);