1273929Sjmmv/* Copyright (c) 2008 The NetBSD Foundation, Inc. 2240116Smarcel * All rights reserved. 3240116Smarcel * 4240116Smarcel * Redistribution and use in source and binary forms, with or without 5240116Smarcel * modification, are permitted provided that the following conditions 6240116Smarcel * are met: 7240116Smarcel * 1. Redistributions of source code must retain the above copyright 8240116Smarcel * notice, this list of conditions and the following disclaimer. 9240116Smarcel * 2. Redistributions in binary form must reproduce the above copyright 10240116Smarcel * notice, this list of conditions and the following disclaimer in the 11240116Smarcel * documentation and/or other materials provided with the distribution. 12240116Smarcel * 13240116Smarcel * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 14240116Smarcel * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 15240116Smarcel * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 16240116Smarcel * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17240116Smarcel * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 18240116Smarcel * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19240116Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 20240116Smarcel * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21240116Smarcel * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22240116Smarcel * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23240116Smarcel * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 24273929Sjmmv * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 25240116Smarcel 26273929Sjmmv#include "atf-c/detail/process.h" 27273929Sjmmv 28240116Smarcel#include <sys/types.h> 29240116Smarcel#include <sys/time.h> 30240116Smarcel#include <sys/resource.h> 31240116Smarcel#include <sys/wait.h> 32240116Smarcel 33240116Smarcel#include <errno.h> 34240116Smarcel#include <fcntl.h> 35240116Smarcel#include <signal.h> 36240116Smarcel#include <stdio.h> 37240116Smarcel#include <stdlib.h> 38240116Smarcel#include <string.h> 39240116Smarcel#include <unistd.h> 40240116Smarcel 41240116Smarcel#include <atf-c.h> 42240116Smarcel 43240116Smarcel#include "atf-c/defs.h" 44273929Sjmmv#include "atf-c/detail/sanity.h" 45273929Sjmmv#include "atf-c/detail/test_helpers.h" 46240116Smarcel 47240116Smarcelatf_error_t atf_process_status_init(atf_process_status_t *, int); 48240116Smarcel 49240116Smarcel/* --------------------------------------------------------------------- 50240116Smarcel * Auxiliary functions for testing of 'atf_process_fork'. 51240116Smarcel * --------------------------------------------------------------------- */ 52240116Smarcel 53240116Smarcel/* 54240116Smarcel * Testing of atf_process_fork is quite messy. We want to be able to test 55240116Smarcel * all the possible combinations of stdout and stderr behavior to ensure 56240116Smarcel * that the streams are manipulated correctly. 57240116Smarcel * 58240116Smarcel * To do this, the do_fork function is a wrapper for atf_process_fork that 59240116Smarcel * issues stream-specific hooks before fork, while the child is running and 60240116Smarcel * after the child terminates. We then provide test cases that just call 61240116Smarcel * do_fork with different hooks. 62240116Smarcel * 63240116Smarcel * The hooks are described by base_stream, and we then have one *_stream 64240116Smarcel * type for ever possible stream behavior. 65240116Smarcel */ 66240116Smarcel 67240116Smarcelenum out_type { stdout_type, stderr_type }; 68240116Smarcel 69240116Smarcelstruct base_stream { 70240116Smarcel void (*init)(void *); 71240116Smarcel void (*process)(void *, atf_process_child_t *); 72240116Smarcel void (*fini)(void *); 73240116Smarcel 74240116Smarcel /* m_sb is initialized by subclasses that need it, but all consumers 75240116Smarcel * must use m_sb_ptr, which may or may not point to m_sb. This allows 76240116Smarcel * us to test the interface with a NULL value, which triggers a 77240116Smarcel * default behavior. */ 78240116Smarcel atf_process_stream_t m_sb; 79240116Smarcel atf_process_stream_t *m_sb_ptr; 80240116Smarcel enum out_type m_type; 81240116Smarcel}; 82240116Smarcel#define BASE_STREAM(ihook, phook, fhook, type) \ 83240116Smarcel { .init = ihook, \ 84240116Smarcel .process = phook, \ 85240116Smarcel .fini = fhook, \ 86240116Smarcel .m_type = type } 87240116Smarcel 88240116Smarcelstatic 89240116Smarcelvoid 90240116Smarcelcheck_file(const enum out_type type) 91240116Smarcel{ 92240116Smarcel switch (type) { 93240116Smarcel case stdout_type: 94258289Sjmmv ATF_CHECK(atf_utils_grep_file("stdout: msg", "stdout")); 95258289Sjmmv ATF_CHECK(!atf_utils_grep_file("stderr: msg", "stdout")); 96240116Smarcel break; 97240116Smarcel case stderr_type: 98258289Sjmmv ATF_CHECK(atf_utils_grep_file("stderr: msg", "stderr")); 99258289Sjmmv ATF_CHECK(!atf_utils_grep_file("stdout: msg", "stderr")); 100240116Smarcel break; 101240116Smarcel default: 102240116Smarcel UNREACHABLE; 103240116Smarcel } 104240116Smarcel} 105240116Smarcel 106240116Smarcelstruct capture_stream { 107240116Smarcel struct base_stream m_base; 108240116Smarcel 109258289Sjmmv char *m_msg; 110240116Smarcel}; 111240116Smarcel#define CAPTURE_STREAM(type) \ 112240116Smarcel { .m_base = BASE_STREAM(capture_stream_init, \ 113240116Smarcel capture_stream_process, \ 114240116Smarcel capture_stream_fini, \ 115240116Smarcel type) } 116240116Smarcel 117240116Smarcelstatic 118240116Smarcelvoid 119240116Smarcelcapture_stream_init(void *v) 120240116Smarcel{ 121240116Smarcel struct capture_stream *s = v; 122240116Smarcel 123240116Smarcel s->m_base.m_sb_ptr = &s->m_base.m_sb; 124240116Smarcel RE(atf_process_stream_init_capture(&s->m_base.m_sb)); 125258289Sjmmv s->m_msg = NULL; 126240116Smarcel} 127240116Smarcel 128240116Smarcelstatic 129240116Smarcelvoid 130240116Smarcelcapture_stream_process(void *v, atf_process_child_t *c) 131240116Smarcel{ 132240116Smarcel struct capture_stream *s = v; 133240116Smarcel 134240116Smarcel switch (s->m_base.m_type) { 135240116Smarcel case stdout_type: 136258289Sjmmv s->m_msg = atf_utils_readline(atf_process_child_stdout(c)); 137240116Smarcel break; 138240116Smarcel case stderr_type: 139258289Sjmmv s->m_msg = atf_utils_readline(atf_process_child_stderr(c)); 140240116Smarcel break; 141240116Smarcel default: 142240116Smarcel UNREACHABLE; 143240116Smarcel } 144240116Smarcel} 145240116Smarcel 146240116Smarcelstatic 147240116Smarcelvoid 148240116Smarcelcapture_stream_fini(void *v) 149240116Smarcel{ 150240116Smarcel struct capture_stream *s = v; 151240116Smarcel 152240116Smarcel switch (s->m_base.m_type) { 153240116Smarcel case stdout_type: 154258289Sjmmv ATF_CHECK(atf_utils_grep_string("stdout: msg", s->m_msg)); 155258289Sjmmv ATF_CHECK(!atf_utils_grep_string("stderr: msg", s->m_msg)); 156240116Smarcel break; 157240116Smarcel case stderr_type: 158258289Sjmmv ATF_CHECK(!atf_utils_grep_string("stdout: msg", s->m_msg)); 159258289Sjmmv ATF_CHECK(atf_utils_grep_string("stderr: msg", s->m_msg)); 160240116Smarcel break; 161240116Smarcel default: 162240116Smarcel UNREACHABLE; 163240116Smarcel } 164240116Smarcel 165258289Sjmmv free(s->m_msg); 166240116Smarcel atf_process_stream_fini(&s->m_base.m_sb); 167240116Smarcel} 168240116Smarcel 169240116Smarcelstruct connect_stream { 170240116Smarcel struct base_stream m_base; 171240116Smarcel 172240116Smarcel int m_fd; 173240116Smarcel}; 174240116Smarcel#define CONNECT_STREAM(type) \ 175240116Smarcel { .m_base = BASE_STREAM(connect_stream_init, \ 176240116Smarcel NULL, \ 177240116Smarcel connect_stream_fini, \ 178240116Smarcel type) } 179240116Smarcel 180240116Smarcelstatic 181240116Smarcelvoid 182240116Smarcelconnect_stream_init(void *v) 183240116Smarcel{ 184240116Smarcel struct connect_stream *s = v; 185240116Smarcel int src_fd; 186240116Smarcel 187240116Smarcel switch (s->m_base.m_type) { 188240116Smarcel case stdout_type: 189240116Smarcel src_fd = STDOUT_FILENO; 190240116Smarcel s->m_fd = open("stdout", O_WRONLY | O_CREAT | O_TRUNC, 0644); 191240116Smarcel break; 192240116Smarcel case stderr_type: 193240116Smarcel src_fd = STDERR_FILENO; 194240116Smarcel s->m_fd = open("stderr", O_WRONLY | O_CREAT | O_TRUNC, 0644); 195240116Smarcel break; 196240116Smarcel default: 197240116Smarcel UNREACHABLE; 198240116Smarcel src_fd = -1; 199240116Smarcel } 200240116Smarcel ATF_REQUIRE(s->m_fd != -1); 201240116Smarcel 202240116Smarcel s->m_base.m_sb_ptr = &s->m_base.m_sb; 203240116Smarcel RE(atf_process_stream_init_connect(&s->m_base.m_sb, src_fd, s->m_fd)); 204240116Smarcel} 205240116Smarcel 206240116Smarcelstatic 207240116Smarcelvoid 208240116Smarcelconnect_stream_fini(void *v) 209240116Smarcel{ 210240116Smarcel struct connect_stream *s = v; 211240116Smarcel 212240116Smarcel ATF_REQUIRE(close(s->m_fd) != -1); 213240116Smarcel 214240116Smarcel atf_process_stream_fini(&s->m_base.m_sb); 215240116Smarcel 216240116Smarcel check_file(s->m_base.m_type); 217240116Smarcel} 218240116Smarcel 219240116Smarcelstruct inherit_stream { 220240116Smarcel struct base_stream m_base; 221240116Smarcel int m_fd; 222240116Smarcel 223240116Smarcel int m_old_fd; 224240116Smarcel}; 225240116Smarcel#define INHERIT_STREAM(type) \ 226240116Smarcel { .m_base = BASE_STREAM(inherit_stream_init, \ 227240116Smarcel NULL, \ 228240116Smarcel inherit_stream_fini, \ 229240116Smarcel type) } 230240116Smarcel 231240116Smarcelstatic 232240116Smarcelvoid 233240116Smarcelinherit_stream_init(void *v) 234240116Smarcel{ 235240116Smarcel struct inherit_stream *s = v; 236240116Smarcel const char *name; 237240116Smarcel 238240116Smarcel s->m_base.m_sb_ptr = &s->m_base.m_sb; 239240116Smarcel RE(atf_process_stream_init_inherit(&s->m_base.m_sb)); 240240116Smarcel 241240116Smarcel switch (s->m_base.m_type) { 242240116Smarcel case stdout_type: 243240116Smarcel s->m_fd = STDOUT_FILENO; 244240116Smarcel name = "stdout"; 245240116Smarcel break; 246240116Smarcel case stderr_type: 247240116Smarcel s->m_fd = STDERR_FILENO; 248240116Smarcel name = "stderr"; 249240116Smarcel break; 250240116Smarcel default: 251240116Smarcel UNREACHABLE; 252240116Smarcel name = NULL; 253240116Smarcel } 254240116Smarcel 255240116Smarcel s->m_old_fd = dup(s->m_fd); 256240116Smarcel ATF_REQUIRE(s->m_old_fd != -1); 257240116Smarcel ATF_REQUIRE(close(s->m_fd) != -1); 258240116Smarcel ATF_REQUIRE_EQ(open(name, O_WRONLY | O_CREAT | O_TRUNC, 0644), 259240116Smarcel s->m_fd); 260240116Smarcel} 261240116Smarcel 262240116Smarcelstatic 263240116Smarcelvoid 264240116Smarcelinherit_stream_fini(void *v) 265240116Smarcel{ 266240116Smarcel struct inherit_stream *s = v; 267240116Smarcel 268240116Smarcel ATF_REQUIRE(dup2(s->m_old_fd, s->m_fd) != -1); 269240116Smarcel ATF_REQUIRE(close(s->m_old_fd) != -1); 270240116Smarcel 271240116Smarcel atf_process_stream_fini(&s->m_base.m_sb); 272240116Smarcel 273240116Smarcel check_file(s->m_base.m_type); 274240116Smarcel} 275240116Smarcel 276240116Smarcel#define default_stream inherit_stream 277240116Smarcel#define DEFAULT_STREAM(type) \ 278240116Smarcel { .m_base = BASE_STREAM(default_stream_init, \ 279240116Smarcel NULL, \ 280240116Smarcel default_stream_fini, \ 281240116Smarcel type) } 282240116Smarcel 283240116Smarcelstatic 284240116Smarcelvoid 285240116Smarceldefault_stream_init(void *v) 286240116Smarcel{ 287240116Smarcel struct inherit_stream *s = v; 288240116Smarcel 289240116Smarcel inherit_stream_init(v); 290240116Smarcel s->m_base.m_sb_ptr = NULL; 291240116Smarcel} 292240116Smarcel 293240116Smarcelstatic 294240116Smarcelvoid 295240116Smarceldefault_stream_fini(void *v) 296240116Smarcel{ 297240116Smarcel inherit_stream_fini(v); 298240116Smarcel} 299240116Smarcel 300240116Smarcelstruct redirect_fd_stream { 301240116Smarcel struct base_stream m_base; 302240116Smarcel 303240116Smarcel int m_fd; 304240116Smarcel}; 305240116Smarcel#define REDIRECT_FD_STREAM(type) \ 306240116Smarcel { .m_base = BASE_STREAM(redirect_fd_stream_init, \ 307240116Smarcel NULL, \ 308240116Smarcel redirect_fd_stream_fini, \ 309240116Smarcel type) } 310240116Smarcel 311240116Smarcelstatic 312240116Smarcelvoid 313240116Smarcelredirect_fd_stream_init(void *v) 314240116Smarcel{ 315240116Smarcel struct redirect_fd_stream *s = v; 316240116Smarcel 317240116Smarcel switch (s->m_base.m_type) { 318240116Smarcel case stdout_type: 319240116Smarcel s->m_fd = open("stdout", O_WRONLY | O_CREAT | O_TRUNC, 0644); 320240116Smarcel break; 321240116Smarcel case stderr_type: 322240116Smarcel s->m_fd = open("stderr", O_WRONLY | O_CREAT | O_TRUNC, 0644); 323240116Smarcel break; 324240116Smarcel default: 325240116Smarcel UNREACHABLE; 326240116Smarcel } 327240116Smarcel ATF_REQUIRE(s->m_fd != -1); 328240116Smarcel 329240116Smarcel s->m_base.m_sb_ptr = &s->m_base.m_sb; 330240116Smarcel RE(atf_process_stream_init_redirect_fd(&s->m_base.m_sb, s->m_fd)); 331240116Smarcel} 332240116Smarcel 333240116Smarcelstatic 334240116Smarcelvoid 335240116Smarcelredirect_fd_stream_fini(void *v) 336240116Smarcel{ 337240116Smarcel struct redirect_fd_stream *s = v; 338240116Smarcel 339240116Smarcel ATF_REQUIRE(close(s->m_fd) != -1); 340240116Smarcel 341240116Smarcel atf_process_stream_fini(&s->m_base.m_sb); 342240116Smarcel 343240116Smarcel check_file(s->m_base.m_type); 344240116Smarcel} 345240116Smarcel 346240116Smarcelstruct redirect_path_stream { 347240116Smarcel struct base_stream m_base; 348240116Smarcel 349240116Smarcel atf_fs_path_t m_path; 350240116Smarcel}; 351240116Smarcel#define REDIRECT_PATH_STREAM(type) \ 352240116Smarcel { .m_base = BASE_STREAM(redirect_path_stream_init, \ 353240116Smarcel NULL, \ 354240116Smarcel redirect_path_stream_fini, \ 355240116Smarcel type) } 356240116Smarcel 357240116Smarcelstatic 358240116Smarcelvoid 359240116Smarcelredirect_path_stream_init(void *v) 360240116Smarcel{ 361240116Smarcel struct redirect_path_stream *s = v; 362240116Smarcel 363240116Smarcel switch (s->m_base.m_type) { 364240116Smarcel case stdout_type: 365240116Smarcel RE(atf_fs_path_init_fmt(&s->m_path, "stdout")); 366240116Smarcel break; 367240116Smarcel case stderr_type: 368240116Smarcel RE(atf_fs_path_init_fmt(&s->m_path, "stderr")); 369240116Smarcel break; 370240116Smarcel default: 371240116Smarcel UNREACHABLE; 372240116Smarcel } 373240116Smarcel 374240116Smarcel s->m_base.m_sb_ptr = &s->m_base.m_sb; 375240116Smarcel RE(atf_process_stream_init_redirect_path(&s->m_base.m_sb, &s->m_path)); 376240116Smarcel} 377240116Smarcel 378240116Smarcelstatic 379240116Smarcelvoid 380240116Smarcelredirect_path_stream_fini(void *v) 381240116Smarcel{ 382240116Smarcel struct redirect_path_stream *s = v; 383240116Smarcel 384240116Smarcel atf_process_stream_fini(&s->m_base.m_sb); 385240116Smarcel 386240116Smarcel atf_fs_path_fini(&s->m_path); 387240116Smarcel 388240116Smarcel check_file(s->m_base.m_type); 389240116Smarcel} 390240116Smarcel 391240116Smarcelstatic void child_print(void *) ATF_DEFS_ATTRIBUTE_NORETURN; 392240116Smarcel 393240116Smarcelstruct child_print_data { 394240116Smarcel const char *m_msg; 395240116Smarcel}; 396240116Smarcel 397240116Smarcelstatic 398240116Smarcelvoid 399240116Smarcelchild_print(void *v) 400240116Smarcel{ 401240116Smarcel struct child_print_data *cpd = v; 402240116Smarcel 403240116Smarcel fprintf(stdout, "stdout: %s\n", cpd->m_msg); 404240116Smarcel fprintf(stderr, "stderr: %s\n", cpd->m_msg); 405240116Smarcel 406240116Smarcel exit(EXIT_SUCCESS); 407240116Smarcel} 408240116Smarcel 409240116Smarcelstatic 410240116Smarcelvoid 411240116Smarceldo_fork(const struct base_stream *outfs, void *out, 412240116Smarcel const struct base_stream *errfs, void *err) 413240116Smarcel{ 414240116Smarcel atf_process_child_t child; 415240116Smarcel atf_process_status_t status; 416240116Smarcel struct child_print_data cpd = { "msg" }; 417240116Smarcel 418240116Smarcel outfs->init(out); 419240116Smarcel errfs->init(err); 420240116Smarcel 421240116Smarcel RE(atf_process_fork(&child, child_print, outfs->m_sb_ptr, 422240116Smarcel errfs->m_sb_ptr, &cpd)); 423240116Smarcel if (outfs->process != NULL) 424240116Smarcel outfs->process(out, &child); 425240116Smarcel if (errfs->process != NULL) 426240116Smarcel errfs->process(err, &child); 427240116Smarcel RE(atf_process_child_wait(&child, &status)); 428240116Smarcel 429240116Smarcel outfs->fini(out); 430240116Smarcel errfs->fini(err); 431240116Smarcel 432240116Smarcel atf_process_status_fini(&status); 433240116Smarcel} 434240116Smarcel 435240116Smarcel/* --------------------------------------------------------------------- 436240116Smarcel * Test cases for the "stream" type. 437240116Smarcel * --------------------------------------------------------------------- */ 438240116Smarcel 439240116SmarcelATF_TC(stream_init_capture); 440240116SmarcelATF_TC_HEAD(stream_init_capture, tc) 441240116Smarcel{ 442240116Smarcel atf_tc_set_md_var(tc, "descr", "Tests the " 443240116Smarcel "atf_process_stream_init_capture function"); 444240116Smarcel} 445240116SmarcelATF_TC_BODY(stream_init_capture, tc) 446240116Smarcel{ 447240116Smarcel atf_process_stream_t sb; 448240116Smarcel 449240116Smarcel RE(atf_process_stream_init_capture(&sb)); 450240116Smarcel 451240116Smarcel ATF_CHECK_EQ(atf_process_stream_type(&sb), 452240116Smarcel atf_process_stream_type_capture); 453240116Smarcel 454240116Smarcel atf_process_stream_fini(&sb); 455240116Smarcel} 456240116Smarcel 457240116SmarcelATF_TC(stream_init_connect); 458240116SmarcelATF_TC_HEAD(stream_init_connect, tc) 459240116Smarcel{ 460240116Smarcel atf_tc_set_md_var(tc, "descr", "Tests the " 461240116Smarcel "atf_process_stream_init_connect function"); 462240116Smarcel} 463240116SmarcelATF_TC_BODY(stream_init_connect, tc) 464240116Smarcel{ 465240116Smarcel atf_process_stream_t sb; 466240116Smarcel 467240116Smarcel RE(atf_process_stream_init_connect(&sb, 1, 2)); 468240116Smarcel 469240116Smarcel ATF_CHECK_EQ(atf_process_stream_type(&sb), 470240116Smarcel atf_process_stream_type_connect); 471240116Smarcel 472240116Smarcel atf_process_stream_fini(&sb); 473240116Smarcel} 474240116Smarcel 475240116SmarcelATF_TC(stream_init_inherit); 476240116SmarcelATF_TC_HEAD(stream_init_inherit, tc) 477240116Smarcel{ 478240116Smarcel atf_tc_set_md_var(tc, "descr", "Tests the " 479240116Smarcel "atf_process_stream_init_inherit function"); 480240116Smarcel} 481240116SmarcelATF_TC_BODY(stream_init_inherit, tc) 482240116Smarcel{ 483240116Smarcel atf_process_stream_t sb; 484240116Smarcel 485240116Smarcel RE(atf_process_stream_init_inherit(&sb)); 486240116Smarcel 487240116Smarcel ATF_CHECK_EQ(atf_process_stream_type(&sb), 488240116Smarcel atf_process_stream_type_inherit); 489240116Smarcel 490240116Smarcel atf_process_stream_fini(&sb); 491240116Smarcel} 492240116Smarcel 493240116SmarcelATF_TC(stream_init_redirect_fd); 494240116SmarcelATF_TC_HEAD(stream_init_redirect_fd, tc) 495240116Smarcel{ 496240116Smarcel atf_tc_set_md_var(tc, "descr", "Tests the " 497240116Smarcel "atf_process_stream_init_redirect_fd function"); 498240116Smarcel} 499240116SmarcelATF_TC_BODY(stream_init_redirect_fd, tc) 500240116Smarcel{ 501240116Smarcel atf_process_stream_t sb; 502240116Smarcel 503240116Smarcel RE(atf_process_stream_init_redirect_fd(&sb, 1)); 504240116Smarcel 505240116Smarcel ATF_CHECK_EQ(atf_process_stream_type(&sb), 506240116Smarcel atf_process_stream_type_redirect_fd); 507240116Smarcel 508240116Smarcel atf_process_stream_fini(&sb); 509240116Smarcel} 510240116Smarcel 511240116SmarcelATF_TC(stream_init_redirect_path); 512240116SmarcelATF_TC_HEAD(stream_init_redirect_path, tc) 513240116Smarcel{ 514240116Smarcel atf_tc_set_md_var(tc, "descr", "Tests the " 515240116Smarcel "atf_process_stream_init_redirect_path function"); 516240116Smarcel} 517240116SmarcelATF_TC_BODY(stream_init_redirect_path, tc) 518240116Smarcel{ 519240116Smarcel atf_process_stream_t sb; 520240116Smarcel atf_fs_path_t path; 521240116Smarcel 522240116Smarcel RE(atf_fs_path_init_fmt(&path, "foo")); 523240116Smarcel RE(atf_process_stream_init_redirect_path(&sb, &path)); 524240116Smarcel 525240116Smarcel ATF_CHECK_EQ(atf_process_stream_type(&sb), 526240116Smarcel atf_process_stream_type_redirect_path); 527240116Smarcel 528240116Smarcel atf_process_stream_fini(&sb); 529240116Smarcel atf_fs_path_fini(&path); 530240116Smarcel} 531240116Smarcel 532240116Smarcel/* --------------------------------------------------------------------- 533240116Smarcel * Test cases for the "status" type. 534240116Smarcel * --------------------------------------------------------------------- */ 535240116Smarcel 536240116Smarcelstatic void child_exit_success(void) ATF_DEFS_ATTRIBUTE_NORETURN; 537240116Smarcelstatic void child_exit_failure(void) ATF_DEFS_ATTRIBUTE_NORETURN; 538240116Smarcelstatic void child_sigkill(void) ATF_DEFS_ATTRIBUTE_NORETURN; 539240116Smarcelstatic void child_sigquit(void) ATF_DEFS_ATTRIBUTE_NORETURN; 540240116Smarcelstatic void child_sigterm(void) ATF_DEFS_ATTRIBUTE_NORETURN; 541240116Smarcel 542240116Smarcelvoid 543240116Smarcelchild_exit_success(void) 544240116Smarcel{ 545240116Smarcel exit(EXIT_SUCCESS); 546240116Smarcel} 547240116Smarcel 548240116Smarcelvoid 549240116Smarcelchild_exit_failure(void) 550240116Smarcel{ 551240116Smarcel exit(EXIT_FAILURE); 552240116Smarcel} 553240116Smarcel 554240116Smarcelvoid 555240116Smarcelchild_sigkill(void) 556240116Smarcel{ 557240116Smarcel kill(getpid(), SIGKILL); 558240116Smarcel abort(); 559240116Smarcel} 560240116Smarcel 561240116Smarcelvoid 562240116Smarcelchild_sigquit(void) 563240116Smarcel{ 564240116Smarcel kill(getpid(), SIGQUIT); 565240116Smarcel abort(); 566240116Smarcel} 567240116Smarcel 568240116Smarcelvoid 569240116Smarcelchild_sigterm(void) 570240116Smarcel{ 571240116Smarcel kill(getpid(), SIGTERM); 572240116Smarcel abort(); 573240116Smarcel} 574240116Smarcel 575240116Smarcelstatic 576240116Smarcelint 577240116Smarcelfork_and_wait_child(void (*child_func)(void)) 578240116Smarcel{ 579240116Smarcel pid_t pid; 580240116Smarcel int status; 581240116Smarcel 582240116Smarcel pid = fork(); 583240116Smarcel ATF_REQUIRE(pid != -1); 584240116Smarcel if (pid == 0) { 585240116Smarcel status = 0; /* Silence compiler warnings */ 586240116Smarcel child_func(); 587240116Smarcel UNREACHABLE; 588240116Smarcel } else { 589240116Smarcel ATF_REQUIRE(waitpid(pid, &status, 0) != 0); 590240116Smarcel } 591240116Smarcel 592240116Smarcel return status; 593240116Smarcel} 594240116Smarcel 595240116SmarcelATF_TC(status_exited); 596240116SmarcelATF_TC_HEAD(status_exited, tc) 597240116Smarcel{ 598240116Smarcel atf_tc_set_md_var(tc, "descr", "Tests the status type for processes " 599240116Smarcel "that exit cleanly"); 600240116Smarcel} 601240116SmarcelATF_TC_BODY(status_exited, tc) 602240116Smarcel{ 603240116Smarcel { 604240116Smarcel const int rawstatus = fork_and_wait_child(child_exit_success); 605240116Smarcel atf_process_status_t s; 606240116Smarcel RE(atf_process_status_init(&s, rawstatus)); 607240116Smarcel ATF_CHECK(atf_process_status_exited(&s)); 608240116Smarcel ATF_CHECK_EQ(atf_process_status_exitstatus(&s), EXIT_SUCCESS); 609240116Smarcel ATF_CHECK(!atf_process_status_signaled(&s)); 610240116Smarcel atf_process_status_fini(&s); 611240116Smarcel } 612240116Smarcel 613240116Smarcel { 614240116Smarcel const int rawstatus = fork_and_wait_child(child_exit_failure); 615240116Smarcel atf_process_status_t s; 616240116Smarcel RE(atf_process_status_init(&s, rawstatus)); 617240116Smarcel ATF_CHECK(atf_process_status_exited(&s)); 618240116Smarcel ATF_CHECK_EQ(atf_process_status_exitstatus(&s), EXIT_FAILURE); 619240116Smarcel ATF_CHECK(!atf_process_status_signaled(&s)); 620240116Smarcel atf_process_status_fini(&s); 621240116Smarcel } 622240116Smarcel} 623240116Smarcel 624240116SmarcelATF_TC(status_signaled); 625240116SmarcelATF_TC_HEAD(status_signaled, tc) 626240116Smarcel{ 627240116Smarcel atf_tc_set_md_var(tc, "descr", "Tests the status type for processes " 628240116Smarcel "that end due to a signal"); 629240116Smarcel} 630240116SmarcelATF_TC_BODY(status_signaled, tc) 631240116Smarcel{ 632240116Smarcel { 633240116Smarcel const int rawstatus = fork_and_wait_child(child_sigkill); 634240116Smarcel atf_process_status_t s; 635240116Smarcel RE(atf_process_status_init(&s, rawstatus)); 636240116Smarcel ATF_CHECK(!atf_process_status_exited(&s)); 637240116Smarcel ATF_CHECK(atf_process_status_signaled(&s)); 638240116Smarcel ATF_CHECK_EQ(atf_process_status_termsig(&s), SIGKILL); 639240116Smarcel ATF_CHECK(!atf_process_status_coredump(&s)); 640240116Smarcel atf_process_status_fini(&s); 641240116Smarcel } 642240116Smarcel 643240116Smarcel { 644240116Smarcel const int rawstatus = fork_and_wait_child(child_sigterm); 645240116Smarcel atf_process_status_t s; 646240116Smarcel RE(atf_process_status_init(&s, rawstatus)); 647240116Smarcel ATF_CHECK(!atf_process_status_exited(&s)); 648240116Smarcel ATF_CHECK(atf_process_status_signaled(&s)); 649240116Smarcel ATF_CHECK_EQ(atf_process_status_termsig(&s), SIGTERM); 650240116Smarcel ATF_CHECK(!atf_process_status_coredump(&s)); 651240116Smarcel atf_process_status_fini(&s); 652240116Smarcel } 653240116Smarcel} 654240116Smarcel 655240116SmarcelATF_TC(status_coredump); 656240116SmarcelATF_TC_HEAD(status_coredump, tc) 657240116Smarcel{ 658240116Smarcel atf_tc_set_md_var(tc, "descr", "Tests the status type for processes " 659240116Smarcel "that crash"); 660240116Smarcel} 661240116SmarcelATF_TC_BODY(status_coredump, tc) 662240116Smarcel{ 663240116Smarcel struct rlimit rl; 664240116Smarcel rl.rlim_cur = RLIM_INFINITY; 665240116Smarcel rl.rlim_max = RLIM_INFINITY; 666240116Smarcel if (setrlimit(RLIMIT_CORE, &rl) == -1) 667240116Smarcel atf_tc_skip("Cannot unlimit the core file size; check limits " 668240116Smarcel "manually"); 669240116Smarcel 670240116Smarcel const int rawstatus = fork_and_wait_child(child_sigquit); 671240116Smarcel atf_process_status_t s; 672240116Smarcel RE(atf_process_status_init(&s, rawstatus)); 673240116Smarcel ATF_CHECK(!atf_process_status_exited(&s)); 674240116Smarcel ATF_CHECK(atf_process_status_signaled(&s)); 675240116Smarcel ATF_CHECK_EQ(atf_process_status_termsig(&s), SIGQUIT); 676240116Smarcel ATF_CHECK(atf_process_status_coredump(&s)); 677240116Smarcel atf_process_status_fini(&s); 678240116Smarcel} 679240116Smarcel 680240116Smarcel/* --------------------------------------------------------------------- 681240116Smarcel * Test cases for the "child" type. 682240116Smarcel * --------------------------------------------------------------------- */ 683240116Smarcel 684240116Smarcelstatic void child_report_pid(void *) ATF_DEFS_ATTRIBUTE_NORETURN; 685240116Smarcel 686240116Smarcelstatic 687240116Smarcelvoid 688240116Smarcelchild_report_pid(void *v ATF_DEFS_ATTRIBUTE_UNUSED) 689240116Smarcel{ 690240116Smarcel const pid_t pid = getpid(); 691240116Smarcel if (write(STDOUT_FILENO, &pid, sizeof(pid)) != sizeof(pid)) 692240116Smarcel abort(); 693240116Smarcel fprintf(stderr, "Reporting %d to parent\n", (int)getpid()); 694240116Smarcel exit(EXIT_SUCCESS); 695240116Smarcel} 696240116Smarcel 697240116SmarcelATF_TC(child_pid); 698240116SmarcelATF_TC_HEAD(child_pid, tc) 699240116Smarcel{ 700240116Smarcel atf_tc_set_md_var(tc, "descr", "Tests the correctness of the pid " 701240116Smarcel "stored in the child type"); 702240116Smarcel} 703240116SmarcelATF_TC_BODY(child_pid, tc) 704240116Smarcel{ 705240116Smarcel atf_process_stream_t outsb, errsb; 706240116Smarcel atf_process_child_t child; 707240116Smarcel atf_process_status_t status; 708240116Smarcel pid_t pid; 709240116Smarcel 710240116Smarcel RE(atf_process_stream_init_capture(&outsb)); 711240116Smarcel RE(atf_process_stream_init_inherit(&errsb)); 712240116Smarcel 713240116Smarcel RE(atf_process_fork(&child, child_report_pid, &outsb, &errsb, NULL)); 714240116Smarcel ATF_CHECK_EQ(read(atf_process_child_stdout(&child), &pid, sizeof(pid)), 715240116Smarcel sizeof(pid)); 716240116Smarcel printf("Expected PID: %d\n", (int)atf_process_child_pid(&child)); 717240116Smarcel printf("Actual PID: %d\n", (int)pid); 718240116Smarcel ATF_CHECK_EQ(atf_process_child_pid(&child), pid); 719240116Smarcel 720240116Smarcel RE(atf_process_child_wait(&child, &status)); 721240116Smarcel atf_process_status_fini(&status); 722240116Smarcel 723240116Smarcel atf_process_stream_fini(&outsb); 724240116Smarcel atf_process_stream_fini(&errsb); 725240116Smarcel} 726240116Smarcel 727240116Smarcelstatic 728240116Smarcelvoid 729240116Smarcelchild_loop(void *v ATF_DEFS_ATTRIBUTE_UNUSED) 730240116Smarcel{ 731240116Smarcel for (;;) 732240116Smarcel sleep(1); 733240116Smarcel} 734240116Smarcel 735240116Smarcelstatic 736240116Smarcelvoid 737240116Smarcelnop_signal(int sig ATF_DEFS_ATTRIBUTE_UNUSED) 738240116Smarcel{ 739240116Smarcel} 740240116Smarcel 741240116Smarcelstatic 742240116Smarcelvoid 743240116Smarcelchild_spawn_loop_and_wait_eintr(void *v ATF_DEFS_ATTRIBUTE_UNUSED) 744240116Smarcel{ 745240116Smarcel atf_process_child_t child; 746240116Smarcel atf_process_status_t status; 747240116Smarcel struct sigaction sighup, old_sighup; 748240116Smarcel 749240116Smarcel#define RE_ABORT(expr) \ 750240116Smarcel do { \ 751240116Smarcel atf_error_t _aux_err = expr; \ 752240116Smarcel if (atf_is_error(_aux_err)) { \ 753240116Smarcel atf_error_free(_aux_err); \ 754240116Smarcel abort(); \ 755240116Smarcel } \ 756240116Smarcel } while (0) 757240116Smarcel 758240116Smarcel { 759240116Smarcel atf_process_stream_t outsb, errsb; 760240116Smarcel 761240116Smarcel RE_ABORT(atf_process_stream_init_capture(&outsb)); 762240116Smarcel RE_ABORT(atf_process_stream_init_inherit(&errsb)); 763240116Smarcel RE_ABORT(atf_process_fork(&child, child_loop, &outsb, &errsb, NULL)); 764240116Smarcel atf_process_stream_fini(&outsb); 765240116Smarcel atf_process_stream_fini(&errsb); 766240116Smarcel } 767240116Smarcel 768240116Smarcel sighup.sa_handler = nop_signal; 769240116Smarcel sigemptyset(&sighup.sa_mask); 770240116Smarcel sighup.sa_flags = 0; 771240116Smarcel if (sigaction(SIGHUP, &sighup, &old_sighup) == -1) 772240116Smarcel abort(); 773240116Smarcel 774240116Smarcel printf("waiting\n"); 775240116Smarcel fflush(stdout); 776240116Smarcel 777240116Smarcel fprintf(stderr, "Child entering wait(2)\n"); 778240116Smarcel atf_error_t err = atf_process_child_wait(&child, &status); 779240116Smarcel fprintf(stderr, "Child's wait(2) terminated\n"); 780240116Smarcel if (!atf_is_error(err)) { 781240116Smarcel fprintf(stderr, "wait completed successfully (not interrupted)\n"); 782240116Smarcel abort(); 783240116Smarcel } 784240116Smarcel if (!atf_error_is(err, "libc")) { 785240116Smarcel fprintf(stderr, "wait did not raise libc_error\n"); 786240116Smarcel abort(); 787240116Smarcel } 788240116Smarcel if (atf_libc_error_code(err) != EINTR) { 789240116Smarcel fprintf(stderr, "libc_error is not EINTR\n"); 790240116Smarcel abort(); 791240116Smarcel } 792240116Smarcel atf_error_free(err); 793240116Smarcel 794240116Smarcel sigaction(SIGHUP, &old_sighup, NULL); 795240116Smarcel 796240116Smarcel fprintf(stderr, "Child is killing subchild\n"); 797240116Smarcel kill(atf_process_child_pid(&child), SIGTERM); 798240116Smarcel 799240116Smarcel RE_ABORT(atf_process_child_wait(&child, &status)); 800240116Smarcel atf_process_status_fini(&status); 801240116Smarcel 802240116Smarcel#undef RE_ABORT 803240116Smarcel 804240116Smarcel exit(EXIT_SUCCESS); 805240116Smarcel} 806240116Smarcel 807240116SmarcelATF_TC(child_wait_eintr); 808240116SmarcelATF_TC_HEAD(child_wait_eintr, tc) 809240116Smarcel{ 810240116Smarcel atf_tc_set_md_var(tc, "descr", "Tests the interruption of the wait " 811240116Smarcel "method by an external signal, and the return of " 812240116Smarcel "an EINTR error"); 813240116Smarcel atf_tc_set_md_var(tc, "timeout", "30"); 814240116Smarcel} 815240116SmarcelATF_TC_BODY(child_wait_eintr, tc) 816240116Smarcel{ 817240116Smarcel atf_process_child_t child; 818240116Smarcel atf_process_status_t status; 819240116Smarcel 820240116Smarcel { 821240116Smarcel atf_process_stream_t outsb, errsb; 822240116Smarcel 823240116Smarcel RE(atf_process_stream_init_capture(&outsb)); 824240116Smarcel RE(atf_process_stream_init_inherit(&errsb)); 825240116Smarcel RE(atf_process_fork(&child, child_spawn_loop_and_wait_eintr, 826240116Smarcel &outsb, &errsb, NULL)); 827240116Smarcel atf_process_stream_fini(&outsb); 828240116Smarcel atf_process_stream_fini(&errsb); 829240116Smarcel } 830240116Smarcel 831240116Smarcel { 832240116Smarcel /* Wait until the child process performs the wait call. This is 833240116Smarcel * racy, because the message we get from it is sent *before* 834240116Smarcel * doing the real system call... but I can't figure any other way 835240116Smarcel * to do this. */ 836240116Smarcel char buf[16]; 837240116Smarcel printf("Waiting for child to issue wait(2)\n"); 838240116Smarcel ATF_REQUIRE(read(atf_process_child_stdout(&child), buf, 839240116Smarcel sizeof(buf)) > 0); 840240116Smarcel sleep(1); 841240116Smarcel } 842240116Smarcel 843240116Smarcel printf("Interrupting child's wait(2) call\n"); 844240116Smarcel kill(atf_process_child_pid(&child), SIGHUP); 845240116Smarcel 846240116Smarcel printf("Waiting for child's completion\n"); 847240116Smarcel RE(atf_process_child_wait(&child, &status)); 848240116Smarcel ATF_REQUIRE(atf_process_status_exited(&status)); 849240116Smarcel ATF_REQUIRE_EQ(atf_process_status_exitstatus(&status), EXIT_SUCCESS); 850240116Smarcel atf_process_status_fini(&status); 851240116Smarcel} 852240116Smarcel 853240116Smarcel/* --------------------------------------------------------------------- 854240116Smarcel * Tests cases for the free functions. 855240116Smarcel * --------------------------------------------------------------------- */ 856240116Smarcel 857240116Smarcelstatic 858240116Smarcelvoid 859240116Smarceldo_exec(const atf_tc_t *tc, const char *helper_name, atf_process_status_t *s, 860240116Smarcel void (*prehook)(void)) 861240116Smarcel{ 862240116Smarcel atf_fs_path_t process_helpers; 863240116Smarcel const char *argv[3]; 864240116Smarcel 865240116Smarcel get_process_helpers_path(tc, true, &process_helpers); 866240116Smarcel 867240116Smarcel argv[0] = atf_fs_path_cstring(&process_helpers); 868240116Smarcel argv[1] = helper_name; 869240116Smarcel argv[2] = NULL; 870240116Smarcel printf("Executing %s %s\n", argv[0], argv[1]); 871240116Smarcel 872240116Smarcel RE(atf_process_exec_array(s, &process_helpers, argv, NULL, NULL, prehook)); 873240116Smarcel atf_fs_path_fini(&process_helpers); 874240116Smarcel} 875240116Smarcel 876240116Smarcelstatic 877240116Smarcelvoid 878240116Smarcelcheck_line(int fd, const char *exp) 879240116Smarcel{ 880258289Sjmmv char *line = atf_utils_readline(fd); 881258289Sjmmv ATF_CHECK(line != NULL); 882258289Sjmmv ATF_CHECK_STREQ_MSG(exp, line, "read: '%s', expected: '%s'", line, exp); 883258289Sjmmv free(line); 884240116Smarcel} 885240116Smarcel 886240116SmarcelATF_TC(exec_failure); 887240116SmarcelATF_TC_HEAD(exec_failure, tc) 888240116Smarcel{ 889240116Smarcel atf_tc_set_md_var(tc, "descr", "Tests execing a command"); 890240116Smarcel} 891240116SmarcelATF_TC_BODY(exec_failure, tc) 892240116Smarcel{ 893240116Smarcel atf_process_status_t status; 894240116Smarcel 895240116Smarcel do_exec(tc, "exit-failure", &status, NULL); 896240116Smarcel ATF_CHECK(atf_process_status_exited(&status)); 897240116Smarcel ATF_CHECK_EQ(atf_process_status_exitstatus(&status), EXIT_FAILURE); 898240116Smarcel atf_process_status_fini(&status); 899240116Smarcel} 900240116Smarcel 901240116SmarcelATF_TC(exec_list); 902240116SmarcelATF_TC_HEAD(exec_list, tc) 903240116Smarcel{ 904240116Smarcel atf_tc_set_md_var(tc, "descr", "Tests execing a command"); 905240116Smarcel} 906240116SmarcelATF_TC_BODY(exec_list, tc) 907240116Smarcel{ 908240116Smarcel atf_fs_path_t process_helpers; 909240116Smarcel atf_list_t argv; 910240116Smarcel atf_process_status_t status; 911240116Smarcel 912240116Smarcel RE(atf_list_init(&argv)); 913240116Smarcel 914240116Smarcel get_process_helpers_path(tc, true, &process_helpers); 915240116Smarcel atf_list_append(&argv, strdup(atf_fs_path_cstring(&process_helpers)), true); 916240116Smarcel atf_list_append(&argv, strdup("echo"), true); 917240116Smarcel atf_list_append(&argv, strdup("test-message"), true); 918240116Smarcel { 919240116Smarcel atf_fs_path_t outpath; 920240116Smarcel atf_process_stream_t outsb; 921240116Smarcel 922240116Smarcel RE(atf_fs_path_init_fmt(&outpath, "stdout")); 923240116Smarcel RE(atf_process_stream_init_redirect_path(&outsb, &outpath)); 924240116Smarcel RE(atf_process_exec_list(&status, &process_helpers, &argv, &outsb, 925240116Smarcel NULL, NULL)); 926240116Smarcel atf_process_stream_fini(&outsb); 927240116Smarcel atf_fs_path_fini(&outpath); 928240116Smarcel } 929240116Smarcel atf_list_fini(&argv); 930240116Smarcel 931240116Smarcel ATF_CHECK(atf_process_status_exited(&status)); 932240116Smarcel ATF_CHECK_EQ(atf_process_status_exitstatus(&status), EXIT_SUCCESS); 933240116Smarcel 934240116Smarcel { 935240116Smarcel int fd = open("stdout", O_RDONLY); 936240116Smarcel ATF_CHECK(fd != -1); 937240116Smarcel check_line(fd, "test-message"); 938240116Smarcel close(fd); 939240116Smarcel } 940240116Smarcel 941240116Smarcel atf_process_status_fini(&status); 942240116Smarcel atf_fs_path_fini(&process_helpers); 943240116Smarcel} 944240116Smarcel 945240116Smarcelstatic void 946240116Smarcelexit_early(void) 947240116Smarcel{ 948240116Smarcel exit(80); 949240116Smarcel} 950240116Smarcel 951240116SmarcelATF_TC(exec_prehook); 952240116SmarcelATF_TC_HEAD(exec_prehook, tc) 953240116Smarcel{ 954240116Smarcel atf_tc_set_md_var(tc, "descr", "Tests execing a command with a prehook"); 955240116Smarcel} 956240116SmarcelATF_TC_BODY(exec_prehook, tc) 957240116Smarcel{ 958240116Smarcel atf_process_status_t status; 959240116Smarcel 960240116Smarcel do_exec(tc, "exit-success", &status, exit_early); 961240116Smarcel ATF_CHECK(atf_process_status_exited(&status)); 962240116Smarcel ATF_CHECK_EQ(atf_process_status_exitstatus(&status), 80); 963240116Smarcel atf_process_status_fini(&status); 964240116Smarcel} 965240116Smarcel 966240116SmarcelATF_TC(exec_success); 967240116SmarcelATF_TC_HEAD(exec_success, tc) 968240116Smarcel{ 969240116Smarcel atf_tc_set_md_var(tc, "descr", "Tests execing a command"); 970240116Smarcel} 971240116SmarcelATF_TC_BODY(exec_success, tc) 972240116Smarcel{ 973240116Smarcel atf_process_status_t status; 974240116Smarcel 975240116Smarcel do_exec(tc, "exit-success", &status, NULL); 976240116Smarcel ATF_CHECK(atf_process_status_exited(&status)); 977240116Smarcel ATF_CHECK_EQ(atf_process_status_exitstatus(&status), EXIT_SUCCESS); 978240116Smarcel atf_process_status_fini(&status); 979240116Smarcel} 980240116Smarcel 981240116Smarcelstatic const int exit_v_null = 1; 982240116Smarcelstatic const int exit_v_notnull = 2; 983240116Smarcel 984240116Smarcelstatic 985240116Smarcelvoid 986240116Smarcelchild_cookie(void *v) 987240116Smarcel{ 988240116Smarcel if (v == NULL) 989240116Smarcel exit(exit_v_null); 990240116Smarcel else 991240116Smarcel exit(exit_v_notnull); 992240116Smarcel 993240116Smarcel UNREACHABLE; 994240116Smarcel} 995240116Smarcel 996240116SmarcelATF_TC(fork_cookie); 997240116SmarcelATF_TC_HEAD(fork_cookie, tc) 998240116Smarcel{ 999240116Smarcel atf_tc_set_md_var(tc, "descr", "Tests forking a child, with " 1000240116Smarcel "a null and non-null data cookie"); 1001240116Smarcel} 1002240116SmarcelATF_TC_BODY(fork_cookie, tc) 1003240116Smarcel{ 1004240116Smarcel atf_process_stream_t outsb, errsb; 1005240116Smarcel 1006240116Smarcel RE(atf_process_stream_init_inherit(&outsb)); 1007240116Smarcel RE(atf_process_stream_init_inherit(&errsb)); 1008240116Smarcel 1009240116Smarcel { 1010240116Smarcel atf_process_child_t child; 1011240116Smarcel atf_process_status_t status; 1012240116Smarcel 1013240116Smarcel RE(atf_process_fork(&child, child_cookie, &outsb, &errsb, NULL)); 1014240116Smarcel RE(atf_process_child_wait(&child, &status)); 1015240116Smarcel 1016240116Smarcel ATF_CHECK(atf_process_status_exited(&status)); 1017240116Smarcel ATF_CHECK_EQ(atf_process_status_exitstatus(&status), exit_v_null); 1018240116Smarcel 1019240116Smarcel atf_process_status_fini(&status); 1020240116Smarcel } 1021240116Smarcel 1022240116Smarcel { 1023240116Smarcel atf_process_child_t child; 1024240116Smarcel atf_process_status_t status; 1025240116Smarcel int dummy_int; 1026240116Smarcel 1027240116Smarcel RE(atf_process_fork(&child, child_cookie, &outsb, &errsb, &dummy_int)); 1028240116Smarcel RE(atf_process_child_wait(&child, &status)); 1029240116Smarcel 1030240116Smarcel ATF_CHECK(atf_process_status_exited(&status)); 1031240116Smarcel ATF_CHECK_EQ(atf_process_status_exitstatus(&status), exit_v_notnull); 1032240116Smarcel 1033240116Smarcel atf_process_status_fini(&status); 1034240116Smarcel } 1035240116Smarcel 1036240116Smarcel atf_process_stream_fini(&errsb); 1037240116Smarcel atf_process_stream_fini(&outsb); 1038240116Smarcel} 1039240116Smarcel 1040240116Smarcel#define TC_FORK_STREAMS(outlc, outuc, errlc, erruc) \ 1041240116Smarcel ATF_TC(fork_out_ ## outlc ## _err_ ## errlc); \ 1042240116Smarcel ATF_TC_HEAD(fork_out_ ## outlc ## _err_ ## errlc, tc) \ 1043240116Smarcel { \ 1044240116Smarcel atf_tc_set_md_var(tc, "descr", "Tests forking a child, with " \ 1045240116Smarcel "stdout " #outlc " and stderr " #errlc); \ 1046240116Smarcel } \ 1047240116Smarcel ATF_TC_BODY(fork_out_ ## outlc ## _err_ ## errlc, tc) \ 1048240116Smarcel { \ 1049240116Smarcel struct outlc ## _stream out = outuc ## _STREAM(stdout_type); \ 1050240116Smarcel struct errlc ## _stream err = erruc ## _STREAM(stderr_type); \ 1051240116Smarcel do_fork(&out.m_base, &out, &err.m_base, &err); \ 1052240116Smarcel } 1053240116Smarcel 1054240116SmarcelTC_FORK_STREAMS(capture, CAPTURE, capture, CAPTURE); 1055240116SmarcelTC_FORK_STREAMS(capture, CAPTURE, connect, CONNECT); 1056240116SmarcelTC_FORK_STREAMS(capture, CAPTURE, default, DEFAULT); 1057240116SmarcelTC_FORK_STREAMS(capture, CAPTURE, inherit, INHERIT); 1058240116SmarcelTC_FORK_STREAMS(capture, CAPTURE, redirect_fd, REDIRECT_FD); 1059240116SmarcelTC_FORK_STREAMS(capture, CAPTURE, redirect_path, REDIRECT_PATH); 1060240116SmarcelTC_FORK_STREAMS(connect, CONNECT, capture, CAPTURE); 1061240116SmarcelTC_FORK_STREAMS(connect, CONNECT, connect, CONNECT); 1062240116SmarcelTC_FORK_STREAMS(connect, CONNECT, default, DEFAULT); 1063240116SmarcelTC_FORK_STREAMS(connect, CONNECT, inherit, INHERIT); 1064240116SmarcelTC_FORK_STREAMS(connect, CONNECT, redirect_fd, REDIRECT_FD); 1065240116SmarcelTC_FORK_STREAMS(connect, CONNECT, redirect_path, REDIRECT_PATH); 1066240116SmarcelTC_FORK_STREAMS(default, DEFAULT, capture, CAPTURE); 1067240116SmarcelTC_FORK_STREAMS(default, DEFAULT, connect, CONNECT); 1068240116SmarcelTC_FORK_STREAMS(default, DEFAULT, default, DEFAULT); 1069240116SmarcelTC_FORK_STREAMS(default, DEFAULT, inherit, INHERIT); 1070240116SmarcelTC_FORK_STREAMS(default, DEFAULT, redirect_fd, REDIRECT_FD); 1071240116SmarcelTC_FORK_STREAMS(default, DEFAULT, redirect_path, REDIRECT_PATH); 1072240116SmarcelTC_FORK_STREAMS(inherit, INHERIT, capture, CAPTURE); 1073240116SmarcelTC_FORK_STREAMS(inherit, INHERIT, connect, CONNECT); 1074240116SmarcelTC_FORK_STREAMS(inherit, INHERIT, default, DEFAULT); 1075240116SmarcelTC_FORK_STREAMS(inherit, INHERIT, inherit, INHERIT); 1076240116SmarcelTC_FORK_STREAMS(inherit, INHERIT, redirect_fd, REDIRECT_FD); 1077240116SmarcelTC_FORK_STREAMS(inherit, INHERIT, redirect_path, REDIRECT_PATH); 1078240116SmarcelTC_FORK_STREAMS(redirect_fd, REDIRECT_FD, capture, CAPTURE); 1079240116SmarcelTC_FORK_STREAMS(redirect_fd, REDIRECT_FD, connect, CONNECT); 1080240116SmarcelTC_FORK_STREAMS(redirect_fd, REDIRECT_FD, default, DEFAULT); 1081240116SmarcelTC_FORK_STREAMS(redirect_fd, REDIRECT_FD, inherit, INHERIT); 1082240116SmarcelTC_FORK_STREAMS(redirect_fd, REDIRECT_FD, redirect_fd, REDIRECT_FD); 1083240116SmarcelTC_FORK_STREAMS(redirect_fd, REDIRECT_FD, redirect_path, REDIRECT_PATH); 1084240116SmarcelTC_FORK_STREAMS(redirect_path, REDIRECT_PATH, capture, CAPTURE); 1085240116SmarcelTC_FORK_STREAMS(redirect_path, REDIRECT_PATH, connect, CONNECT); 1086240116SmarcelTC_FORK_STREAMS(redirect_path, REDIRECT_PATH, default, DEFAULT); 1087240116SmarcelTC_FORK_STREAMS(redirect_path, REDIRECT_PATH, inherit, INHERIT); 1088240116SmarcelTC_FORK_STREAMS(redirect_path, REDIRECT_PATH, redirect_fd, REDIRECT_FD); 1089240116SmarcelTC_FORK_STREAMS(redirect_path, REDIRECT_PATH, redirect_path, REDIRECT_PATH); 1090240116Smarcel 1091240116Smarcel#undef TC_FORK_STREAMS 1092240116Smarcel 1093240116Smarcel/* --------------------------------------------------------------------- 1094240116Smarcel * Main. 1095240116Smarcel * --------------------------------------------------------------------- */ 1096240116Smarcel 1097240116SmarcelATF_TP_ADD_TCS(tp) 1098240116Smarcel{ 1099240116Smarcel /* Add the tests for the "stream" type. */ 1100240116Smarcel ATF_TP_ADD_TC(tp, stream_init_capture); 1101240116Smarcel ATF_TP_ADD_TC(tp, stream_init_connect); 1102240116Smarcel ATF_TP_ADD_TC(tp, stream_init_inherit); 1103240116Smarcel ATF_TP_ADD_TC(tp, stream_init_redirect_fd); 1104240116Smarcel ATF_TP_ADD_TC(tp, stream_init_redirect_path); 1105240116Smarcel 1106240116Smarcel /* Add the tests for the "status" type. */ 1107240116Smarcel ATF_TP_ADD_TC(tp, status_exited); 1108240116Smarcel ATF_TP_ADD_TC(tp, status_signaled); 1109240116Smarcel ATF_TP_ADD_TC(tp, status_coredump); 1110240116Smarcel 1111240116Smarcel /* Add the tests for the "child" type. */ 1112240116Smarcel ATF_TP_ADD_TC(tp, child_pid); 1113240116Smarcel ATF_TP_ADD_TC(tp, child_wait_eintr); 1114240116Smarcel 1115240116Smarcel /* Add the tests for the free functions. */ 1116240116Smarcel ATF_TP_ADD_TC(tp, exec_failure); 1117240116Smarcel ATF_TP_ADD_TC(tp, exec_list); 1118240116Smarcel ATF_TP_ADD_TC(tp, exec_prehook); 1119240116Smarcel ATF_TP_ADD_TC(tp, exec_success); 1120240116Smarcel ATF_TP_ADD_TC(tp, fork_cookie); 1121240116Smarcel ATF_TP_ADD_TC(tp, fork_out_capture_err_capture); 1122240116Smarcel ATF_TP_ADD_TC(tp, fork_out_capture_err_connect); 1123240116Smarcel ATF_TP_ADD_TC(tp, fork_out_capture_err_default); 1124240116Smarcel ATF_TP_ADD_TC(tp, fork_out_capture_err_inherit); 1125240116Smarcel ATF_TP_ADD_TC(tp, fork_out_capture_err_redirect_fd); 1126240116Smarcel ATF_TP_ADD_TC(tp, fork_out_capture_err_redirect_path); 1127240116Smarcel ATF_TP_ADD_TC(tp, fork_out_connect_err_capture); 1128240116Smarcel ATF_TP_ADD_TC(tp, fork_out_connect_err_connect); 1129240116Smarcel ATF_TP_ADD_TC(tp, fork_out_connect_err_default); 1130240116Smarcel ATF_TP_ADD_TC(tp, fork_out_connect_err_inherit); 1131240116Smarcel ATF_TP_ADD_TC(tp, fork_out_connect_err_redirect_fd); 1132240116Smarcel ATF_TP_ADD_TC(tp, fork_out_connect_err_redirect_path); 1133240116Smarcel ATF_TP_ADD_TC(tp, fork_out_default_err_capture); 1134240116Smarcel ATF_TP_ADD_TC(tp, fork_out_default_err_connect); 1135240116Smarcel ATF_TP_ADD_TC(tp, fork_out_default_err_default); 1136240116Smarcel ATF_TP_ADD_TC(tp, fork_out_default_err_inherit); 1137240116Smarcel ATF_TP_ADD_TC(tp, fork_out_default_err_redirect_fd); 1138240116Smarcel ATF_TP_ADD_TC(tp, fork_out_default_err_redirect_path); 1139240116Smarcel ATF_TP_ADD_TC(tp, fork_out_inherit_err_capture); 1140240116Smarcel ATF_TP_ADD_TC(tp, fork_out_inherit_err_connect); 1141240116Smarcel ATF_TP_ADD_TC(tp, fork_out_inherit_err_default); 1142240116Smarcel ATF_TP_ADD_TC(tp, fork_out_inherit_err_inherit); 1143240116Smarcel ATF_TP_ADD_TC(tp, fork_out_inherit_err_redirect_fd); 1144240116Smarcel ATF_TP_ADD_TC(tp, fork_out_inherit_err_redirect_path); 1145240116Smarcel ATF_TP_ADD_TC(tp, fork_out_redirect_fd_err_capture); 1146240116Smarcel ATF_TP_ADD_TC(tp, fork_out_redirect_fd_err_connect); 1147240116Smarcel ATF_TP_ADD_TC(tp, fork_out_redirect_fd_err_default); 1148240116Smarcel ATF_TP_ADD_TC(tp, fork_out_redirect_fd_err_inherit); 1149240116Smarcel ATF_TP_ADD_TC(tp, fork_out_redirect_fd_err_redirect_fd); 1150240116Smarcel ATF_TP_ADD_TC(tp, fork_out_redirect_fd_err_redirect_path); 1151240116Smarcel ATF_TP_ADD_TC(tp, fork_out_redirect_path_err_capture); 1152240116Smarcel ATF_TP_ADD_TC(tp, fork_out_redirect_path_err_connect); 1153240116Smarcel ATF_TP_ADD_TC(tp, fork_out_redirect_path_err_default); 1154240116Smarcel ATF_TP_ADD_TC(tp, fork_out_redirect_path_err_inherit); 1155240116Smarcel ATF_TP_ADD_TC(tp, fork_out_redirect_path_err_redirect_fd); 1156240116Smarcel ATF_TP_ADD_TC(tp, fork_out_redirect_path_err_redirect_path); 1157240116Smarcel 1158240116Smarcel return atf_no_error(); 1159240116Smarcel} 1160