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