Home | History | Annotate | Line # | Download | only in atf-c
tc.c revision 1.13
      1   1.1      jmmv /*
      2   1.1      jmmv  * Automated Testing Framework (atf)
      3   1.1      jmmv  *
      4  1.12      jmmv  * Copyright (c) 2008 The NetBSD Foundation, Inc.
      5   1.1      jmmv  * All rights reserved.
      6   1.1      jmmv  *
      7   1.1      jmmv  * Redistribution and use in source and binary forms, with or without
      8   1.1      jmmv  * modification, are permitted provided that the following conditions
      9   1.1      jmmv  * are met:
     10   1.1      jmmv  * 1. Redistributions of source code must retain the above copyright
     11   1.1      jmmv  *    notice, this list of conditions and the following disclaimer.
     12   1.1      jmmv  * 2. Redistributions in binary form must reproduce the above copyright
     13   1.1      jmmv  *    notice, this list of conditions and the following disclaimer in the
     14   1.1      jmmv  *    documentation and/or other materials provided with the distribution.
     15   1.1      jmmv  *
     16   1.1      jmmv  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
     17   1.1      jmmv  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
     18   1.1      jmmv  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     19   1.1      jmmv  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20   1.1      jmmv  * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
     21   1.1      jmmv  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22   1.1      jmmv  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     23   1.1      jmmv  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     24   1.1      jmmv  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
     25   1.1      jmmv  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     26   1.1      jmmv  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     27   1.1      jmmv  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28   1.1      jmmv  */
     29   1.1      jmmv 
     30   1.7      jmmv #include <sys/types.h>
     31   1.7      jmmv #include <sys/stat.h>
     32  1.10  christos #include <sys/uio.h>
     33   1.7      jmmv 
     34   1.1      jmmv #include <errno.h>
     35   1.7      jmmv #include <fcntl.h>
     36   1.1      jmmv #include <stdarg.h>
     37   1.1      jmmv #include <stdbool.h>
     38   1.1      jmmv #include <stdio.h>
     39   1.1      jmmv #include <stdlib.h>
     40   1.1      jmmv #include <string.h>
     41   1.1      jmmv #include <unistd.h>
     42   1.1      jmmv 
     43   1.3      jmmv #include "atf-c/defs.h"
     44   1.1      jmmv #include "atf-c/error.h"
     45   1.1      jmmv #include "atf-c/tc.h"
     46   1.7      jmmv 
     47   1.7      jmmv #include "detail/env.h"
     48   1.7      jmmv #include "detail/fs.h"
     49   1.7      jmmv #include "detail/map.h"
     50   1.7      jmmv #include "detail/sanity.h"
     51   1.7      jmmv #include "detail/text.h"
     52   1.1      jmmv 
     53   1.1      jmmv /* ---------------------------------------------------------------------
     54   1.6      jmmv  * Auxiliary functions.
     55   1.1      jmmv  * --------------------------------------------------------------------- */
     56   1.1      jmmv 
     57   1.6      jmmv enum expect_type {
     58   1.6      jmmv     EXPECT_PASS,
     59   1.6      jmmv     EXPECT_FAIL,
     60   1.6      jmmv     EXPECT_EXIT,
     61   1.6      jmmv     EXPECT_SIGNAL,
     62   1.6      jmmv     EXPECT_DEATH,
     63   1.6      jmmv     EXPECT_TIMEOUT,
     64   1.6      jmmv };
     65   1.6      jmmv 
     66   1.6      jmmv struct context {
     67   1.6      jmmv     const atf_tc_t *tc;
     68   1.7      jmmv     const char *resfile;
     69   1.6      jmmv     size_t fail_count;
     70   1.6      jmmv 
     71   1.6      jmmv     enum expect_type expect;
     72   1.6      jmmv     atf_dynstr_t expect_reason;
     73   1.6      jmmv     size_t expect_previous_fail_count;
     74   1.6      jmmv     size_t expect_fail_count;
     75   1.6      jmmv     int expect_exitcode;
     76   1.6      jmmv     int expect_signo;
     77   1.6      jmmv };
     78   1.6      jmmv 
     79   1.7      jmmv static void context_init(struct context *, const atf_tc_t *, const char *);
     80   1.6      jmmv static void check_fatal_error(atf_error_t);
     81   1.6      jmmv static void report_fatal_error(const char *, ...)
     82  1.13     joerg     ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(1, 2)
     83   1.6      jmmv     ATF_DEFS_ATTRIBUTE_NORETURN;
     84   1.7      jmmv static atf_error_t write_resfile(const int, const char *, const int,
     85   1.6      jmmv                                  const atf_dynstr_t *);
     86   1.7      jmmv static void create_resfile(const char *, const char *, const int,
     87   1.6      jmmv                            atf_dynstr_t *);
     88   1.6      jmmv static void error_in_expect(struct context *, const char *, ...)
     89  1.13     joerg     ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(2, 3)
     90   1.6      jmmv     ATF_DEFS_ATTRIBUTE_NORETURN;
     91   1.6      jmmv static void validate_expect(struct context *);
     92   1.6      jmmv static void expected_failure(struct context *, atf_dynstr_t *)
     93   1.6      jmmv     ATF_DEFS_ATTRIBUTE_NORETURN;
     94   1.6      jmmv static void fail_requirement(struct context *, atf_dynstr_t *)
     95   1.6      jmmv     ATF_DEFS_ATTRIBUTE_NORETURN;
     96   1.6      jmmv static void fail_check(struct context *, atf_dynstr_t *);
     97   1.6      jmmv static void pass(struct context *)
     98   1.6      jmmv     ATF_DEFS_ATTRIBUTE_NORETURN;
     99   1.6      jmmv static void skip(struct context *, atf_dynstr_t *)
    100   1.6      jmmv     ATF_DEFS_ATTRIBUTE_NORETURN;
    101   1.6      jmmv static void format_reason_ap(atf_dynstr_t *, const char *, const size_t,
    102  1.13     joerg                              const char *, va_list)
    103  1.13     joerg     ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(4, 0);
    104   1.6      jmmv static void format_reason_fmt(atf_dynstr_t *, const char *, const size_t,
    105  1.13     joerg                               const char *, ...)
    106  1.13     joerg     ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(4, 5);
    107   1.6      jmmv static void errno_test(struct context *, const char *, const size_t,
    108   1.6      jmmv                        const int, const char *, const bool,
    109   1.6      jmmv                        void (*)(struct context *, atf_dynstr_t *));
    110   1.1      jmmv static atf_error_t check_prog_in_dir(const char *, void *);
    111  1.12      jmmv static atf_error_t check_prog(struct context *, const char *);
    112   1.6      jmmv 
    113   1.6      jmmv static void
    114   1.7      jmmv context_init(struct context *ctx, const atf_tc_t *tc, const char *resfile)
    115   1.6      jmmv {
    116   1.6      jmmv     ctx->tc = tc;
    117   1.6      jmmv     ctx->resfile = resfile;
    118   1.6      jmmv     ctx->fail_count = 0;
    119   1.6      jmmv     ctx->expect = EXPECT_PASS;
    120   1.6      jmmv     check_fatal_error(atf_dynstr_init(&ctx->expect_reason));
    121   1.6      jmmv     ctx->expect_previous_fail_count = 0;
    122   1.6      jmmv     ctx->expect_fail_count = 0;
    123   1.6      jmmv     ctx->expect_exitcode = 0;
    124   1.6      jmmv     ctx->expect_signo = 0;
    125   1.6      jmmv }
    126   1.6      jmmv 
    127   1.6      jmmv static void
    128   1.6      jmmv check_fatal_error(atf_error_t err)
    129   1.6      jmmv {
    130   1.6      jmmv     if (atf_is_error(err)) {
    131   1.6      jmmv         char buf[1024];
    132   1.6      jmmv         atf_error_format(err, buf, sizeof(buf));
    133   1.6      jmmv         fprintf(stderr, "FATAL ERROR: %s\n", buf);
    134   1.6      jmmv         atf_error_free(err);
    135   1.6      jmmv         abort();
    136   1.6      jmmv     }
    137   1.6      jmmv }
    138   1.6      jmmv 
    139   1.6      jmmv static void
    140   1.6      jmmv report_fatal_error(const char *msg, ...)
    141   1.6      jmmv {
    142   1.6      jmmv     va_list ap;
    143   1.6      jmmv     fprintf(stderr, "FATAL ERROR: ");
    144   1.6      jmmv 
    145   1.6      jmmv     va_start(ap, msg);
    146   1.6      jmmv     vfprintf(stderr, msg, ap);
    147   1.6      jmmv     va_end(ap);
    148   1.6      jmmv 
    149   1.6      jmmv     fprintf(stderr, "\n");
    150   1.6      jmmv     abort();
    151   1.6      jmmv }
    152   1.6      jmmv 
    153   1.6      jmmv /** Writes to a results file.
    154   1.6      jmmv  *
    155   1.6      jmmv  * The results file is supposed to be already open.
    156   1.6      jmmv  *
    157   1.6      jmmv  * This function returns an error code instead of exiting in case of error
    158   1.6      jmmv  * because the caller needs to clean up the reason object before terminating.
    159   1.6      jmmv  */
    160   1.6      jmmv static atf_error_t
    161   1.7      jmmv write_resfile(const int fd, const char *result, const int arg,
    162   1.6      jmmv               const atf_dynstr_t *reason)
    163   1.6      jmmv {
    164  1.10  christos     static char NL[] = "\n", CS[] = ": ";
    165  1.10  christos     char buf[64];
    166  1.10  christos     const char *r;
    167  1.10  christos     struct iovec iov[5];
    168  1.10  christos     ssize_t ret;
    169  1.10  christos     int count = 0;
    170  1.10  christos 
    171  1.11  christos     INV(arg == -1 || reason != NULL);
    172  1.10  christos 
    173  1.12      jmmv #define UNCONST(a) ((void *)(unsigned long)(const void *)(a))
    174  1.12      jmmv     iov[count].iov_base = UNCONST(result);
    175  1.10  christos     iov[count++].iov_len = strlen(result);
    176  1.10  christos 
    177  1.10  christos     if (reason != NULL) {
    178  1.12      jmmv         if (arg != -1) {
    179  1.12      jmmv             iov[count].iov_base = buf;
    180  1.12      jmmv             iov[count++].iov_len = snprintf(buf, sizeof(buf), "(%d)", arg);
    181  1.12      jmmv         }
    182  1.12      jmmv 
    183  1.12      jmmv         iov[count].iov_base = CS;
    184  1.12      jmmv         iov[count++].iov_len = sizeof(CS) - 1;
    185  1.12      jmmv 
    186  1.12      jmmv         r = atf_dynstr_cstring(reason);
    187  1.12      jmmv         iov[count].iov_base = UNCONST(r);
    188  1.12      jmmv         iov[count++].iov_len = strlen(r);
    189   1.7      jmmv     }
    190  1.12      jmmv #undef UNCONST
    191   1.6      jmmv 
    192  1.10  christos     iov[count].iov_base = NL;
    193  1.10  christos     iov[count++].iov_len = sizeof(NL) - 1;
    194  1.10  christos 
    195  1.10  christos     while ((ret = writev(fd, iov, count)) == -1 && errno == EINTR)
    196  1.10  christos         continue; /* Retry. */
    197  1.10  christos     if (ret != -1)
    198  1.10  christos         return atf_no_error();
    199   1.6      jmmv 
    200   1.7      jmmv     return atf_libc_error(
    201   1.7      jmmv         errno, "Failed to write results file; result %s, reason %s", result,
    202   1.6      jmmv         reason == NULL ? "null" : atf_dynstr_cstring(reason));
    203   1.6      jmmv }
    204   1.6      jmmv 
    205   1.6      jmmv /** Creates a results file.
    206   1.6      jmmv  *
    207   1.6      jmmv  * The input reason is released in all cases.
    208   1.6      jmmv  *
    209   1.6      jmmv  * An error in this function is considered to be fatal, hence why it does
    210   1.6      jmmv  * not return any error code.
    211   1.6      jmmv  */
    212   1.6      jmmv static void
    213   1.7      jmmv create_resfile(const char *resfile, const char *result, const int arg,
    214   1.6      jmmv                atf_dynstr_t *reason)
    215   1.6      jmmv {
    216   1.6      jmmv     atf_error_t err;
    217   1.6      jmmv 
    218   1.7      jmmv     if (strcmp("/dev/stdout", resfile) == 0) {
    219   1.7      jmmv         err = write_resfile(STDOUT_FILENO, result, arg, reason);
    220   1.7      jmmv     } else if (strcmp("/dev/stderr", resfile) == 0) {
    221   1.7      jmmv         err = write_resfile(STDERR_FILENO, result, arg, reason);
    222   1.6      jmmv     } else {
    223   1.7      jmmv         const int fd = open(resfile, O_WRONLY | O_CREAT | O_TRUNC,
    224   1.7      jmmv             S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
    225   1.7      jmmv         if (fd == -1) {
    226   1.6      jmmv             err = atf_libc_error(errno, "Cannot create results file '%s'",
    227   1.7      jmmv                                  resfile);
    228   1.6      jmmv         } else {
    229   1.7      jmmv             err = write_resfile(fd, result, arg, reason);
    230   1.7      jmmv             close(fd);
    231   1.6      jmmv         }
    232   1.6      jmmv     }
    233   1.6      jmmv 
    234   1.6      jmmv     if (reason != NULL)
    235   1.6      jmmv         atf_dynstr_fini(reason);
    236   1.6      jmmv 
    237   1.6      jmmv     check_fatal_error(err);
    238   1.6      jmmv }
    239   1.6      jmmv 
    240   1.6      jmmv /** Fails a test case if validate_expect fails. */
    241   1.6      jmmv static void
    242   1.6      jmmv error_in_expect(struct context *ctx, const char *fmt, ...)
    243   1.6      jmmv {
    244   1.6      jmmv     atf_dynstr_t reason;
    245   1.6      jmmv     va_list ap;
    246   1.6      jmmv 
    247   1.6      jmmv     va_start(ap, fmt);
    248   1.6      jmmv     format_reason_ap(&reason, NULL, 0, fmt, ap);
    249   1.6      jmmv     va_end(ap);
    250   1.6      jmmv 
    251   1.6      jmmv     ctx->expect = EXPECT_PASS;  /* Ensure fail_requirement really fails. */
    252   1.6      jmmv     fail_requirement(ctx, &reason);
    253   1.6      jmmv }
    254   1.6      jmmv 
    255   1.6      jmmv /** Ensures that the "expect" state is correct.
    256   1.6      jmmv  *
    257   1.6      jmmv  * Call this function before modifying the current value of expect.
    258   1.6      jmmv  */
    259   1.6      jmmv static void
    260   1.6      jmmv validate_expect(struct context *ctx)
    261   1.6      jmmv {
    262   1.6      jmmv     if (ctx->expect == EXPECT_DEATH) {
    263   1.6      jmmv         error_in_expect(ctx, "Test case was expected to terminate abruptly "
    264   1.6      jmmv             "but it continued execution");
    265   1.6      jmmv     } else if (ctx->expect == EXPECT_EXIT) {
    266   1.6      jmmv         error_in_expect(ctx, "Test case was expected to exit cleanly but it "
    267   1.6      jmmv             "continued execution");
    268   1.6      jmmv     } else if (ctx->expect == EXPECT_FAIL) {
    269   1.6      jmmv         if (ctx->expect_fail_count == ctx->expect_previous_fail_count)
    270   1.6      jmmv             error_in_expect(ctx, "Test case was expecting a failure but none "
    271   1.6      jmmv                 "were raised");
    272   1.6      jmmv         else
    273   1.6      jmmv             INV(ctx->expect_fail_count > ctx->expect_previous_fail_count);
    274   1.6      jmmv     } else if (ctx->expect == EXPECT_PASS) {
    275   1.6      jmmv         /* Nothing to validate. */
    276   1.6      jmmv     } else if (ctx->expect == EXPECT_SIGNAL) {
    277   1.6      jmmv         error_in_expect(ctx, "Test case was expected to receive a termination "
    278   1.6      jmmv             "signal but it continued execution");
    279   1.6      jmmv     } else if (ctx->expect == EXPECT_TIMEOUT) {
    280   1.6      jmmv         error_in_expect(ctx, "Test case was expected to hang but it continued "
    281   1.6      jmmv             "execution");
    282   1.6      jmmv     } else
    283   1.6      jmmv         UNREACHABLE;
    284   1.6      jmmv }
    285   1.6      jmmv 
    286   1.6      jmmv static void
    287   1.6      jmmv expected_failure(struct context *ctx, atf_dynstr_t *reason)
    288   1.6      jmmv {
    289   1.6      jmmv     check_fatal_error(atf_dynstr_prepend_fmt(reason, "%s: ",
    290   1.6      jmmv         atf_dynstr_cstring(&ctx->expect_reason)));
    291   1.6      jmmv     create_resfile(ctx->resfile, "expected_failure", -1, reason);
    292   1.6      jmmv     exit(EXIT_SUCCESS);
    293   1.6      jmmv }
    294   1.6      jmmv 
    295   1.6      jmmv static void
    296   1.6      jmmv fail_requirement(struct context *ctx, atf_dynstr_t *reason)
    297   1.6      jmmv {
    298   1.6      jmmv     if (ctx->expect == EXPECT_FAIL) {
    299   1.6      jmmv         expected_failure(ctx, reason);
    300   1.6      jmmv     } else if (ctx->expect == EXPECT_PASS) {
    301   1.6      jmmv         create_resfile(ctx->resfile, "failed", -1, reason);
    302   1.6      jmmv         exit(EXIT_FAILURE);
    303   1.6      jmmv     } else {
    304   1.6      jmmv         error_in_expect(ctx, "Test case raised a failure but was not "
    305   1.6      jmmv             "expecting one; reason was %s", atf_dynstr_cstring(reason));
    306   1.6      jmmv     }
    307   1.6      jmmv     UNREACHABLE;
    308   1.6      jmmv }
    309   1.6      jmmv 
    310   1.6      jmmv static void
    311   1.6      jmmv fail_check(struct context *ctx, atf_dynstr_t *reason)
    312   1.6      jmmv {
    313   1.6      jmmv     if (ctx->expect == EXPECT_FAIL) {
    314   1.6      jmmv         fprintf(stderr, "*** Expected check failure: %s: %s\n",
    315   1.6      jmmv             atf_dynstr_cstring(&ctx->expect_reason),
    316   1.6      jmmv             atf_dynstr_cstring(reason));
    317   1.6      jmmv         ctx->expect_fail_count++;
    318   1.6      jmmv     } else if (ctx->expect == EXPECT_PASS) {
    319   1.6      jmmv         fprintf(stderr, "*** Check failed: %s\n", atf_dynstr_cstring(reason));
    320   1.6      jmmv         ctx->fail_count++;
    321   1.6      jmmv     } else {
    322   1.6      jmmv         error_in_expect(ctx, "Test case raised a failure but was not "
    323   1.6      jmmv             "expecting one; reason was %s", atf_dynstr_cstring(reason));
    324   1.6      jmmv     }
    325   1.6      jmmv 
    326   1.6      jmmv     atf_dynstr_fini(reason);
    327   1.6      jmmv }
    328   1.6      jmmv 
    329   1.6      jmmv static void
    330   1.6      jmmv pass(struct context *ctx)
    331   1.6      jmmv {
    332   1.6      jmmv     if (ctx->expect == EXPECT_FAIL) {
    333   1.6      jmmv         error_in_expect(ctx, "Test case was expecting a failure but got "
    334   1.6      jmmv             "a pass instead");
    335   1.6      jmmv     } else if (ctx->expect == EXPECT_PASS) {
    336   1.6      jmmv         create_resfile(ctx->resfile, "passed", -1, NULL);
    337   1.6      jmmv         exit(EXIT_SUCCESS);
    338   1.6      jmmv     } else {
    339   1.6      jmmv         error_in_expect(ctx, "Test case asked to explicitly pass but was "
    340   1.6      jmmv             "not expecting such condition");
    341   1.6      jmmv     }
    342   1.6      jmmv     UNREACHABLE;
    343   1.6      jmmv }
    344   1.6      jmmv 
    345   1.6      jmmv static void
    346   1.6      jmmv skip(struct context *ctx, atf_dynstr_t *reason)
    347   1.6      jmmv {
    348   1.6      jmmv     if (ctx->expect == EXPECT_PASS) {
    349   1.6      jmmv         create_resfile(ctx->resfile, "skipped", -1, reason);
    350   1.6      jmmv         exit(EXIT_SUCCESS);
    351   1.6      jmmv     } else {
    352   1.6      jmmv         error_in_expect(ctx, "Can only skip a test case when running in "
    353   1.6      jmmv             "expect pass mode");
    354   1.6      jmmv     }
    355   1.6      jmmv     UNREACHABLE;
    356   1.6      jmmv }
    357   1.6      jmmv 
    358   1.6      jmmv /** Formats a failure/skip reason message.
    359   1.6      jmmv  *
    360   1.6      jmmv  * The formatted reason is stored in out_reason.  out_reason is initialized
    361   1.6      jmmv  * in this function and is supposed to be released by the caller.  In general,
    362   1.6      jmmv  * the reason will eventually be fed to create_resfile, which will release
    363   1.6      jmmv  * it.
    364   1.6      jmmv  *
    365   1.6      jmmv  * Errors in this function are fatal.  Rationale being: reasons are used to
    366   1.6      jmmv  * create results files; if we can't format the reason correctly, the result
    367   1.6      jmmv  * of the test program will be bogus.  So it's better to just exit with a
    368   1.6      jmmv  * fatal error.
    369   1.6      jmmv  */
    370   1.6      jmmv static void
    371   1.6      jmmv format_reason_ap(atf_dynstr_t *out_reason,
    372   1.6      jmmv                  const char *source_file, const size_t source_line,
    373   1.6      jmmv                  const char *reason, va_list ap)
    374   1.6      jmmv {
    375   1.6      jmmv     atf_error_t err;
    376   1.6      jmmv 
    377   1.6      jmmv     if (source_file != NULL) {
    378   1.6      jmmv         err = atf_dynstr_init_fmt(out_reason, "%s:%zd: ", source_file,
    379   1.6      jmmv                                   source_line);
    380   1.6      jmmv     } else {
    381   1.6      jmmv         PRE(source_line == 0);
    382   1.6      jmmv         err = atf_dynstr_init(out_reason);
    383   1.6      jmmv     }
    384   1.6      jmmv 
    385   1.6      jmmv     if (!atf_is_error(err)) {
    386   1.6      jmmv         va_list ap2;
    387   1.6      jmmv         va_copy(ap2, ap);
    388   1.6      jmmv         err = atf_dynstr_append_ap(out_reason, reason, ap2);
    389   1.6      jmmv         va_end(ap2);
    390   1.6      jmmv     }
    391   1.6      jmmv 
    392   1.6      jmmv     check_fatal_error(err);
    393   1.6      jmmv }
    394   1.6      jmmv 
    395   1.6      jmmv static void
    396   1.6      jmmv format_reason_fmt(atf_dynstr_t *out_reason,
    397   1.6      jmmv                   const char *source_file, const size_t source_line,
    398   1.6      jmmv                   const char *reason, ...)
    399   1.6      jmmv {
    400   1.6      jmmv     va_list ap;
    401   1.6      jmmv 
    402   1.6      jmmv     va_start(ap, reason);
    403   1.6      jmmv     format_reason_ap(out_reason, source_file, source_line, reason, ap);
    404   1.6      jmmv     va_end(ap);
    405   1.6      jmmv }
    406   1.6      jmmv 
    407   1.6      jmmv static void
    408   1.6      jmmv errno_test(struct context *ctx, const char *file, const size_t line,
    409   1.6      jmmv            const int exp_errno, const char *expr_str,
    410   1.6      jmmv            const bool expr_result,
    411   1.6      jmmv            void (*fail_func)(struct context *, atf_dynstr_t *))
    412   1.6      jmmv {
    413   1.6      jmmv     const int actual_errno = errno;
    414   1.6      jmmv 
    415   1.6      jmmv     if (expr_result) {
    416   1.6      jmmv         if (exp_errno != actual_errno) {
    417   1.6      jmmv             atf_dynstr_t reason;
    418   1.6      jmmv 
    419   1.6      jmmv             format_reason_fmt(&reason, file, line, "Expected errno %d, got %d, "
    420   1.6      jmmv                 "in %s", exp_errno, actual_errno, expr_str);
    421   1.6      jmmv             fail_func(ctx, &reason);
    422   1.6      jmmv         }
    423   1.6      jmmv     } else {
    424   1.6      jmmv         atf_dynstr_t reason;
    425   1.6      jmmv 
    426   1.6      jmmv         format_reason_fmt(&reason, file, line, "Expected true value in %s",
    427   1.6      jmmv             expr_str);
    428   1.6      jmmv         fail_func(ctx, &reason);
    429   1.6      jmmv     }
    430   1.6      jmmv }
    431   1.6      jmmv 
    432   1.6      jmmv struct prog_found_pair {
    433   1.6      jmmv     const char *prog;
    434   1.6      jmmv     bool found;
    435   1.6      jmmv };
    436   1.6      jmmv 
    437   1.6      jmmv static atf_error_t
    438   1.6      jmmv check_prog_in_dir(const char *dir, void *data)
    439   1.6      jmmv {
    440   1.6      jmmv     struct prog_found_pair *pf = data;
    441   1.6      jmmv     atf_error_t err;
    442   1.6      jmmv 
    443   1.6      jmmv     if (pf->found)
    444   1.6      jmmv         err = atf_no_error();
    445   1.6      jmmv     else {
    446   1.6      jmmv         atf_fs_path_t p;
    447   1.6      jmmv 
    448   1.6      jmmv         err = atf_fs_path_init_fmt(&p, "%s/%s", dir, pf->prog);
    449   1.6      jmmv         if (atf_is_error(err))
    450   1.6      jmmv             goto out_p;
    451   1.6      jmmv 
    452   1.6      jmmv         err = atf_fs_eaccess(&p, atf_fs_access_x);
    453   1.6      jmmv         if (!atf_is_error(err))
    454   1.6      jmmv             pf->found = true;
    455   1.6      jmmv         else {
    456   1.6      jmmv             atf_error_free(err);
    457   1.6      jmmv             INV(!pf->found);
    458   1.6      jmmv             err = atf_no_error();
    459   1.6      jmmv         }
    460   1.6      jmmv 
    461   1.6      jmmv out_p:
    462   1.6      jmmv         atf_fs_path_fini(&p);
    463   1.6      jmmv     }
    464   1.6      jmmv 
    465   1.6      jmmv     return err;
    466   1.6      jmmv }
    467   1.6      jmmv 
    468   1.6      jmmv static atf_error_t
    469  1.12      jmmv check_prog(struct context *ctx, const char *prog)
    470   1.6      jmmv {
    471   1.6      jmmv     atf_error_t err;
    472   1.6      jmmv     atf_fs_path_t p;
    473   1.6      jmmv 
    474   1.6      jmmv     err = atf_fs_path_init_fmt(&p, "%s", prog);
    475   1.6      jmmv     if (atf_is_error(err))
    476   1.6      jmmv         goto out;
    477   1.6      jmmv 
    478   1.6      jmmv     if (atf_fs_path_is_absolute(&p)) {
    479   1.6      jmmv         err = atf_fs_eaccess(&p, atf_fs_access_x);
    480   1.6      jmmv         if (atf_is_error(err)) {
    481   1.6      jmmv             atf_dynstr_t reason;
    482   1.6      jmmv 
    483   1.6      jmmv             atf_error_free(err);
    484   1.6      jmmv             atf_fs_path_fini(&p);
    485   1.6      jmmv             format_reason_fmt(&reason, NULL, 0, "The required program %s could "
    486   1.6      jmmv                 "not be found", prog);
    487   1.6      jmmv             skip(ctx, &reason);
    488   1.6      jmmv         }
    489   1.6      jmmv     } else {
    490   1.6      jmmv         const char *path = atf_env_get("PATH");
    491   1.6      jmmv         struct prog_found_pair pf;
    492   1.6      jmmv         atf_fs_path_t bp;
    493   1.6      jmmv 
    494   1.6      jmmv         err = atf_fs_path_branch_path(&p, &bp);
    495   1.6      jmmv         if (atf_is_error(err))
    496   1.6      jmmv             goto out_p;
    497   1.6      jmmv 
    498   1.6      jmmv         if (strcmp(atf_fs_path_cstring(&bp), ".") != 0) {
    499   1.6      jmmv             atf_fs_path_fini(&bp);
    500   1.6      jmmv             atf_fs_path_fini(&p);
    501   1.6      jmmv 
    502   1.6      jmmv             report_fatal_error("Relative paths are not allowed when searching "
    503   1.6      jmmv                 "for a program (%s)", prog);
    504   1.6      jmmv             UNREACHABLE;
    505   1.6      jmmv         }
    506   1.6      jmmv 
    507   1.6      jmmv         pf.prog = prog;
    508   1.6      jmmv         pf.found = false;
    509   1.6      jmmv         err = atf_text_for_each_word(path, ":", check_prog_in_dir, &pf);
    510   1.6      jmmv         if (atf_is_error(err))
    511   1.6      jmmv             goto out_bp;
    512   1.6      jmmv 
    513   1.6      jmmv         if (!pf.found) {
    514   1.6      jmmv             atf_dynstr_t reason;
    515   1.6      jmmv 
    516   1.6      jmmv             atf_fs_path_fini(&bp);
    517   1.6      jmmv             atf_fs_path_fini(&p);
    518   1.6      jmmv             format_reason_fmt(&reason, NULL, 0, "The required program %s could "
    519   1.6      jmmv                 "not be found in the PATH", prog);
    520   1.6      jmmv             fail_requirement(ctx, &reason);
    521   1.6      jmmv         }
    522   1.6      jmmv 
    523   1.6      jmmv out_bp:
    524   1.6      jmmv         atf_fs_path_fini(&bp);
    525   1.6      jmmv     }
    526   1.6      jmmv 
    527   1.6      jmmv out_p:
    528   1.6      jmmv     atf_fs_path_fini(&p);
    529   1.6      jmmv out:
    530   1.6      jmmv     return err;
    531   1.6      jmmv }
    532   1.1      jmmv 
    533   1.1      jmmv /* ---------------------------------------------------------------------
    534   1.1      jmmv  * The "atf_tc" type.
    535   1.1      jmmv  * --------------------------------------------------------------------- */
    536   1.1      jmmv 
    537   1.7      jmmv struct atf_tc_impl {
    538   1.7      jmmv     const char *m_ident;
    539   1.7      jmmv 
    540   1.7      jmmv     atf_map_t m_vars;
    541   1.7      jmmv     atf_map_t m_config;
    542   1.7      jmmv 
    543   1.7      jmmv     atf_tc_head_t m_head;
    544   1.7      jmmv     atf_tc_body_t m_body;
    545   1.7      jmmv     atf_tc_cleanup_t m_cleanup;
    546   1.7      jmmv };
    547   1.7      jmmv 
    548   1.1      jmmv /*
    549   1.1      jmmv  * Constructors/destructors.
    550   1.1      jmmv  */
    551   1.1      jmmv 
    552   1.1      jmmv atf_error_t
    553   1.1      jmmv atf_tc_init(atf_tc_t *tc, const char *ident, atf_tc_head_t head,
    554   1.1      jmmv             atf_tc_body_t body, atf_tc_cleanup_t cleanup,
    555   1.7      jmmv             const char *const *config)
    556   1.1      jmmv {
    557   1.1      jmmv     atf_error_t err;
    558   1.1      jmmv 
    559   1.7      jmmv     tc->pimpl = malloc(sizeof(struct atf_tc_impl));
    560   1.7      jmmv     if (tc->pimpl == NULL) {
    561   1.7      jmmv         err = atf_no_memory_error();
    562   1.7      jmmv         goto err;
    563   1.7      jmmv     }
    564   1.7      jmmv 
    565   1.7      jmmv     tc->pimpl->m_ident = ident;
    566   1.7      jmmv     tc->pimpl->m_head = head;
    567   1.7      jmmv     tc->pimpl->m_body = body;
    568   1.7      jmmv     tc->pimpl->m_cleanup = cleanup;
    569   1.1      jmmv 
    570   1.7      jmmv     err = atf_map_init_charpp(&tc->pimpl->m_config, config);
    571   1.1      jmmv     if (atf_is_error(err))
    572   1.5      jmmv         goto err;
    573   1.1      jmmv 
    574   1.7      jmmv     err = atf_map_init(&tc->pimpl->m_vars);
    575   1.7      jmmv     if (atf_is_error(err))
    576   1.7      jmmv         goto err_vars;
    577   1.7      jmmv 
    578  1.13     joerg     err = atf_tc_set_md_var(tc, "ident", "%s", ident);
    579   1.1      jmmv     if (atf_is_error(err))
    580   1.1      jmmv         goto err_map;
    581   1.1      jmmv 
    582   1.6      jmmv     if (cleanup != NULL) {
    583   1.6      jmmv         err = atf_tc_set_md_var(tc, "has.cleanup", "true");
    584   1.6      jmmv         if (atf_is_error(err))
    585   1.6      jmmv             goto err_map;
    586   1.6      jmmv     }
    587   1.6      jmmv 
    588   1.1      jmmv     /* XXX Should the head be able to return error codes? */
    589   1.7      jmmv     if (tc->pimpl->m_head != NULL)
    590   1.7      jmmv         tc->pimpl->m_head(tc);
    591   1.1      jmmv 
    592   1.6      jmmv     if (strcmp(atf_tc_get_md_var(tc, "ident"), ident) != 0) {
    593   1.6      jmmv         report_fatal_error("Test case head modified the read-only 'ident' "
    594   1.6      jmmv             "property");
    595   1.6      jmmv         UNREACHABLE;
    596   1.6      jmmv     }
    597   1.1      jmmv 
    598   1.1      jmmv     INV(!atf_is_error(err));
    599   1.1      jmmv     return err;
    600   1.1      jmmv 
    601   1.1      jmmv err_map:
    602   1.7      jmmv     atf_map_fini(&tc->pimpl->m_vars);
    603   1.7      jmmv err_vars:
    604   1.7      jmmv     atf_map_fini(&tc->pimpl->m_config);
    605   1.5      jmmv err:
    606   1.1      jmmv     return err;
    607   1.1      jmmv }
    608   1.1      jmmv 
    609   1.1      jmmv atf_error_t
    610   1.1      jmmv atf_tc_init_pack(atf_tc_t *tc, const atf_tc_pack_t *pack,
    611   1.7      jmmv                  const char *const *config)
    612   1.1      jmmv {
    613   1.1      jmmv     return atf_tc_init(tc, pack->m_ident, pack->m_head, pack->m_body,
    614   1.1      jmmv                        pack->m_cleanup, config);
    615   1.1      jmmv }
    616   1.1      jmmv 
    617   1.1      jmmv void
    618   1.1      jmmv atf_tc_fini(atf_tc_t *tc)
    619   1.1      jmmv {
    620   1.7      jmmv     atf_map_fini(&tc->pimpl->m_vars);
    621   1.7      jmmv     free(tc->pimpl);
    622   1.1      jmmv }
    623   1.1      jmmv 
    624   1.1      jmmv /*
    625   1.1      jmmv  * Getters.
    626   1.1      jmmv  */
    627   1.1      jmmv 
    628   1.1      jmmv const char *
    629   1.1      jmmv atf_tc_get_ident(const atf_tc_t *tc)
    630   1.1      jmmv {
    631   1.7      jmmv     return tc->pimpl->m_ident;
    632   1.1      jmmv }
    633   1.1      jmmv 
    634   1.1      jmmv const char *
    635   1.1      jmmv atf_tc_get_config_var(const atf_tc_t *tc, const char *name)
    636   1.1      jmmv {
    637   1.1      jmmv     const char *val;
    638   1.1      jmmv     atf_map_citer_t iter;
    639   1.1      jmmv 
    640   1.1      jmmv     PRE(atf_tc_has_config_var(tc, name));
    641   1.7      jmmv     iter = atf_map_find_c(&tc->pimpl->m_config, name);
    642   1.1      jmmv     val = atf_map_citer_data(iter);
    643   1.1      jmmv     INV(val != NULL);
    644   1.1      jmmv 
    645   1.1      jmmv     return val;
    646   1.1      jmmv }
    647   1.1      jmmv 
    648   1.1      jmmv const char *
    649   1.1      jmmv atf_tc_get_config_var_wd(const atf_tc_t *tc, const char *name,
    650   1.1      jmmv                          const char *defval)
    651   1.1      jmmv {
    652   1.1      jmmv     const char *val;
    653   1.1      jmmv 
    654   1.1      jmmv     if (!atf_tc_has_config_var(tc, name))
    655   1.1      jmmv         val = defval;
    656   1.1      jmmv     else
    657   1.1      jmmv         val = atf_tc_get_config_var(tc, name);
    658   1.1      jmmv 
    659   1.1      jmmv     return val;
    660   1.1      jmmv }
    661   1.1      jmmv 
    662   1.8      jmmv bool
    663   1.8      jmmv atf_tc_get_config_var_as_bool(const atf_tc_t *tc, const char *name)
    664   1.8      jmmv {
    665   1.8      jmmv     bool val;
    666   1.8      jmmv     const char *strval;
    667   1.8      jmmv     atf_error_t err;
    668   1.8      jmmv 
    669   1.8      jmmv     strval = atf_tc_get_config_var(tc, name);
    670   1.8      jmmv     err = atf_text_to_bool(strval, &val);
    671   1.8      jmmv     if (atf_is_error(err)) {
    672   1.8      jmmv         atf_error_free(err);
    673   1.8      jmmv         atf_tc_fail("Configuration variable %s does not have a valid "
    674   1.8      jmmv                     "boolean value; found %s", name, strval);
    675   1.8      jmmv     }
    676   1.8      jmmv 
    677   1.8      jmmv     return val;
    678   1.8      jmmv }
    679   1.8      jmmv 
    680   1.8      jmmv bool
    681   1.8      jmmv atf_tc_get_config_var_as_bool_wd(const atf_tc_t *tc, const char *name,
    682   1.8      jmmv                                  const bool defval)
    683   1.8      jmmv {
    684   1.8      jmmv     bool val;
    685   1.8      jmmv 
    686   1.8      jmmv     if (!atf_tc_has_config_var(tc, name))
    687   1.8      jmmv         val = defval;
    688   1.8      jmmv     else
    689   1.8      jmmv         val = atf_tc_get_config_var_as_bool(tc, name);
    690   1.8      jmmv 
    691   1.8      jmmv     return val;
    692   1.8      jmmv }
    693   1.8      jmmv 
    694   1.8      jmmv long
    695   1.8      jmmv atf_tc_get_config_var_as_long(const atf_tc_t *tc, const char *name)
    696   1.8      jmmv {
    697   1.8      jmmv     long val;
    698   1.8      jmmv     const char *strval;
    699   1.8      jmmv     atf_error_t err;
    700   1.8      jmmv 
    701   1.8      jmmv     strval = atf_tc_get_config_var(tc, name);
    702   1.8      jmmv     err = atf_text_to_long(strval, &val);
    703   1.8      jmmv     if (atf_is_error(err)) {
    704   1.8      jmmv         atf_error_free(err);
    705   1.8      jmmv         atf_tc_fail("Configuration variable %s does not have a valid "
    706   1.8      jmmv                     "long value; found %s", name, strval);
    707   1.8      jmmv     }
    708   1.8      jmmv 
    709   1.8      jmmv     return val;
    710   1.8      jmmv }
    711   1.8      jmmv 
    712   1.8      jmmv long
    713   1.8      jmmv atf_tc_get_config_var_as_long_wd(const atf_tc_t *tc, const char *name,
    714   1.8      jmmv                                  const long defval)
    715   1.8      jmmv {
    716   1.8      jmmv     long val;
    717   1.8      jmmv 
    718   1.8      jmmv     if (!atf_tc_has_config_var(tc, name))
    719   1.8      jmmv         val = defval;
    720   1.8      jmmv     else
    721   1.8      jmmv         val = atf_tc_get_config_var_as_long(tc, name);
    722   1.8      jmmv 
    723   1.8      jmmv     return val;
    724   1.8      jmmv }
    725   1.8      jmmv 
    726   1.1      jmmv const char *
    727   1.1      jmmv atf_tc_get_md_var(const atf_tc_t *tc, const char *name)
    728   1.1      jmmv {
    729   1.1      jmmv     const char *val;
    730   1.1      jmmv     atf_map_citer_t iter;
    731   1.1      jmmv 
    732   1.1      jmmv     PRE(atf_tc_has_md_var(tc, name));
    733   1.7      jmmv     iter = atf_map_find_c(&tc->pimpl->m_vars, name);
    734   1.1      jmmv     val = atf_map_citer_data(iter);
    735   1.1      jmmv     INV(val != NULL);
    736   1.1      jmmv 
    737   1.1      jmmv     return val;
    738   1.1      jmmv }
    739   1.1      jmmv 
    740   1.7      jmmv char **
    741   1.4      jmmv atf_tc_get_md_vars(const atf_tc_t *tc)
    742   1.4      jmmv {
    743   1.7      jmmv     return atf_map_to_charpp(&tc->pimpl->m_vars);
    744   1.4      jmmv }
    745   1.4      jmmv 
    746   1.1      jmmv bool
    747   1.1      jmmv atf_tc_has_config_var(const atf_tc_t *tc, const char *name)
    748   1.1      jmmv {
    749   1.1      jmmv     atf_map_citer_t end, iter;
    750   1.1      jmmv 
    751   1.7      jmmv     iter = atf_map_find_c(&tc->pimpl->m_config, name);
    752   1.7      jmmv     end = atf_map_end_c(&tc->pimpl->m_config);
    753   1.7      jmmv     return !atf_equal_map_citer_map_citer(iter, end);
    754   1.1      jmmv }
    755   1.1      jmmv 
    756   1.1      jmmv bool
    757   1.1      jmmv atf_tc_has_md_var(const atf_tc_t *tc, const char *name)
    758   1.1      jmmv {
    759   1.1      jmmv     atf_map_citer_t end, iter;
    760   1.1      jmmv 
    761   1.7      jmmv     iter = atf_map_find_c(&tc->pimpl->m_vars, name);
    762   1.7      jmmv     end = atf_map_end_c(&tc->pimpl->m_vars);
    763   1.1      jmmv     return !atf_equal_map_citer_map_citer(iter, end);
    764   1.1      jmmv }
    765   1.1      jmmv 
    766   1.1      jmmv /*
    767   1.1      jmmv  * Modifiers.
    768   1.1      jmmv  */
    769   1.1      jmmv 
    770   1.1      jmmv atf_error_t
    771   1.1      jmmv atf_tc_set_md_var(atf_tc_t *tc, const char *name, const char *fmt, ...)
    772   1.1      jmmv {
    773   1.1      jmmv     atf_error_t err;
    774   1.1      jmmv     char *value;
    775   1.1      jmmv     va_list ap;
    776   1.1      jmmv 
    777   1.1      jmmv     va_start(ap, fmt);
    778   1.1      jmmv     err = atf_text_format_ap(&value, fmt, ap);
    779   1.1      jmmv     va_end(ap);
    780   1.1      jmmv 
    781   1.1      jmmv     if (!atf_is_error(err))
    782   1.7      jmmv         err = atf_map_insert(&tc->pimpl->m_vars, name, value, true);
    783   1.1      jmmv     else
    784   1.1      jmmv         free(value);
    785   1.1      jmmv 
    786   1.1      jmmv     return err;
    787   1.1      jmmv }
    788   1.1      jmmv 
    789   1.1      jmmv /* ---------------------------------------------------------------------
    790   1.6      jmmv  * Free functions, as they should be publicly but they can't.
    791   1.1      jmmv  * --------------------------------------------------------------------- */
    792   1.1      jmmv 
    793   1.6      jmmv static void _atf_tc_fail(struct context *, const char *, va_list)
    794  1.13     joerg     ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(2, 0)
    795   1.6      jmmv     ATF_DEFS_ATTRIBUTE_NORETURN;
    796  1.13     joerg static void _atf_tc_fail_nonfatal(struct context *, const char *, va_list)
    797  1.13     joerg     ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(2, 0);
    798   1.6      jmmv static void _atf_tc_fail_check(struct context *, const char *, const size_t,
    799  1.13     joerg     const char *, va_list)
    800  1.13     joerg     ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(4, 0);
    801   1.6      jmmv static void _atf_tc_fail_requirement(struct context *, const char *,
    802  1.13     joerg     const size_t, const char *, va_list)
    803  1.13     joerg     ATF_DEFS_ATTRIBUTE_NORETURN
    804  1.13     joerg     ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(4, 0);
    805   1.6      jmmv static void _atf_tc_pass(struct context *) ATF_DEFS_ATTRIBUTE_NORETURN;
    806   1.6      jmmv static void _atf_tc_require_prog(struct context *, const char *);
    807   1.6      jmmv static void _atf_tc_skip(struct context *, const char *, va_list)
    808  1.13     joerg     ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(2, 0)
    809   1.6      jmmv     ATF_DEFS_ATTRIBUTE_NORETURN;
    810   1.6      jmmv static void _atf_tc_check_errno(struct context *, const char *, const size_t,
    811   1.6      jmmv     const int, const char *, const bool);
    812   1.6      jmmv static void _atf_tc_require_errno(struct context *, const char *, const size_t,
    813   1.6      jmmv     const int, const char *, const bool);
    814   1.6      jmmv static void _atf_tc_expect_pass(struct context *);
    815  1.13     joerg static void _atf_tc_expect_fail(struct context *, const char *, va_list)
    816  1.13     joerg     ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(2, 0);
    817   1.6      jmmv static void _atf_tc_expect_exit(struct context *, const int, const char *,
    818  1.13     joerg     va_list) ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(3, 0);
    819   1.6      jmmv static void _atf_tc_expect_signal(struct context *, const int, const char *,
    820  1.13     joerg     va_list) ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(3, 0);
    821   1.6      jmmv static void _atf_tc_expect_death(struct context *, const char *,
    822  1.13     joerg     va_list) ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(2, 0);
    823   1.6      jmmv 
    824   1.6      jmmv static void
    825   1.6      jmmv _atf_tc_fail(struct context *ctx, const char *fmt, va_list ap)
    826   1.6      jmmv {
    827   1.6      jmmv     va_list ap2;
    828   1.6      jmmv     atf_dynstr_t reason;
    829   1.6      jmmv 
    830   1.6      jmmv     va_copy(ap2, ap);
    831   1.6      jmmv     format_reason_ap(&reason, NULL, 0, fmt, ap2);
    832   1.6      jmmv     va_end(ap2);
    833   1.6      jmmv 
    834   1.6      jmmv     fail_requirement(ctx, &reason);
    835   1.6      jmmv     UNREACHABLE;
    836   1.6      jmmv }
    837   1.6      jmmv 
    838   1.6      jmmv static void
    839   1.6      jmmv _atf_tc_fail_nonfatal(struct context *ctx, const char *fmt, va_list ap)
    840   1.6      jmmv {
    841   1.6      jmmv     va_list ap2;
    842   1.6      jmmv     atf_dynstr_t reason;
    843   1.6      jmmv 
    844   1.6      jmmv     va_copy(ap2, ap);
    845   1.6      jmmv     format_reason_ap(&reason, NULL, 0, fmt, ap2);
    846   1.6      jmmv     va_end(ap2);
    847   1.6      jmmv 
    848   1.6      jmmv     fail_check(ctx, &reason);
    849   1.6      jmmv }
    850   1.1      jmmv 
    851   1.6      jmmv static void
    852   1.6      jmmv _atf_tc_fail_check(struct context *ctx, const char *file, const size_t line,
    853   1.6      jmmv                    const char *fmt, va_list ap)
    854   1.1      jmmv {
    855   1.6      jmmv     va_list ap2;
    856   1.6      jmmv     atf_dynstr_t reason;
    857   1.1      jmmv 
    858   1.6      jmmv     va_copy(ap2, ap);
    859   1.6      jmmv     format_reason_ap(&reason, file, line, fmt, ap2);
    860   1.6      jmmv     va_end(ap2);
    861   1.6      jmmv 
    862   1.6      jmmv     fail_check(ctx, &reason);
    863   1.6      jmmv }
    864   1.1      jmmv 
    865   1.6      jmmv static void
    866   1.6      jmmv _atf_tc_fail_requirement(struct context *ctx, const char *file,
    867   1.6      jmmv                          const size_t line, const char *fmt, va_list ap)
    868   1.6      jmmv {
    869   1.6      jmmv     va_list ap2;
    870   1.6      jmmv     atf_dynstr_t reason;
    871   1.1      jmmv 
    872   1.6      jmmv     va_copy(ap2, ap);
    873   1.6      jmmv     format_reason_ap(&reason, file, line, fmt, ap2);
    874   1.6      jmmv     va_end(ap2);
    875   1.1      jmmv 
    876   1.6      jmmv     fail_requirement(ctx, &reason);
    877   1.6      jmmv     UNREACHABLE;
    878   1.1      jmmv }
    879   1.1      jmmv 
    880   1.6      jmmv static void
    881   1.6      jmmv _atf_tc_pass(struct context *ctx)
    882   1.1      jmmv {
    883   1.6      jmmv     pass(ctx);
    884   1.6      jmmv     UNREACHABLE;
    885   1.1      jmmv }
    886   1.1      jmmv 
    887   1.6      jmmv static void
    888   1.6      jmmv _atf_tc_require_prog(struct context *ctx, const char *prog)
    889   1.6      jmmv {
    890  1.12      jmmv     check_fatal_error(check_prog(ctx, prog));
    891   1.6      jmmv }
    892   1.1      jmmv 
    893   1.6      jmmv static void
    894   1.6      jmmv _atf_tc_skip(struct context *ctx, const char *fmt, va_list ap)
    895   1.1      jmmv {
    896   1.6      jmmv     atf_dynstr_t reason;
    897   1.6      jmmv     va_list ap2;
    898   1.6      jmmv 
    899   1.6      jmmv     va_copy(ap2, ap);
    900   1.6      jmmv     format_reason_ap(&reason, NULL, 0, fmt, ap2);
    901   1.6      jmmv     va_end(ap2);
    902   1.1      jmmv 
    903   1.6      jmmv     skip(ctx, &reason);
    904   1.6      jmmv }
    905   1.1      jmmv 
    906   1.6      jmmv static void
    907   1.6      jmmv _atf_tc_check_errno(struct context *ctx, const char *file, const size_t line,
    908   1.6      jmmv                     const int exp_errno, const char *expr_str,
    909   1.6      jmmv                     const bool expr_result)
    910   1.6      jmmv {
    911   1.6      jmmv     errno_test(ctx, file, line, exp_errno, expr_str, expr_result, fail_check);
    912   1.6      jmmv }
    913   1.1      jmmv 
    914   1.6      jmmv static void
    915   1.6      jmmv _atf_tc_require_errno(struct context *ctx, const char *file, const size_t line,
    916   1.6      jmmv                       const int exp_errno, const char *expr_str,
    917   1.6      jmmv                       const bool expr_result)
    918   1.6      jmmv {
    919   1.6      jmmv     errno_test(ctx, file, line, exp_errno, expr_str, expr_result,
    920   1.6      jmmv         fail_requirement);
    921   1.6      jmmv }
    922   1.1      jmmv 
    923   1.6      jmmv static void
    924   1.6      jmmv _atf_tc_expect_pass(struct context *ctx)
    925   1.6      jmmv {
    926   1.6      jmmv     validate_expect(ctx);
    927   1.1      jmmv 
    928   1.6      jmmv     ctx->expect = EXPECT_PASS;
    929   1.6      jmmv }
    930   1.1      jmmv 
    931   1.6      jmmv static void
    932   1.6      jmmv _atf_tc_expect_fail(struct context *ctx, const char *reason, va_list ap)
    933   1.6      jmmv {
    934   1.6      jmmv     va_list ap2;
    935   1.1      jmmv 
    936   1.6      jmmv     validate_expect(ctx);
    937   1.1      jmmv 
    938   1.6      jmmv     ctx->expect = EXPECT_FAIL;
    939   1.6      jmmv     atf_dynstr_fini(&ctx->expect_reason);
    940   1.6      jmmv     va_copy(ap2, ap);
    941   1.6      jmmv     check_fatal_error(atf_dynstr_init_ap(&ctx->expect_reason, reason, ap2));
    942   1.6      jmmv     va_end(ap2);
    943   1.6      jmmv     ctx->expect_previous_fail_count = ctx->expect_fail_count;
    944   1.1      jmmv }
    945   1.1      jmmv 
    946   1.6      jmmv static void
    947   1.6      jmmv _atf_tc_expect_exit(struct context *ctx, const int exitcode, const char *reason,
    948   1.6      jmmv                     va_list ap)
    949   1.1      jmmv {
    950   1.6      jmmv     va_list ap2;
    951   1.6      jmmv     atf_dynstr_t formatted;
    952   1.6      jmmv 
    953   1.6      jmmv     validate_expect(ctx);
    954   1.6      jmmv 
    955   1.6      jmmv     ctx->expect = EXPECT_EXIT;
    956   1.6      jmmv     va_copy(ap2, ap);
    957   1.6      jmmv     check_fatal_error(atf_dynstr_init_ap(&formatted, reason, ap2));
    958   1.6      jmmv     va_end(ap2);
    959   1.1      jmmv 
    960   1.6      jmmv     create_resfile(ctx->resfile, "expected_exit", exitcode, &formatted);
    961   1.6      jmmv }
    962   1.1      jmmv 
    963   1.6      jmmv static void
    964   1.6      jmmv _atf_tc_expect_signal(struct context *ctx, const int signo, const char *reason,
    965   1.6      jmmv                       va_list ap)
    966   1.6      jmmv {
    967   1.6      jmmv     va_list ap2;
    968   1.6      jmmv     atf_dynstr_t formatted;
    969   1.1      jmmv 
    970   1.6      jmmv     validate_expect(ctx);
    971   1.1      jmmv 
    972   1.6      jmmv     ctx->expect = EXPECT_SIGNAL;
    973   1.6      jmmv     va_copy(ap2, ap);
    974   1.6      jmmv     check_fatal_error(atf_dynstr_init_ap(&formatted, reason, ap2));
    975   1.6      jmmv     va_end(ap2);
    976   1.1      jmmv 
    977   1.6      jmmv     create_resfile(ctx->resfile, "expected_signal", signo, &formatted);
    978   1.1      jmmv }
    979   1.1      jmmv 
    980   1.6      jmmv static void
    981   1.6      jmmv _atf_tc_expect_death(struct context *ctx, const char *reason, va_list ap)
    982   1.3      jmmv {
    983   1.6      jmmv     va_list ap2;
    984   1.6      jmmv     atf_dynstr_t formatted;
    985   1.6      jmmv 
    986   1.6      jmmv     validate_expect(ctx);
    987   1.6      jmmv 
    988   1.6      jmmv     ctx->expect = EXPECT_DEATH;
    989   1.6      jmmv     va_copy(ap2, ap);
    990   1.6      jmmv     check_fatal_error(atf_dynstr_init_ap(&formatted, reason, ap2));
    991   1.6      jmmv     va_end(ap2);
    992   1.3      jmmv 
    993   1.6      jmmv     create_resfile(ctx->resfile, "expected_death", -1, &formatted);
    994   1.6      jmmv }
    995   1.3      jmmv 
    996  1.13     joerg ATF_DEFS_ATTRIBUTE_FORMAT_PRINTF(2, 0)
    997   1.6      jmmv static void
    998   1.6      jmmv _atf_tc_expect_timeout(struct context *ctx, const char *reason, va_list ap)
    999   1.6      jmmv {
   1000   1.6      jmmv     va_list ap2;
   1001   1.6      jmmv     atf_dynstr_t formatted;
   1002   1.3      jmmv 
   1003   1.6      jmmv     validate_expect(ctx);
   1004   1.3      jmmv 
   1005   1.6      jmmv     ctx->expect = EXPECT_TIMEOUT;
   1006   1.6      jmmv     va_copy(ap2, ap);
   1007   1.6      jmmv     check_fatal_error(atf_dynstr_init_ap(&formatted, reason, ap2));
   1008   1.6      jmmv     va_end(ap2);
   1009   1.3      jmmv 
   1010   1.6      jmmv     create_resfile(ctx->resfile, "expected_timeout", -1, &formatted);
   1011   1.3      jmmv }
   1012   1.3      jmmv 
   1013   1.6      jmmv /* ---------------------------------------------------------------------
   1014   1.6      jmmv  * Free functions.
   1015   1.6      jmmv  * --------------------------------------------------------------------- */
   1016   1.6      jmmv 
   1017   1.6      jmmv static struct context Current;
   1018   1.6      jmmv 
   1019   1.6      jmmv atf_error_t
   1020   1.7      jmmv atf_tc_run(const atf_tc_t *tc, const char *resfile)
   1021   1.3      jmmv {
   1022   1.6      jmmv     context_init(&Current, tc, resfile);
   1023   1.6      jmmv 
   1024   1.7      jmmv     tc->pimpl->m_body(tc);
   1025   1.6      jmmv 
   1026   1.6      jmmv     validate_expect(&Current);
   1027   1.6      jmmv 
   1028   1.6      jmmv     if (Current.fail_count > 0) {
   1029   1.6      jmmv         atf_dynstr_t reason;
   1030   1.3      jmmv 
   1031  1.13     joerg         format_reason_fmt(&reason, NULL, 0, "%zu checks failed; see output for "
   1032   1.6      jmmv             "more details", Current.fail_count);
   1033   1.6      jmmv         fail_requirement(&Current, &reason);
   1034   1.6      jmmv     } else if (Current.expect_fail_count > 0) {
   1035   1.6      jmmv         atf_dynstr_t reason;
   1036   1.6      jmmv 
   1037  1.13     joerg         format_reason_fmt(&reason, NULL, 0, "%zu checks failed as expected; "
   1038   1.6      jmmv             "see output for more details", Current.expect_fail_count);
   1039   1.6      jmmv         expected_failure(&Current, &reason);
   1040   1.6      jmmv     } else {
   1041   1.6      jmmv         pass(&Current);
   1042   1.6      jmmv     }
   1043   1.6      jmmv     UNREACHABLE;
   1044   1.6      jmmv     return atf_no_error();
   1045   1.6      jmmv }
   1046   1.6      jmmv 
   1047   1.6      jmmv atf_error_t
   1048   1.6      jmmv atf_tc_cleanup(const atf_tc_t *tc)
   1049   1.6      jmmv {
   1050   1.7      jmmv     if (tc->pimpl->m_cleanup != NULL)
   1051   1.7      jmmv         tc->pimpl->m_cleanup(tc);
   1052   1.6      jmmv     return atf_no_error(); /* XXX */
   1053   1.1      jmmv }
   1054   1.1      jmmv 
   1055   1.6      jmmv /* ---------------------------------------------------------------------
   1056   1.6      jmmv  * Free functions that depend on Current.
   1057   1.6      jmmv  * --------------------------------------------------------------------- */
   1058   1.6      jmmv 
   1059   1.6      jmmv /*
   1060   1.6      jmmv  * All the functions below provide delegates to other internal functions
   1061   1.6      jmmv  * (prefixed by _) that take the current test case as an argument to
   1062   1.6      jmmv  * prevent them from accessing global state.  This is to keep the side-
   1063   1.6      jmmv  * effects of the internal functions clearer and easier to understand.
   1064   1.6      jmmv  *
   1065   1.6      jmmv  * The public API should never have hid the fact that it needs access to
   1066   1.6      jmmv  * the current test case (other than maybe in the macros), but changing it
   1067   1.6      jmmv  * is hard.  TODO: Revisit in the future.
   1068   1.6      jmmv  */
   1069   1.6      jmmv 
   1070   1.1      jmmv void
   1071   1.1      jmmv atf_tc_fail(const char *fmt, ...)
   1072   1.1      jmmv {
   1073   1.1      jmmv     va_list ap;
   1074   1.1      jmmv 
   1075   1.6      jmmv     PRE(Current.tc != NULL);
   1076   1.1      jmmv 
   1077   1.1      jmmv     va_start(ap, fmt);
   1078   1.6      jmmv     _atf_tc_fail(&Current, fmt, ap);
   1079   1.1      jmmv     va_end(ap);
   1080   1.6      jmmv }
   1081   1.1      jmmv 
   1082   1.6      jmmv void
   1083   1.6      jmmv atf_tc_fail_nonfatal(const char *fmt, ...)
   1084   1.6      jmmv {
   1085   1.6      jmmv     va_list ap;
   1086   1.1      jmmv 
   1087   1.6      jmmv     PRE(Current.tc != NULL);
   1088   1.1      jmmv 
   1089   1.6      jmmv     va_start(ap, fmt);
   1090   1.6      jmmv     _atf_tc_fail_nonfatal(&Current, fmt, ap);
   1091   1.6      jmmv     va_end(ap);
   1092   1.1      jmmv }
   1093   1.1      jmmv 
   1094   1.1      jmmv void
   1095   1.6      jmmv atf_tc_fail_check(const char *file, const size_t line, const char *fmt, ...)
   1096   1.1      jmmv {
   1097   1.1      jmmv     va_list ap;
   1098   1.1      jmmv 
   1099   1.6      jmmv     PRE(Current.tc != NULL);
   1100   1.6      jmmv 
   1101   1.1      jmmv     va_start(ap, fmt);
   1102   1.6      jmmv     _atf_tc_fail_check(&Current, file, line, fmt, ap);
   1103   1.1      jmmv     va_end(ap);
   1104   1.1      jmmv }
   1105   1.1      jmmv 
   1106   1.1      jmmv void
   1107   1.6      jmmv atf_tc_fail_requirement(const char *file, const size_t line,
   1108   1.6      jmmv                         const char *fmt, ...)
   1109   1.1      jmmv {
   1110   1.1      jmmv     va_list ap;
   1111   1.1      jmmv 
   1112   1.6      jmmv     PRE(Current.tc != NULL);
   1113   1.6      jmmv 
   1114   1.1      jmmv     va_start(ap, fmt);
   1115   1.6      jmmv     _atf_tc_fail_requirement(&Current, file, line, fmt, ap);
   1116   1.1      jmmv     va_end(ap);
   1117   1.1      jmmv }
   1118   1.1      jmmv 
   1119   1.1      jmmv void
   1120   1.6      jmmv atf_tc_pass(void)
   1121   1.6      jmmv {
   1122   1.6      jmmv     PRE(Current.tc != NULL);
   1123   1.6      jmmv 
   1124   1.6      jmmv     _atf_tc_pass(&Current);
   1125   1.6      jmmv }
   1126   1.6      jmmv 
   1127   1.6      jmmv void
   1128   1.6      jmmv atf_tc_require_prog(const char *prog)
   1129   1.6      jmmv {
   1130   1.6      jmmv     PRE(Current.tc != NULL);
   1131   1.6      jmmv 
   1132   1.6      jmmv     _atf_tc_require_prog(&Current, prog);
   1133   1.6      jmmv }
   1134   1.6      jmmv 
   1135   1.6      jmmv void
   1136   1.6      jmmv atf_tc_skip(const char *fmt, ...)
   1137   1.1      jmmv {
   1138   1.1      jmmv     va_list ap;
   1139   1.1      jmmv 
   1140   1.6      jmmv     PRE(Current.tc != NULL);
   1141   1.6      jmmv 
   1142   1.1      jmmv     va_start(ap, fmt);
   1143   1.6      jmmv     _atf_tc_skip(&Current, fmt, ap);
   1144   1.1      jmmv     va_end(ap);
   1145   1.6      jmmv }
   1146   1.6      jmmv 
   1147   1.6      jmmv void
   1148   1.6      jmmv atf_tc_check_errno(const char *file, const size_t line, const int exp_errno,
   1149   1.6      jmmv                    const char *expr_str, const bool expr_result)
   1150   1.6      jmmv {
   1151   1.6      jmmv     PRE(Current.tc != NULL);
   1152   1.1      jmmv 
   1153   1.6      jmmv     _atf_tc_check_errno(&Current, file, line, exp_errno, expr_str,
   1154   1.6      jmmv                         expr_result);
   1155   1.1      jmmv }
   1156   1.1      jmmv 
   1157   1.1      jmmv void
   1158   1.6      jmmv atf_tc_require_errno(const char *file, const size_t line, const int exp_errno,
   1159   1.6      jmmv                      const char *expr_str, const bool expr_result)
   1160   1.1      jmmv {
   1161   1.6      jmmv     PRE(Current.tc != NULL);
   1162   1.1      jmmv 
   1163   1.6      jmmv     _atf_tc_require_errno(&Current, file, line, exp_errno, expr_str,
   1164   1.6      jmmv                           expr_result);
   1165   1.6      jmmv }
   1166   1.1      jmmv 
   1167   1.6      jmmv void
   1168   1.6      jmmv atf_tc_expect_pass(void)
   1169   1.6      jmmv {
   1170   1.6      jmmv     PRE(Current.tc != NULL);
   1171   1.1      jmmv 
   1172   1.6      jmmv     _atf_tc_expect_pass(&Current);
   1173   1.1      jmmv }
   1174   1.1      jmmv 
   1175   1.1      jmmv void
   1176   1.6      jmmv atf_tc_expect_fail(const char *reason, ...)
   1177   1.1      jmmv {
   1178   1.6      jmmv     va_list ap;
   1179   1.1      jmmv 
   1180   1.6      jmmv     PRE(Current.tc != NULL);
   1181   1.1      jmmv 
   1182   1.6      jmmv     va_start(ap, reason);
   1183   1.6      jmmv     _atf_tc_expect_fail(&Current, reason, ap);
   1184   1.6      jmmv     va_end(ap);
   1185   1.6      jmmv }
   1186   1.1      jmmv 
   1187   1.6      jmmv void
   1188   1.6      jmmv atf_tc_expect_exit(const int exitcode, const char *reason, ...)
   1189   1.6      jmmv {
   1190   1.6      jmmv     va_list ap;
   1191   1.1      jmmv 
   1192   1.6      jmmv     PRE(Current.tc != NULL);
   1193   1.1      jmmv 
   1194   1.6      jmmv     va_start(ap, reason);
   1195   1.6      jmmv     _atf_tc_expect_exit(&Current, exitcode, reason, ap);
   1196   1.6      jmmv     va_end(ap);
   1197   1.1      jmmv }
   1198   1.1      jmmv 
   1199   1.1      jmmv void
   1200   1.6      jmmv atf_tc_expect_signal(const int signo, const char *reason, ...)
   1201   1.1      jmmv {
   1202   1.6      jmmv     va_list ap;
   1203   1.6      jmmv 
   1204   1.6      jmmv     PRE(Current.tc != NULL);
   1205   1.1      jmmv 
   1206   1.6      jmmv     va_start(ap, reason);
   1207   1.6      jmmv     _atf_tc_expect_signal(&Current, signo, reason, ap);
   1208   1.6      jmmv     va_end(ap);
   1209   1.1      jmmv }
   1210   1.1      jmmv 
   1211   1.1      jmmv void
   1212   1.6      jmmv atf_tc_expect_death(const char *reason, ...)
   1213   1.1      jmmv {
   1214   1.1      jmmv     va_list ap;
   1215   1.1      jmmv 
   1216   1.6      jmmv     PRE(Current.tc != NULL);
   1217   1.1      jmmv 
   1218   1.6      jmmv     va_start(ap, reason);
   1219   1.6      jmmv     _atf_tc_expect_death(&Current, reason, ap);
   1220   1.1      jmmv     va_end(ap);
   1221   1.6      jmmv }
   1222   1.1      jmmv 
   1223   1.6      jmmv void
   1224   1.6      jmmv atf_tc_expect_timeout(const char *reason, ...)
   1225   1.6      jmmv {
   1226   1.6      jmmv     va_list ap;
   1227   1.1      jmmv 
   1228   1.6      jmmv     PRE(Current.tc != NULL);
   1229   1.1      jmmv 
   1230   1.6      jmmv     va_start(ap, reason);
   1231   1.6      jmmv     _atf_tc_expect_timeout(&Current, reason, ap);
   1232   1.6      jmmv     va_end(ap);
   1233   1.1      jmmv }
   1234