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