1 /* $NetBSD: tc.c,v 1.3 2014/12/10 04:38:03 christos Exp $ */
4 * Automated Testing Framework (atf)
6 * Copyright (c) 2008 The NetBSD Foundation, Inc.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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>
45 #include "atf-c/defs.h"
46 #include "atf-c/error.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 * --------------------------------------------------------------------- */
73 enum expect_type expect
;
74 atf_dynstr_t expect_reason
;
75 size_t expect_previous_fail_count
;
76 size_t expect_fail_count
;
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,
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,
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 *);
112 context_init(struct context
*ctx
, const atf_tc_t
*tc
, const char *resfile
)
115 ctx
->resfile
= resfile
;
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;
126 check_fatal_error(atf_error_t err
)
128 if (atf_is_error(err
)) {
130 atf_error_format(err
, buf
, sizeof(buf
));
131 fprintf(stderr
, "FATAL ERROR: %s\n", buf
);
138 report_fatal_error(const char *msg
, ...)
141 fprintf(stderr
, "FATAL ERROR: ");
144 vfprintf(stderr
, msg
, ap
);
147 fprintf(stderr
, "\n");
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.
159 write_resfile(const int fd
, const char *result
, const int arg
,
160 const atf_dynstr_t
*reason
)
162 static char NL
[] = "\n", CS
[] = ": ";
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
) {
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
);
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. */
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.
211 create_resfile(const char *resfile
, const char *result
, const int arg
,
212 atf_dynstr_t
*reason
)
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
);
221 const int fd
= open(resfile
, O_WRONLY
| O_CREAT
| O_TRUNC
,
222 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
);
224 err
= atf_libc_error(errno
, "Cannot create results file '%s'",
227 err
= write_resfile(fd
, result
, arg
, reason
);
233 atf_dynstr_fini(reason
);
235 check_fatal_error(err
);
238 /** Fails a test case if validate_expect fails. */
240 error_in_expect(struct context
*ctx
, const char *fmt
, ...)
246 format_reason_ap(&reason
, NULL
, 0, fmt
, 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.
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 "
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 "
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
);
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
);
302 error_in_expect(ctx
, "Test case raised a failure but was not "
303 "expecting one; reason was %s", atf_dynstr_cstring(reason
));
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
));
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
);
328 pass(struct context
*ctx
)
330 if (ctx
->expect
== EXPECT_FAIL
) {
331 error_in_expect(ctx
, "Test case was expecting a failure but got "
333 } else if (ctx
->expect
== EXPECT_PASS
) {
334 create_resfile(ctx
->resfile
, "passed", -1, NULL
);
337 error_in_expect(ctx
, "Test case asked to explicitly pass but was "
338 "not expecting such condition");
344 skip(struct context
*ctx
, atf_dynstr_t
*reason
)
346 if (ctx
->expect
== EXPECT_PASS
) {
347 create_resfile(ctx
->resfile
, "skipped", -1, reason
);
350 error_in_expect(ctx
, "Can only skip a test case when running in "
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
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
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
)
375 if (source_file
!= NULL
) {
376 err
= atf_dynstr_init_fmt(out_reason
, "%s:%zd: ", source_file
,
379 PRE(source_line
== 0);
380 err
= atf_dynstr_init(out_reason
);
383 if (!atf_is_error(err
)) {
386 err
= atf_dynstr_append_ap(out_reason
, reason
, ap2
);
390 check_fatal_error(err
);
394 format_reason_fmt(atf_dynstr_t
*out_reason
,
395 const char *source_file
, const size_t source_line
,
396 const char *reason
, ...)
400 va_start(ap
, reason
);
401 format_reason_ap(out_reason
, source_file
, source_line
, reason
, ap
);
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
;
414 if (exp_errno
!= actual_errno
) {
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
);
424 format_reason_fmt(&reason
, file
, line
, "Expected true value in %s",
426 fail_func(ctx
, &reason
);
430 struct prog_found_pair
{
436 check_prog_in_dir(const char *dir
, void *data
)
438 struct prog_found_pair
*pf
= data
;
442 err
= atf_no_error();
446 err
= atf_fs_path_init_fmt(&p
, "%s/%s", dir
, pf
->prog
);
447 if (atf_is_error(err
))
450 err
= atf_fs_eaccess(&p
, atf_fs_access_x
);
451 if (!atf_is_error(err
))
456 err
= atf_no_error();
460 atf_fs_path_fini(&p
);
467 check_prog(struct context
*ctx
, const char *prog
)
472 err
= atf_fs_path_init_fmt(&p
, "%s", prog
);
473 if (atf_is_error(err
))
476 if (atf_fs_path_is_absolute(&p
)) {
477 err
= atf_fs_eaccess(&p
, atf_fs_access_x
);
478 if (atf_is_error(err
)) {
482 atf_fs_path_fini(&p
);
483 format_reason_fmt(&reason
, NULL
, 0, "The required program %s could "
484 "not be found", prog
);
488 const char *path
= atf_env_get("PATH");
489 struct prog_found_pair pf
;
492 err
= atf_fs_path_branch_path(&p
, &bp
);
493 if (atf_is_error(err
))
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
);
507 err
= atf_text_for_each_word(path
, ":", check_prog_in_dir
, &pf
);
508 if (atf_is_error(err
))
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
);
522 atf_fs_path_fini(&bp
);
526 atf_fs_path_fini(&p
);
531 /* ---------------------------------------------------------------------
533 * --------------------------------------------------------------------- */
541 atf_tc_head_t m_head
;
542 atf_tc_body_t m_body
;
543 atf_tc_cleanup_t m_cleanup
;
547 * Constructors/destructors.
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
)
557 tc
->pimpl
= malloc(sizeof(struct atf_tc_impl
));
558 if (tc
->pimpl
== NULL
) {
559 err
= atf_no_memory_error();
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
))
572 err
= atf_map_init(&tc
->pimpl
->m_vars
);
573 if (atf_is_error(err
))
576 err
= atf_tc_set_md_var(tc
, "ident", ident
);
577 if (atf_is_error(err
))
580 if (cleanup
!= NULL
) {
581 err
= atf_tc_set_md_var(tc
, "has.cleanup", "true");
582 if (atf_is_error(err
))
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' "
596 INV(!atf_is_error(err
));
600 atf_map_fini(&tc
->pimpl
->m_vars
);
602 atf_map_fini(&tc
->pimpl
->m_config
);
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
);
616 atf_tc_fini(atf_tc_t
*tc
)
618 atf_map_fini(&tc
->pimpl
->m_vars
);
627 atf_tc_get_ident(const atf_tc_t
*tc
)
629 return tc
->pimpl
->m_ident
;
633 atf_tc_get_config_var(const atf_tc_t
*tc
, const char *name
)
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
);
647 atf_tc_get_config_var_wd(const atf_tc_t
*tc
, const char *name
,
652 if (!atf_tc_has_config_var(tc
, name
))
655 val
= atf_tc_get_config_var(tc
, name
);
661 atf_tc_get_config_var_as_bool(const atf_tc_t
*tc
, const char *name
)
667 strval
= atf_tc_get_config_var(tc
, name
);
668 err
= atf_text_to_bool(strval
, &val
);
669 if (atf_is_error(err
)) {
671 atf_tc_fail("Configuration variable %s does not have a valid "
672 "boolean value; found %s", name
, strval
);
679 atf_tc_get_config_var_as_bool_wd(const atf_tc_t
*tc
, const char *name
,
684 if (!atf_tc_has_config_var(tc
, name
))
687 val
= atf_tc_get_config_var_as_bool(tc
, name
);
693 atf_tc_get_config_var_as_long(const atf_tc_t
*tc
, const char *name
)
699 strval
= atf_tc_get_config_var(tc
, name
);
700 err
= atf_text_to_long(strval
, &val
);
701 if (atf_is_error(err
)) {
703 atf_tc_fail("Configuration variable %s does not have a valid "
704 "long value; found %s", name
, strval
);
711 atf_tc_get_config_var_as_long_wd(const atf_tc_t
*tc
, const char *name
,
716 if (!atf_tc_has_config_var(tc
, name
))
719 val
= atf_tc_get_config_var_as_long(tc
, name
);
725 atf_tc_get_md_var(const atf_tc_t
*tc
, const char *name
)
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
);
739 atf_tc_get_md_vars(const atf_tc_t
*tc
)
741 return atf_map_to_charpp(&tc
->pimpl
->m_vars
);
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
);
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
);
769 atf_tc_set_md_var(atf_tc_t
*tc
, const char *name
, const char *fmt
, ...)
776 err
= atf_text_format_ap(&value
, fmt
, ap
);
779 if (!atf_is_error(err
))
780 err
= atf_map_insert(&tc
->pimpl
->m_vars
, name
, value
, true);
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 *,
810 static void _atf_tc_expect_signal(struct context
*, const int, const char *,
812 static void _atf_tc_expect_death(struct context
*, const char *,
816 _atf_tc_fail(struct context
*ctx
, const char *fmt
, va_list ap
)
822 format_reason_ap(&reason
, NULL
, 0, fmt
, ap2
);
825 fail_requirement(ctx
, &reason
);
830 _atf_tc_fail_nonfatal(struct context
*ctx
, const char *fmt
, va_list ap
)
836 format_reason_ap(&reason
, NULL
, 0, fmt
, ap2
);
839 fail_check(ctx
, &reason
);
843 _atf_tc_fail_check(struct context
*ctx
, const char *file
, const size_t line
,
844 const char *fmt
, va_list ap
)
850 format_reason_ap(&reason
, file
, line
, fmt
, ap2
);
853 fail_check(ctx
, &reason
);
857 _atf_tc_fail_requirement(struct context
*ctx
, const char *file
,
858 const size_t line
, const char *fmt
, va_list ap
)
864 format_reason_ap(&reason
, file
, line
, fmt
, ap2
);
867 fail_requirement(ctx
, &reason
);
872 _atf_tc_pass(struct context
*ctx
)
879 _atf_tc_require_prog(struct context
*ctx
, const char *prog
)
881 check_fatal_error(check_prog(ctx
, prog
));
885 _atf_tc_skip(struct context
*ctx
, const char *fmt
, va_list ap
)
891 format_reason_ap(&reason
, NULL
, 0, fmt
, ap2
);
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
);
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
,
915 _atf_tc_expect_pass(struct context
*ctx
)
917 validate_expect(ctx
);
919 ctx
->expect
= EXPECT_PASS
;
923 _atf_tc_expect_fail(struct context
*ctx
, const char *reason
, va_list ap
)
927 validate_expect(ctx
);
929 ctx
->expect
= EXPECT_FAIL
;
930 atf_dynstr_fini(&ctx
->expect_reason
);
932 check_fatal_error(atf_dynstr_init_ap(&ctx
->expect_reason
, reason
, ap2
));
934 ctx
->expect_previous_fail_count
= ctx
->expect_fail_count
;
938 _atf_tc_expect_exit(struct context
*ctx
, const int exitcode
, const char *reason
,
942 atf_dynstr_t formatted
;
944 validate_expect(ctx
);
946 ctx
->expect
= EXPECT_EXIT
;
948 check_fatal_error(atf_dynstr_init_ap(&formatted
, reason
, ap2
));
951 create_resfile(ctx
->resfile
, "expected_exit", exitcode
, &formatted
);
955 _atf_tc_expect_signal(struct context
*ctx
, const int signo
, const char *reason
,
959 atf_dynstr_t formatted
;
961 validate_expect(ctx
);
963 ctx
->expect
= EXPECT_SIGNAL
;
965 check_fatal_error(atf_dynstr_init_ap(&formatted
, reason
, ap2
));
968 create_resfile(ctx
->resfile
, "expected_signal", signo
, &formatted
);
972 _atf_tc_expect_death(struct context
*ctx
, const char *reason
, va_list ap
)
975 atf_dynstr_t formatted
;
977 validate_expect(ctx
);
979 ctx
->expect
= EXPECT_DEATH
;
981 check_fatal_error(atf_dynstr_init_ap(&formatted
, reason
, ap2
));
984 create_resfile(ctx
->resfile
, "expected_death", -1, &formatted
);
988 _atf_tc_expect_timeout(struct context
*ctx
, const char *reason
, va_list ap
)
991 atf_dynstr_t formatted
;
993 validate_expect(ctx
);
995 ctx
->expect
= EXPECT_TIMEOUT
;
997 check_fatal_error(atf_dynstr_init_ap(&formatted
, reason
, ap2
));
1000 create_resfile(ctx
->resfile
, "expected_timeout", -1, &formatted
);
1003 /* ---------------------------------------------------------------------
1005 * --------------------------------------------------------------------- */
1007 static struct context Current
;
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
);
1034 return atf_no_error();
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.
1061 atf_tc_fail(const char *fmt
, ...)
1065 PRE(Current
.tc
!= NULL
);
1068 _atf_tc_fail(&Current
, fmt
, ap
);
1073 atf_tc_fail_nonfatal(const char *fmt
, ...)
1077 PRE(Current
.tc
!= NULL
);
1080 _atf_tc_fail_nonfatal(&Current
, fmt
, ap
);
1085 atf_tc_fail_check(const char *file
, const size_t line
, const char *fmt
, ...)
1089 PRE(Current
.tc
!= NULL
);
1092 _atf_tc_fail_check(&Current
, file
, line
, fmt
, ap
);
1097 atf_tc_fail_requirement(const char *file
, const size_t line
,
1098 const char *fmt
, ...)
1102 PRE(Current
.tc
!= NULL
);
1105 _atf_tc_fail_requirement(&Current
, file
, line
, fmt
, ap
);
1112 PRE(Current
.tc
!= NULL
);
1114 _atf_tc_pass(&Current
);
1118 atf_tc_require_prog(const char *prog
)
1120 PRE(Current
.tc
!= NULL
);
1122 _atf_tc_require_prog(&Current
, prog
);
1126 atf_tc_skip(const char *fmt
, ...)
1130 PRE(Current
.tc
!= NULL
);
1133 _atf_tc_skip(&Current
, fmt
, ap
);
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
,
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
,
1158 atf_tc_expect_pass(void)
1160 PRE(Current
.tc
!= NULL
);
1162 _atf_tc_expect_pass(&Current
);
1166 atf_tc_expect_fail(const char *reason
, ...)
1170 PRE(Current
.tc
!= NULL
);
1172 va_start(ap
, reason
);
1173 _atf_tc_expect_fail(&Current
, reason
, ap
);
1178 atf_tc_expect_exit(const int exitcode
, const char *reason
, ...)
1182 PRE(Current
.tc
!= NULL
);
1184 va_start(ap
, reason
);
1185 _atf_tc_expect_exit(&Current
, exitcode
, reason
, ap
);
1190 atf_tc_expect_signal(const int signo
, const char *reason
, ...)
1194 PRE(Current
.tc
!= NULL
);
1196 va_start(ap
, reason
);
1197 _atf_tc_expect_signal(&Current
, signo
, reason
, ap
);
1202 atf_tc_expect_death(const char *reason
, ...)
1206 PRE(Current
.tc
!= NULL
);
1208 va_start(ap
, reason
);
1209 _atf_tc_expect_death(&Current
, reason
, ap
);
1214 atf_tc_expect_timeout(const char *reason
, ...)
1218 PRE(Current
.tc
!= NULL
);
1220 va_start(ap
, reason
);
1221 _atf_tc_expect_timeout(&Current
, reason
, ap
);