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