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