1 /* 2 * Automated Testing Framework (atf) 3 * 4 * Copyright (c) 2008, 2009, 2010 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/resource.h> 32 #include <sys/time.h> 33 #include <sys/wait.h> 34 35 #include <errno.h> 36 #include <fcntl.h> 37 #include <signal.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <unistd.h> 42 43 #include <atf-c.h> 44 45 #include "atf-c/defs.h" 46 47 #include "process.h" 48 #include "sanity.h" 49 #include "test_helpers.h" 50 51 atf_error_t atf_process_status_init(atf_process_status_t *, int); 52 53 /* --------------------------------------------------------------------- 54 * Auxiliary functions for testing of 'atf_process_fork'. 55 * --------------------------------------------------------------------- */ 56 57 /* 58 * Testing of atf_process_fork is quite messy. We want to be able to test 59 * all the possible combinations of stdout and stderr behavior to ensure 60 * that the streams are manipulated correctly. 61 * 62 * To do this, the do_fork function is a wrapper for atf_process_fork that 63 * issues stream-specific hooks before fork, while the child is running and 64 * after the child terminates. We then provide test cases that just call 65 * do_fork with different hooks. 66 * 67 * The hooks are described by base_stream, and we then have one *_stream 68 * type for ever possible stream behavior. 69 */ 70 71 enum out_type { stdout_type, stderr_type }; 72 73 struct base_stream { 74 void (*init)(void *); 75 void (*process)(void *, atf_process_child_t *); 76 void (*fini)(void *); 77 78 /* m_sb is initialized by subclasses that need it, but all consumers 79 * must use m_sb_ptr, which may or may not point to m_sb. This allows 80 * us to test the interface with a NULL value, which triggers a 81 * default behavior. */ 82 atf_process_stream_t m_sb; 83 atf_process_stream_t *m_sb_ptr; 84 enum out_type m_type; 85 }; 86 #define BASE_STREAM(ihook, phook, fhook, type) \ 87 { .init = ihook, \ 88 .process = phook, \ 89 .fini = fhook, \ 90 .m_type = type } 91 92 static 93 void 94 check_file(const enum out_type type) 95 { 96 switch (type) { 97 case stdout_type: 98 ATF_CHECK(grep_file("stdout", "stdout: msg")); 99 ATF_CHECK(!grep_file("stdout", "stderr: msg")); 100 break; 101 case stderr_type: 102 ATF_CHECK(grep_file("stderr", "stderr: msg")); 103 ATF_CHECK(!grep_file("stderr", "stdout: msg")); 104 break; 105 default: 106 UNREACHABLE; 107 } 108 } 109 110 struct capture_stream { 111 struct base_stream m_base; 112 113 atf_dynstr_t m_msg; 114 }; 115 #define CAPTURE_STREAM(type) \ 116 { .m_base = BASE_STREAM(capture_stream_init, \ 117 capture_stream_process, \ 118 capture_stream_fini, \ 119 type) } 120 121 static 122 void 123 capture_stream_init(void *v) 124 { 125 struct capture_stream *s = v; 126 127 s->m_base.m_sb_ptr = &s->m_base.m_sb; 128 RE(atf_process_stream_init_capture(&s->m_base.m_sb)); 129 RE(atf_dynstr_init(&s->m_msg)); 130 } 131 132 static 133 void 134 capture_stream_process(void *v, atf_process_child_t *c) 135 { 136 struct capture_stream *s = v; 137 138 bool eof; 139 switch (s->m_base.m_type) { 140 case stdout_type: 141 eof = read_line(atf_process_child_stdout(c), &s->m_msg); 142 break; 143 case stderr_type: 144 eof = read_line(atf_process_child_stderr(c), &s->m_msg); 145 break; 146 default: 147 UNREACHABLE; 148 } 149 } 150 151 static 152 void 153 capture_stream_fini(void *v) 154 { 155 struct capture_stream *s = v; 156 157 switch (s->m_base.m_type) { 158 case stdout_type: 159 ATF_CHECK(grep_string(&s->m_msg, "stdout: msg")); 160 ATF_CHECK(!grep_string(&s->m_msg, "stderr: msg")); 161 break; 162 case stderr_type: 163 ATF_CHECK(!grep_string(&s->m_msg, "stdout: msg")); 164 ATF_CHECK(grep_string(&s->m_msg, "stderr: msg")); 165 break; 166 default: 167 UNREACHABLE; 168 } 169 170 atf_dynstr_fini(&s->m_msg); 171 atf_process_stream_fini(&s->m_base.m_sb); 172 } 173 174 struct connect_stream { 175 struct base_stream m_base; 176 177 int m_fd; 178 }; 179 #define CONNECT_STREAM(type) \ 180 { .m_base = BASE_STREAM(connect_stream_init, \ 181 NULL, \ 182 connect_stream_fini, \ 183 type) } 184 185 static 186 void 187 connect_stream_init(void *v) 188 { 189 struct connect_stream *s = v; 190 int src_fd; 191 192 switch (s->m_base.m_type) { 193 case stdout_type: 194 src_fd = STDOUT_FILENO; 195 s->m_fd = open("stdout", O_WRONLY | O_CREAT | O_TRUNC, 0644); 196 break; 197 case stderr_type: 198 src_fd = STDERR_FILENO; 199 s->m_fd = open("stderr", O_WRONLY | O_CREAT | O_TRUNC, 0644); 200 break; 201 default: 202 UNREACHABLE; 203 src_fd = -1; 204 } 205 ATF_REQUIRE(s->m_fd != -1); 206 207 s->m_base.m_sb_ptr = &s->m_base.m_sb; 208 RE(atf_process_stream_init_connect(&s->m_base.m_sb, src_fd, s->m_fd)); 209 } 210 211 static 212 void 213 connect_stream_fini(void *v) 214 { 215 struct connect_stream *s = v; 216 217 ATF_REQUIRE(close(s->m_fd) != -1); 218 219 atf_process_stream_fini(&s->m_base.m_sb); 220 221 check_file(s->m_base.m_type); 222 } 223 224 struct inherit_stream { 225 struct base_stream m_base; 226 int m_fd; 227 228 int m_old_fd; 229 }; 230 #define INHERIT_STREAM(type) \ 231 { .m_base = BASE_STREAM(inherit_stream_init, \ 232 NULL, \ 233 inherit_stream_fini, \ 234 type) } 235 236 static 237 void 238 inherit_stream_init(void *v) 239 { 240 struct inherit_stream *s = v; 241 const char *name; 242 243 s->m_base.m_sb_ptr = &s->m_base.m_sb; 244 RE(atf_process_stream_init_inherit(&s->m_base.m_sb)); 245 246 switch (s->m_base.m_type) { 247 case stdout_type: 248 s->m_fd = STDOUT_FILENO; 249 name = "stdout"; 250 break; 251 case stderr_type: 252 s->m_fd = STDERR_FILENO; 253 name = "stderr"; 254 break; 255 default: 256 UNREACHABLE; 257 name = NULL; 258 } 259 260 s->m_old_fd = dup(s->m_fd); 261 ATF_REQUIRE(s->m_old_fd != -1); 262 ATF_REQUIRE(close(s->m_fd) != -1); 263 ATF_REQUIRE_EQ(open(name, O_WRONLY | O_CREAT | O_TRUNC, 0644), 264 s->m_fd); 265 } 266 267 static 268 void 269 inherit_stream_fini(void *v) 270 { 271 struct inherit_stream *s = v; 272 273 ATF_REQUIRE(dup2(s->m_old_fd, s->m_fd) != -1); 274 ATF_REQUIRE(close(s->m_old_fd) != -1); 275 276 atf_process_stream_fini(&s->m_base.m_sb); 277 278 check_file(s->m_base.m_type); 279 } 280 281 #define default_stream inherit_stream 282 #define DEFAULT_STREAM(type) \ 283 { .m_base = BASE_STREAM(default_stream_init, \ 284 NULL, \ 285 default_stream_fini, \ 286 type) } 287 288 static 289 void 290 default_stream_init(void *v) 291 { 292 struct inherit_stream *s = v; 293 294 inherit_stream_init(v); 295 s->m_base.m_sb_ptr = NULL; 296 } 297 298 static 299 void 300 default_stream_fini(void *v) 301 { 302 inherit_stream_fini(v); 303 } 304 305 struct redirect_fd_stream { 306 struct base_stream m_base; 307 308 int m_fd; 309 }; 310 #define REDIRECT_FD_STREAM(type) \ 311 { .m_base = BASE_STREAM(redirect_fd_stream_init, \ 312 NULL, \ 313 redirect_fd_stream_fini, \ 314 type) } 315 316 static 317 void 318 redirect_fd_stream_init(void *v) 319 { 320 struct redirect_fd_stream *s = v; 321 322 switch (s->m_base.m_type) { 323 case stdout_type: 324 s->m_fd = open("stdout", O_WRONLY | O_CREAT | O_TRUNC, 0644); 325 break; 326 case stderr_type: 327 s->m_fd = open("stderr", O_WRONLY | O_CREAT | O_TRUNC, 0644); 328 break; 329 default: 330 UNREACHABLE; 331 } 332 ATF_REQUIRE(s->m_fd != -1); 333 334 s->m_base.m_sb_ptr = &s->m_base.m_sb; 335 RE(atf_process_stream_init_redirect_fd(&s->m_base.m_sb, s->m_fd)); 336 } 337 338 static 339 void 340 redirect_fd_stream_fini(void *v) 341 { 342 struct redirect_fd_stream *s = v; 343 344 ATF_REQUIRE(close(s->m_fd) != -1); 345 346 atf_process_stream_fini(&s->m_base.m_sb); 347 348 check_file(s->m_base.m_type); 349 } 350 351 struct redirect_path_stream { 352 struct base_stream m_base; 353 354 atf_fs_path_t m_path; 355 }; 356 #define REDIRECT_PATH_STREAM(type) \ 357 { .m_base = BASE_STREAM(redirect_path_stream_init, \ 358 NULL, \ 359 redirect_path_stream_fini, \ 360 type) } 361 362 static 363 void 364 redirect_path_stream_init(void *v) 365 { 366 struct redirect_path_stream *s = v; 367 368 switch (s->m_base.m_type) { 369 case stdout_type: 370 RE(atf_fs_path_init_fmt(&s->m_path, "stdout")); 371 break; 372 case stderr_type: 373 RE(atf_fs_path_init_fmt(&s->m_path, "stderr")); 374 break; 375 default: 376 UNREACHABLE; 377 } 378 379 s->m_base.m_sb_ptr = &s->m_base.m_sb; 380 RE(atf_process_stream_init_redirect_path(&s->m_base.m_sb, &s->m_path)); 381 } 382 383 static 384 void 385 redirect_path_stream_fini(void *v) 386 { 387 struct redirect_path_stream *s = v; 388 389 atf_process_stream_fini(&s->m_base.m_sb); 390 391 atf_fs_path_fini(&s->m_path); 392 393 check_file(s->m_base.m_type); 394 } 395 396 static void child_print(void *) ATF_DEFS_ATTRIBUTE_NORETURN; 397 398 struct child_print_data { 399 const char *m_msg; 400 }; 401 402 static 403 void 404 child_print(void *v) 405 { 406 struct child_print_data *cpd = v; 407 408 fprintf(stdout, "stdout: %s\n", cpd->m_msg); 409 fprintf(stderr, "stderr: %s\n", cpd->m_msg); 410 411 exit(EXIT_SUCCESS); 412 } 413 414 static 415 void 416 do_fork(const struct base_stream *outfs, void *out, 417 const struct base_stream *errfs, void *err) 418 { 419 atf_process_child_t child; 420 atf_process_status_t status; 421 struct child_print_data cpd = { "msg" }; 422 423 outfs->init(out); 424 errfs->init(err); 425 426 RE(atf_process_fork(&child, child_print, outfs->m_sb_ptr, 427 errfs->m_sb_ptr, &cpd)); 428 if (outfs->process != NULL) 429 outfs->process(out, &child); 430 if (errfs->process != NULL) 431 errfs->process(err, &child); 432 RE(atf_process_child_wait(&child, &status)); 433 434 outfs->fini(out); 435 errfs->fini(err); 436 437 atf_process_status_fini(&status); 438 } 439 440 /* --------------------------------------------------------------------- 441 * Test cases for the "stream" type. 442 * --------------------------------------------------------------------- */ 443 444 ATF_TC(stream_init_capture); 445 ATF_TC_HEAD(stream_init_capture, tc) 446 { 447 atf_tc_set_md_var(tc, "descr", "Tests the " 448 "atf_process_stream_init_capture function"); 449 } 450 ATF_TC_BODY(stream_init_capture, tc) 451 { 452 atf_process_stream_t sb; 453 454 RE(atf_process_stream_init_capture(&sb)); 455 456 ATF_CHECK_EQ(atf_process_stream_type(&sb), 457 atf_process_stream_type_capture); 458 459 atf_process_stream_fini(&sb); 460 } 461 462 ATF_TC(stream_init_connect); 463 ATF_TC_HEAD(stream_init_connect, tc) 464 { 465 atf_tc_set_md_var(tc, "descr", "Tests the " 466 "atf_process_stream_init_connect function"); 467 } 468 ATF_TC_BODY(stream_init_connect, tc) 469 { 470 atf_process_stream_t sb; 471 472 RE(atf_process_stream_init_connect(&sb, 1, 2)); 473 474 ATF_CHECK_EQ(atf_process_stream_type(&sb), 475 atf_process_stream_type_connect); 476 477 atf_process_stream_fini(&sb); 478 } 479 480 ATF_TC(stream_init_inherit); 481 ATF_TC_HEAD(stream_init_inherit, tc) 482 { 483 atf_tc_set_md_var(tc, "descr", "Tests the " 484 "atf_process_stream_init_inherit function"); 485 } 486 ATF_TC_BODY(stream_init_inherit, tc) 487 { 488 atf_process_stream_t sb; 489 490 RE(atf_process_stream_init_inherit(&sb)); 491 492 ATF_CHECK_EQ(atf_process_stream_type(&sb), 493 atf_process_stream_type_inherit); 494 495 atf_process_stream_fini(&sb); 496 } 497 498 ATF_TC(stream_init_redirect_fd); 499 ATF_TC_HEAD(stream_init_redirect_fd, tc) 500 { 501 atf_tc_set_md_var(tc, "descr", "Tests the " 502 "atf_process_stream_init_redirect_fd function"); 503 } 504 ATF_TC_BODY(stream_init_redirect_fd, tc) 505 { 506 atf_process_stream_t sb; 507 508 RE(atf_process_stream_init_redirect_fd(&sb, 1)); 509 510 ATF_CHECK_EQ(atf_process_stream_type(&sb), 511 atf_process_stream_type_redirect_fd); 512 513 atf_process_stream_fini(&sb); 514 } 515 516 ATF_TC(stream_init_redirect_path); 517 ATF_TC_HEAD(stream_init_redirect_path, tc) 518 { 519 atf_tc_set_md_var(tc, "descr", "Tests the " 520 "atf_process_stream_init_redirect_path function"); 521 } 522 ATF_TC_BODY(stream_init_redirect_path, tc) 523 { 524 atf_process_stream_t sb; 525 atf_fs_path_t path; 526 527 RE(atf_fs_path_init_fmt(&path, "foo")); 528 RE(atf_process_stream_init_redirect_path(&sb, &path)); 529 530 ATF_CHECK_EQ(atf_process_stream_type(&sb), 531 atf_process_stream_type_redirect_path); 532 533 atf_process_stream_fini(&sb); 534 atf_fs_path_fini(&path); 535 } 536 537 /* --------------------------------------------------------------------- 538 * Test cases for the "status" type. 539 * --------------------------------------------------------------------- */ 540 541 static void child_exit_success(void) ATF_DEFS_ATTRIBUTE_NORETURN; 542 static void child_exit_failure(void) ATF_DEFS_ATTRIBUTE_NORETURN; 543 static void child_sigkill(void) ATF_DEFS_ATTRIBUTE_NORETURN; 544 static void child_sigquit(void) ATF_DEFS_ATTRIBUTE_NORETURN; 545 static void child_sigterm(void) ATF_DEFS_ATTRIBUTE_NORETURN; 546 547 void 548 child_exit_success(void) 549 { 550 exit(EXIT_SUCCESS); 551 } 552 553 void 554 child_exit_failure(void) 555 { 556 exit(EXIT_FAILURE); 557 } 558 559 void 560 child_sigkill(void) 561 { 562 kill(getpid(), SIGKILL); 563 abort(); 564 } 565 566 void 567 child_sigquit(void) 568 { 569 kill(getpid(), SIGQUIT); 570 abort(); 571 } 572 573 void 574 child_sigterm(void) 575 { 576 kill(getpid(), SIGTERM); 577 abort(); 578 } 579 580 static 581 int 582 fork_and_wait_child(void (*child_func)(void)) 583 { 584 pid_t pid; 585 int status; 586 587 pid = fork(); 588 ATF_REQUIRE(pid != -1); 589 if (pid == 0) { 590 status = 0; /* Silence compiler warnings */ 591 child_func(); 592 UNREACHABLE; 593 } else { 594 ATF_REQUIRE(waitpid(pid, &status, 0) != 0); 595 } 596 597 return status; 598 } 599 600 ATF_TC(status_exited); 601 ATF_TC_HEAD(status_exited, tc) 602 { 603 atf_tc_set_md_var(tc, "descr", "Tests the status type for processes " 604 "that exit cleanly"); 605 } 606 ATF_TC_BODY(status_exited, tc) 607 { 608 { 609 const int rawstatus = fork_and_wait_child(child_exit_success); 610 atf_process_status_t s; 611 RE(atf_process_status_init(&s, rawstatus)); 612 ATF_CHECK(atf_process_status_exited(&s)); 613 ATF_CHECK_EQ(atf_process_status_exitstatus(&s), EXIT_SUCCESS); 614 ATF_CHECK(!atf_process_status_signaled(&s)); 615 atf_process_status_fini(&s); 616 } 617 618 { 619 const int rawstatus = fork_and_wait_child(child_exit_failure); 620 atf_process_status_t s; 621 RE(atf_process_status_init(&s, rawstatus)); 622 ATF_CHECK(atf_process_status_exited(&s)); 623 ATF_CHECK_EQ(atf_process_status_exitstatus(&s), EXIT_FAILURE); 624 ATF_CHECK(!atf_process_status_signaled(&s)); 625 atf_process_status_fini(&s); 626 } 627 } 628 629 ATF_TC(status_signaled); 630 ATF_TC_HEAD(status_signaled, tc) 631 { 632 atf_tc_set_md_var(tc, "descr", "Tests the status type for processes " 633 "that end due to a signal"); 634 } 635 ATF_TC_BODY(status_signaled, tc) 636 { 637 { 638 const int rawstatus = fork_and_wait_child(child_sigkill); 639 atf_process_status_t s; 640 RE(atf_process_status_init(&s, rawstatus)); 641 ATF_CHECK(!atf_process_status_exited(&s)); 642 ATF_CHECK(atf_process_status_signaled(&s)); 643 ATF_CHECK_EQ(atf_process_status_termsig(&s), SIGKILL); 644 ATF_CHECK(!atf_process_status_coredump(&s)); 645 atf_process_status_fini(&s); 646 } 647 648 { 649 const int rawstatus = fork_and_wait_child(child_sigterm); 650 atf_process_status_t s; 651 RE(atf_process_status_init(&s, rawstatus)); 652 ATF_CHECK(!atf_process_status_exited(&s)); 653 ATF_CHECK(atf_process_status_signaled(&s)); 654 ATF_CHECK_EQ(atf_process_status_termsig(&s), SIGTERM); 655 ATF_CHECK(!atf_process_status_coredump(&s)); 656 atf_process_status_fini(&s); 657 } 658 } 659 660 ATF_TC(status_coredump); 661 ATF_TC_HEAD(status_coredump, tc) 662 { 663 atf_tc_set_md_var(tc, "descr", "Tests the status type for processes " 664 "that crash"); 665 } 666 ATF_TC_BODY(status_coredump, tc) 667 { 668 struct rlimit rl; 669 rl.rlim_cur = RLIM_INFINITY; 670 rl.rlim_max = RLIM_INFINITY; 671 if (setrlimit(RLIMIT_CORE, &rl) == -1) 672 atf_tc_skip("Cannot unlimit the core file size; check limits " 673 "manually"); 674 675 const int rawstatus = fork_and_wait_child(child_sigquit); 676 atf_process_status_t s; 677 RE(atf_process_status_init(&s, rawstatus)); 678 ATF_CHECK(!atf_process_status_exited(&s)); 679 ATF_CHECK(atf_process_status_signaled(&s)); 680 ATF_CHECK_EQ(atf_process_status_termsig(&s), SIGQUIT); 681 ATF_CHECK(atf_process_status_coredump(&s)); 682 atf_process_status_fini(&s); 683 } 684 685 /* --------------------------------------------------------------------- 686 * Test cases for the "child" type. 687 * --------------------------------------------------------------------- */ 688 689 static void child_report_pid(void *) ATF_DEFS_ATTRIBUTE_NORETURN; 690 691 static 692 void 693 child_report_pid(void *v) 694 { 695 const pid_t pid = getpid(); 696 if (write(STDOUT_FILENO, &pid, sizeof(pid)) != sizeof(pid)) 697 abort(); 698 fprintf(stderr, "Reporting %d to parent\n", (int)getpid()); 699 exit(EXIT_SUCCESS); 700 } 701 702 ATF_TC(child_pid); 703 ATF_TC_HEAD(child_pid, tc) 704 { 705 atf_tc_set_md_var(tc, "descr", "Tests the correctness of the pid " 706 "stored in the child type"); 707 } 708 ATF_TC_BODY(child_pid, tc) 709 { 710 atf_process_stream_t outsb, errsb; 711 atf_process_child_t child; 712 atf_process_status_t status; 713 pid_t pid; 714 715 RE(atf_process_stream_init_capture(&outsb)); 716 RE(atf_process_stream_init_inherit(&errsb)); 717 718 RE(atf_process_fork(&child, child_report_pid, &outsb, &errsb, NULL)); 719 ATF_CHECK_EQ(read(atf_process_child_stdout(&child), &pid, sizeof(pid)), 720 sizeof(pid)); 721 printf("Expected PID: %d\n", (int)atf_process_child_pid(&child)); 722 printf("Actual PID: %d\n", (int)pid); 723 ATF_CHECK_EQ(atf_process_child_pid(&child), pid); 724 725 RE(atf_process_child_wait(&child, &status)); 726 atf_process_status_fini(&status); 727 728 atf_process_stream_fini(&outsb); 729 atf_process_stream_fini(&errsb); 730 } 731 732 static 733 void 734 child_loop(void *v) 735 { 736 for (;;) 737 sleep(1); 738 } 739 740 static 741 void 742 nop_signal(int sig) 743 { 744 } 745 746 static 747 void 748 child_spawn_loop_and_wait_eintr(void *v) 749 { 750 atf_process_child_t child; 751 atf_process_status_t status; 752 struct sigaction sighup, old_sighup; 753 754 #define RE_ABORT(expr) \ 755 do { \ 756 atf_error_t _aux_err = expr; \ 757 if (atf_is_error(_aux_err)) { \ 758 atf_error_free(_aux_err); \ 759 abort(); \ 760 } \ 761 } while (0) 762 763 { 764 atf_process_stream_t outsb, errsb; 765 766 RE_ABORT(atf_process_stream_init_capture(&outsb)); 767 RE_ABORT(atf_process_stream_init_inherit(&errsb)); 768 RE_ABORT(atf_process_fork(&child, child_loop, &outsb, &errsb, NULL)); 769 atf_process_stream_fini(&outsb); 770 atf_process_stream_fini(&errsb); 771 } 772 773 sighup.sa_handler = nop_signal; 774 sigemptyset(&sighup.sa_mask); 775 sighup.sa_flags = 0; 776 if (sigaction(SIGHUP, &sighup, &old_sighup) == -1) 777 abort(); 778 779 printf("waiting\n"); 780 fflush(stdout); 781 782 fprintf(stderr, "Child entering wait(2)\n"); 783 atf_error_t err = atf_process_child_wait(&child, &status); 784 fprintf(stderr, "Child's wait(2) terminated\n"); 785 if (!atf_is_error(err)) { 786 fprintf(stderr, "wait completed successfully (not interrupted)\n"); 787 abort(); 788 } 789 if (!atf_error_is(err, "libc")) { 790 fprintf(stderr, "wait did not raise libc_error\n"); 791 abort(); 792 } 793 if (atf_libc_error_code(err) != EINTR) { 794 fprintf(stderr, "libc_error is not EINTR\n"); 795 abort(); 796 } 797 atf_error_free(err); 798 799 sigaction(SIGHUP, &old_sighup, NULL); 800 801 fprintf(stderr, "Child is killing subchild\n"); 802 kill(atf_process_child_pid(&child), SIGTERM); 803 804 RE_ABORT(atf_process_child_wait(&child, &status)); 805 atf_process_status_fini(&status); 806 807 #undef RE_ABORT 808 809 exit(EXIT_SUCCESS); 810 } 811 812 ATF_TC(child_wait_eintr); 813 ATF_TC_HEAD(child_wait_eintr, tc) 814 { 815 atf_tc_set_md_var(tc, "descr", "Tests the interruption of the wait " 816 "method by an external signal, and the return of " 817 "an EINTR error"); 818 atf_tc_set_md_var(tc, "timeout", "30"); 819 } 820 ATF_TC_BODY(child_wait_eintr, tc) 821 { 822 atf_process_child_t child; 823 atf_process_status_t status; 824 825 { 826 atf_process_stream_t outsb, errsb; 827 828 RE(atf_process_stream_init_capture(&outsb)); 829 RE(atf_process_stream_init_inherit(&errsb)); 830 RE(atf_process_fork(&child, child_spawn_loop_and_wait_eintr, 831 &outsb, &errsb, NULL)); 832 atf_process_stream_fini(&outsb); 833 atf_process_stream_fini(&errsb); 834 } 835 836 { 837 /* Wait until the child process performs the wait call. This is 838 * racy, because the message we get from it is sent *before* 839 * doing the real system call... but I can't figure any other way 840 * to do this. */ 841 char buf[16]; 842 printf("Waiting for child to issue wait(2)\n"); 843 ATF_REQUIRE(read(atf_process_child_stdout(&child), buf, 844 sizeof(buf)) > 0); 845 sleep(1); 846 } 847 848 printf("Interrupting child's wait(2) call\n"); 849 kill(atf_process_child_pid(&child), SIGHUP); 850 851 printf("Waiting for child's completion\n"); 852 RE(atf_process_child_wait(&child, &status)); 853 ATF_REQUIRE(atf_process_status_exited(&status)); 854 ATF_REQUIRE_EQ(atf_process_status_exitstatus(&status), EXIT_SUCCESS); 855 atf_process_status_fini(&status); 856 } 857 858 /* --------------------------------------------------------------------- 859 * Tests cases for the free functions. 860 * --------------------------------------------------------------------- */ 861 862 static 863 void 864 do_exec(const atf_tc_t *tc, const char *helper_name, atf_process_status_t *s) 865 { 866 atf_fs_path_t process_helpers; 867 const char *argv[3]; 868 869 get_process_helpers_path(tc, true, &process_helpers); 870 871 argv[0] = atf_fs_path_cstring(&process_helpers); 872 argv[1] = helper_name; 873 argv[2] = NULL; 874 printf("Executing %s %s\n", argv[0], argv[1]); 875 876 RE(atf_process_exec_array(s, &process_helpers, argv, NULL, NULL)); 877 atf_fs_path_fini(&process_helpers); 878 } 879 880 static 881 void 882 check_line(int fd, const char *exp) 883 { 884 atf_dynstr_t line; 885 bool eof; 886 887 atf_dynstr_init(&line); 888 eof = read_line(fd, &line); 889 ATF_CHECK(!eof); 890 ATF_CHECK_MSG(atf_equal_dynstr_cstring(&line, exp), 891 "read: '%s', expected: '%s'", 892 atf_dynstr_cstring(&line), exp); 893 atf_dynstr_fini(&line); 894 } 895 896 ATF_TC(exec_failure); 897 ATF_TC_HEAD(exec_failure, tc) 898 { 899 atf_tc_set_md_var(tc, "descr", "Tests execing a command"); 900 } 901 ATF_TC_BODY(exec_failure, tc) 902 { 903 atf_process_status_t status; 904 905 do_exec(tc, "exit-failure", &status); 906 ATF_CHECK(atf_process_status_exited(&status)); 907 ATF_CHECK_EQ(atf_process_status_exitstatus(&status), EXIT_FAILURE); 908 atf_process_status_fini(&status); 909 } 910 911 ATF_TC(exec_list); 912 ATF_TC_HEAD(exec_list, tc) 913 { 914 atf_tc_set_md_var(tc, "descr", "Tests execing a command"); 915 } 916 ATF_TC_BODY(exec_list, tc) 917 { 918 atf_fs_path_t process_helpers; 919 atf_list_t argv; 920 atf_process_status_t status; 921 922 RE(atf_list_init(&argv)); 923 924 get_process_helpers_path(tc, true, &process_helpers); 925 atf_list_append(&argv, strdup(atf_fs_path_cstring(&process_helpers)), true); 926 atf_list_append(&argv, strdup("echo"), true); 927 atf_list_append(&argv, strdup("test-message"), true); 928 { 929 atf_fs_path_t outpath; 930 atf_process_stream_t outsb; 931 932 RE(atf_fs_path_init_fmt(&outpath, "stdout")); 933 RE(atf_process_stream_init_redirect_path(&outsb, &outpath)); 934 RE(atf_process_exec_list(&status, &process_helpers, &argv, &outsb, 935 NULL)); 936 atf_process_stream_fini(&outsb); 937 atf_fs_path_fini(&outpath); 938 } 939 atf_list_fini(&argv); 940 941 ATF_CHECK(atf_process_status_exited(&status)); 942 ATF_CHECK_EQ(atf_process_status_exitstatus(&status), EXIT_SUCCESS); 943 944 { 945 int fd = open("stdout", O_RDONLY); 946 ATF_CHECK(fd != -1); 947 check_line(fd, "test-message"); 948 close(fd); 949 } 950 951 atf_process_status_fini(&status); 952 atf_fs_path_fini(&process_helpers); 953 } 954 955 ATF_TC(exec_success); 956 ATF_TC_HEAD(exec_success, tc) 957 { 958 atf_tc_set_md_var(tc, "descr", "Tests execing a command"); 959 } 960 ATF_TC_BODY(exec_success, tc) 961 { 962 atf_process_status_t status; 963 964 do_exec(tc, "exit-success", &status); 965 ATF_CHECK(atf_process_status_exited(&status)); 966 ATF_CHECK_EQ(atf_process_status_exitstatus(&status), EXIT_SUCCESS); 967 atf_process_status_fini(&status); 968 } 969 970 static const int exit_v_null = 1; 971 static const int exit_v_notnull = 2; 972 973 static 974 void 975 child_cookie(void *v) 976 { 977 if (v == NULL) 978 exit(exit_v_null); 979 else 980 exit(exit_v_notnull); 981 982 UNREACHABLE; 983 } 984 985 ATF_TC(fork_cookie); 986 ATF_TC_HEAD(fork_cookie, tc) 987 { 988 atf_tc_set_md_var(tc, "descr", "Tests forking a child, with " 989 "a null and non-null data cookie"); 990 } 991 ATF_TC_BODY(fork_cookie, tc) 992 { 993 atf_process_stream_t outsb, errsb; 994 995 RE(atf_process_stream_init_inherit(&outsb)); 996 RE(atf_process_stream_init_inherit(&errsb)); 997 998 { 999 atf_process_child_t child; 1000 atf_process_status_t status; 1001 1002 RE(atf_process_fork(&child, child_cookie, &outsb, &errsb, NULL)); 1003 RE(atf_process_child_wait(&child, &status)); 1004 1005 ATF_CHECK(atf_process_status_exited(&status)); 1006 ATF_CHECK_EQ(atf_process_status_exitstatus(&status), exit_v_null); 1007 1008 atf_process_status_fini(&status); 1009 } 1010 1011 { 1012 atf_process_child_t child; 1013 atf_process_status_t status; 1014 int dummy_int; 1015 1016 RE(atf_process_fork(&child, child_cookie, &outsb, &errsb, &dummy_int)); 1017 RE(atf_process_child_wait(&child, &status)); 1018 1019 ATF_CHECK(atf_process_status_exited(&status)); 1020 ATF_CHECK_EQ(atf_process_status_exitstatus(&status), exit_v_notnull); 1021 1022 atf_process_status_fini(&status); 1023 } 1024 1025 atf_process_stream_fini(&errsb); 1026 atf_process_stream_fini(&outsb); 1027 } 1028 1029 #define TC_FORK_STREAMS(outlc, outuc, errlc, erruc) \ 1030 ATF_TC(fork_out_ ## outlc ## _err_ ## errlc); \ 1031 ATF_TC_HEAD(fork_out_ ## outlc ## _err_ ## errlc, tc) \ 1032 { \ 1033 atf_tc_set_md_var(tc, "descr", "Tests forking a child, with " \ 1034 "stdout " #outlc " and stderr " #errlc); \ 1035 } \ 1036 ATF_TC_BODY(fork_out_ ## outlc ## _err_ ## errlc, tc) \ 1037 { \ 1038 struct outlc ## _stream out = outuc ## _STREAM(stdout_type); \ 1039 struct errlc ## _stream err = erruc ## _STREAM(stderr_type); \ 1040 do_fork(&out.m_base, &out, &err.m_base, &err); \ 1041 } 1042 1043 TC_FORK_STREAMS(capture, CAPTURE, capture, CAPTURE); 1044 TC_FORK_STREAMS(capture, CAPTURE, connect, CONNECT); 1045 TC_FORK_STREAMS(capture, CAPTURE, default, DEFAULT); 1046 TC_FORK_STREAMS(capture, CAPTURE, inherit, INHERIT); 1047 TC_FORK_STREAMS(capture, CAPTURE, redirect_fd, REDIRECT_FD); 1048 TC_FORK_STREAMS(capture, CAPTURE, redirect_path, REDIRECT_PATH); 1049 TC_FORK_STREAMS(connect, CONNECT, capture, CAPTURE); 1050 TC_FORK_STREAMS(connect, CONNECT, connect, CONNECT); 1051 TC_FORK_STREAMS(connect, CONNECT, default, DEFAULT); 1052 TC_FORK_STREAMS(connect, CONNECT, inherit, INHERIT); 1053 TC_FORK_STREAMS(connect, CONNECT, redirect_fd, REDIRECT_FD); 1054 TC_FORK_STREAMS(connect, CONNECT, redirect_path, REDIRECT_PATH); 1055 TC_FORK_STREAMS(default, DEFAULT, capture, CAPTURE); 1056 TC_FORK_STREAMS(default, DEFAULT, connect, CONNECT); 1057 TC_FORK_STREAMS(default, DEFAULT, default, DEFAULT); 1058 TC_FORK_STREAMS(default, DEFAULT, inherit, INHERIT); 1059 TC_FORK_STREAMS(default, DEFAULT, redirect_fd, REDIRECT_FD); 1060 TC_FORK_STREAMS(default, DEFAULT, redirect_path, REDIRECT_PATH); 1061 TC_FORK_STREAMS(inherit, INHERIT, capture, CAPTURE); 1062 TC_FORK_STREAMS(inherit, INHERIT, connect, CONNECT); 1063 TC_FORK_STREAMS(inherit, INHERIT, default, DEFAULT); 1064 TC_FORK_STREAMS(inherit, INHERIT, inherit, INHERIT); 1065 TC_FORK_STREAMS(inherit, INHERIT, redirect_fd, REDIRECT_FD); 1066 TC_FORK_STREAMS(inherit, INHERIT, redirect_path, REDIRECT_PATH); 1067 TC_FORK_STREAMS(redirect_fd, REDIRECT_FD, capture, CAPTURE); 1068 TC_FORK_STREAMS(redirect_fd, REDIRECT_FD, connect, CONNECT); 1069 TC_FORK_STREAMS(redirect_fd, REDIRECT_FD, default, DEFAULT); 1070 TC_FORK_STREAMS(redirect_fd, REDIRECT_FD, inherit, INHERIT); 1071 TC_FORK_STREAMS(redirect_fd, REDIRECT_FD, redirect_fd, REDIRECT_FD); 1072 TC_FORK_STREAMS(redirect_fd, REDIRECT_FD, redirect_path, REDIRECT_PATH); 1073 TC_FORK_STREAMS(redirect_path, REDIRECT_PATH, capture, CAPTURE); 1074 TC_FORK_STREAMS(redirect_path, REDIRECT_PATH, connect, CONNECT); 1075 TC_FORK_STREAMS(redirect_path, REDIRECT_PATH, default, DEFAULT); 1076 TC_FORK_STREAMS(redirect_path, REDIRECT_PATH, inherit, INHERIT); 1077 TC_FORK_STREAMS(redirect_path, REDIRECT_PATH, redirect_fd, REDIRECT_FD); 1078 TC_FORK_STREAMS(redirect_path, REDIRECT_PATH, redirect_path, REDIRECT_PATH); 1079 1080 #undef TC_FORK_STREAMS 1081 1082 /* --------------------------------------------------------------------- 1083 * Main. 1084 * --------------------------------------------------------------------- */ 1085 1086 ATF_TP_ADD_TCS(tp) 1087 { 1088 /* Add the tests for the "stream" type. */ 1089 ATF_TP_ADD_TC(tp, stream_init_capture); 1090 ATF_TP_ADD_TC(tp, stream_init_connect); 1091 ATF_TP_ADD_TC(tp, stream_init_inherit); 1092 ATF_TP_ADD_TC(tp, stream_init_redirect_fd); 1093 ATF_TP_ADD_TC(tp, stream_init_redirect_path); 1094 1095 /* Add the tests for the "status" type. */ 1096 ATF_TP_ADD_TC(tp, status_exited); 1097 ATF_TP_ADD_TC(tp, status_signaled); 1098 ATF_TP_ADD_TC(tp, status_coredump); 1099 1100 /* Add the tests for the "child" type. */ 1101 ATF_TP_ADD_TC(tp, child_pid); 1102 ATF_TP_ADD_TC(tp, child_wait_eintr); 1103 1104 /* Add the tests for the free functions. */ 1105 ATF_TP_ADD_TC(tp, exec_failure); 1106 ATF_TP_ADD_TC(tp, exec_list); 1107 ATF_TP_ADD_TC(tp, exec_success); 1108 ATF_TP_ADD_TC(tp, fork_cookie); 1109 ATF_TP_ADD_TC(tp, fork_out_capture_err_capture); 1110 ATF_TP_ADD_TC(tp, fork_out_capture_err_connect); 1111 ATF_TP_ADD_TC(tp, fork_out_capture_err_default); 1112 ATF_TP_ADD_TC(tp, fork_out_capture_err_inherit); 1113 ATF_TP_ADD_TC(tp, fork_out_capture_err_redirect_fd); 1114 ATF_TP_ADD_TC(tp, fork_out_capture_err_redirect_path); 1115 ATF_TP_ADD_TC(tp, fork_out_connect_err_capture); 1116 ATF_TP_ADD_TC(tp, fork_out_connect_err_connect); 1117 ATF_TP_ADD_TC(tp, fork_out_connect_err_default); 1118 ATF_TP_ADD_TC(tp, fork_out_connect_err_inherit); 1119 ATF_TP_ADD_TC(tp, fork_out_connect_err_redirect_fd); 1120 ATF_TP_ADD_TC(tp, fork_out_connect_err_redirect_path); 1121 ATF_TP_ADD_TC(tp, fork_out_default_err_capture); 1122 ATF_TP_ADD_TC(tp, fork_out_default_err_connect); 1123 ATF_TP_ADD_TC(tp, fork_out_default_err_default); 1124 ATF_TP_ADD_TC(tp, fork_out_default_err_inherit); 1125 ATF_TP_ADD_TC(tp, fork_out_default_err_redirect_fd); 1126 ATF_TP_ADD_TC(tp, fork_out_default_err_redirect_path); 1127 ATF_TP_ADD_TC(tp, fork_out_inherit_err_capture); 1128 ATF_TP_ADD_TC(tp, fork_out_inherit_err_connect); 1129 ATF_TP_ADD_TC(tp, fork_out_inherit_err_default); 1130 ATF_TP_ADD_TC(tp, fork_out_inherit_err_inherit); 1131 ATF_TP_ADD_TC(tp, fork_out_inherit_err_redirect_fd); 1132 ATF_TP_ADD_TC(tp, fork_out_inherit_err_redirect_path); 1133 ATF_TP_ADD_TC(tp, fork_out_redirect_fd_err_capture); 1134 ATF_TP_ADD_TC(tp, fork_out_redirect_fd_err_connect); 1135 ATF_TP_ADD_TC(tp, fork_out_redirect_fd_err_default); 1136 ATF_TP_ADD_TC(tp, fork_out_redirect_fd_err_inherit); 1137 ATF_TP_ADD_TC(tp, fork_out_redirect_fd_err_redirect_fd); 1138 ATF_TP_ADD_TC(tp, fork_out_redirect_fd_err_redirect_path); 1139 ATF_TP_ADD_TC(tp, fork_out_redirect_path_err_capture); 1140 ATF_TP_ADD_TC(tp, fork_out_redirect_path_err_connect); 1141 ATF_TP_ADD_TC(tp, fork_out_redirect_path_err_default); 1142 ATF_TP_ADD_TC(tp, fork_out_redirect_path_err_inherit); 1143 ATF_TP_ADD_TC(tp, fork_out_redirect_path_err_redirect_fd); 1144 ATF_TP_ADD_TC(tp, fork_out_redirect_path_err_redirect_path); 1145 1146 return atf_no_error(); 1147 } 1148