1275988Sngie/* Copyright (c) 2010 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 24275988Sngie * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 25240116Smarcel 26275988Sngie#include "atf-c/utils.h" 27275988Sngie 28260029Sjmmv#include <sys/stat.h> 29260029Sjmmv#include <sys/wait.h> 30260029Sjmmv 31260029Sjmmv#include <fcntl.h> 32260029Sjmmv#include <stddef.h> 33260029Sjmmv#include <stdio.h> 34240116Smarcel#include <stdlib.h> 35240116Smarcel#include <string.h> 36260029Sjmmv#include <unistd.h> 37240116Smarcel 38240116Smarcel#include <atf-c.h> 39240116Smarcel 40275988Sngie#include "atf-c/detail/dynstr.h" 41275988Sngie#include "atf-c/detail/test_helpers.h" 42240116Smarcel 43260029Sjmmv/** Reads the contents of a file into a buffer. 44260029Sjmmv * 45260029Sjmmv * Up to buflen-1 characters are read into buffer. If this function returns, 46260029Sjmmv * the contents read into the buffer are guaranteed to be nul-terminated. 47260029Sjmmv * Note, however, that if the file contains any nul characters itself, 48260029Sjmmv * comparing it "as a string" will not work. 49260029Sjmmv * 50260029Sjmmv * \param path The file to be read, which must exist. 51260029Sjmmv * \param buffer Buffer into which to store the file contents. 52260029Sjmmv * \param buflen Size of the target buffer. 53260029Sjmmv * 54260029Sjmmv * \return The count of bytes read. */ 55260029Sjmmvstatic ssize_t 56260029Sjmmvread_file(const char *path, void *const buffer, const size_t buflen) 57240116Smarcel{ 58260029Sjmmv const int fd = open(path, O_RDONLY); 59260029Sjmmv ATF_REQUIRE_MSG(fd != -1, "Cannot open %s", path); 60260029Sjmmv const ssize_t length = read(fd, buffer, buflen - 1); 61260029Sjmmv close(fd); 62260029Sjmmv ATF_REQUIRE(length != -1); 63260029Sjmmv ((char *)buffer)[length] = '\0'; 64260029Sjmmv return length; 65260029Sjmmv} 66260029Sjmmv 67260029SjmmvATF_TC_WITHOUT_HEAD(cat_file__empty); 68260029SjmmvATF_TC_BODY(cat_file__empty, tc) 69260029Sjmmv{ 70260029Sjmmv atf_utils_create_file("file.txt", "%s", ""); 71260029Sjmmv atf_utils_redirect(STDOUT_FILENO, "captured.txt"); 72260029Sjmmv atf_utils_cat_file("file.txt", "PREFIX"); 73260029Sjmmv fflush(stdout); 74260029Sjmmv close(STDOUT_FILENO); 75260029Sjmmv 76260029Sjmmv char buffer[1024]; 77260029Sjmmv read_file("captured.txt", buffer, sizeof(buffer)); 78260029Sjmmv ATF_REQUIRE_STREQ("", buffer); 79260029Sjmmv} 80260029Sjmmv 81260029SjmmvATF_TC_WITHOUT_HEAD(cat_file__one_line); 82260029SjmmvATF_TC_BODY(cat_file__one_line, tc) 83260029Sjmmv{ 84260029Sjmmv atf_utils_create_file("file.txt", "This is a single line\n"); 85260029Sjmmv atf_utils_redirect(STDOUT_FILENO, "captured.txt"); 86260029Sjmmv atf_utils_cat_file("file.txt", "PREFIX"); 87260029Sjmmv fflush(stdout); 88260029Sjmmv close(STDOUT_FILENO); 89260029Sjmmv 90260029Sjmmv char buffer[1024]; 91260029Sjmmv read_file("captured.txt", buffer, sizeof(buffer)); 92260029Sjmmv ATF_REQUIRE_STREQ("PREFIXThis is a single line\n", buffer); 93260029Sjmmv} 94260029Sjmmv 95260029SjmmvATF_TC_WITHOUT_HEAD(cat_file__several_lines); 96260029SjmmvATF_TC_BODY(cat_file__several_lines, tc) 97260029Sjmmv{ 98260029Sjmmv atf_utils_create_file("file.txt", "First\nSecond line\nAnd third\n"); 99260029Sjmmv atf_utils_redirect(STDOUT_FILENO, "captured.txt"); 100260029Sjmmv atf_utils_cat_file("file.txt", ">"); 101260029Sjmmv fflush(stdout); 102260029Sjmmv close(STDOUT_FILENO); 103260029Sjmmv 104260029Sjmmv char buffer[1024]; 105260029Sjmmv read_file("captured.txt", buffer, sizeof(buffer)); 106260029Sjmmv ATF_REQUIRE_STREQ(">First\n>Second line\n>And third\n", buffer); 107260029Sjmmv} 108260029Sjmmv 109260029SjmmvATF_TC_WITHOUT_HEAD(cat_file__no_newline_eof); 110260029SjmmvATF_TC_BODY(cat_file__no_newline_eof, tc) 111260029Sjmmv{ 112260029Sjmmv atf_utils_create_file("file.txt", "Foo\n bar baz"); 113260029Sjmmv atf_utils_redirect(STDOUT_FILENO, "captured.txt"); 114260029Sjmmv atf_utils_cat_file("file.txt", "PREFIX"); 115260029Sjmmv fflush(stdout); 116260029Sjmmv close(STDOUT_FILENO); 117260029Sjmmv 118260029Sjmmv char buffer[1024]; 119260029Sjmmv read_file("captured.txt", buffer, sizeof(buffer)); 120260029Sjmmv ATF_REQUIRE_STREQ("PREFIXFoo\nPREFIX bar baz", buffer); 121260029Sjmmv} 122260029Sjmmv 123260029SjmmvATF_TC_WITHOUT_HEAD(compare_file__empty__match); 124260029SjmmvATF_TC_BODY(compare_file__empty__match, tc) 125260029Sjmmv{ 126260029Sjmmv atf_utils_create_file("test.txt", "%s", ""); 127260029Sjmmv ATF_REQUIRE(atf_utils_compare_file("test.txt", "")); 128260029Sjmmv} 129260029Sjmmv 130260029SjmmvATF_TC_WITHOUT_HEAD(compare_file__empty__not_match); 131260029SjmmvATF_TC_BODY(compare_file__empty__not_match, tc) 132260029Sjmmv{ 133260029Sjmmv atf_utils_create_file("test.txt", "%s", ""); 134260029Sjmmv ATF_REQUIRE(!atf_utils_compare_file("test.txt", "\n")); 135260029Sjmmv ATF_REQUIRE(!atf_utils_compare_file("test.txt", "foo")); 136260029Sjmmv ATF_REQUIRE(!atf_utils_compare_file("test.txt", " ")); 137260029Sjmmv} 138260029Sjmmv 139260029SjmmvATF_TC_WITHOUT_HEAD(compare_file__short__match); 140260029SjmmvATF_TC_BODY(compare_file__short__match, tc) 141260029Sjmmv{ 142260029Sjmmv atf_utils_create_file("test.txt", "this is a short file"); 143260029Sjmmv ATF_REQUIRE(atf_utils_compare_file("test.txt", "this is a short file")); 144260029Sjmmv} 145260029Sjmmv 146260029SjmmvATF_TC_WITHOUT_HEAD(compare_file__short__not_match); 147260029SjmmvATF_TC_BODY(compare_file__short__not_match, tc) 148260029Sjmmv{ 149260029Sjmmv atf_utils_create_file("test.txt", "this is a short file"); 150260029Sjmmv ATF_REQUIRE(!atf_utils_compare_file("test.txt", "")); 151260029Sjmmv ATF_REQUIRE(!atf_utils_compare_file("test.txt", "\n")); 152260029Sjmmv ATF_REQUIRE(!atf_utils_compare_file("test.txt", "this is a Short file")); 153260029Sjmmv ATF_REQUIRE(!atf_utils_compare_file("test.txt", "this is a short fil")); 154260029Sjmmv ATF_REQUIRE(!atf_utils_compare_file("test.txt", "this is a short file ")); 155260029Sjmmv} 156260029Sjmmv 157260029SjmmvATF_TC_WITHOUT_HEAD(compare_file__long__match); 158260029SjmmvATF_TC_BODY(compare_file__long__match, tc) 159260029Sjmmv{ 160260029Sjmmv char long_contents[3456]; 161260029Sjmmv size_t i = 0; 162260029Sjmmv for (; i < sizeof(long_contents) - 1; i++) 163260029Sjmmv long_contents[i] = '0' + (i % 10); 164260029Sjmmv long_contents[i] = '\0'; 165260029Sjmmv atf_utils_create_file("test.txt", "%s", long_contents); 166260029Sjmmv 167260029Sjmmv ATF_REQUIRE(atf_utils_compare_file("test.txt", long_contents)); 168260029Sjmmv} 169260029Sjmmv 170260029SjmmvATF_TC_WITHOUT_HEAD(compare_file__long__not_match); 171260029SjmmvATF_TC_BODY(compare_file__long__not_match, tc) 172260029Sjmmv{ 173260029Sjmmv char long_contents[3456]; 174260029Sjmmv size_t i = 0; 175260029Sjmmv for (; i < sizeof(long_contents) - 1; i++) 176260029Sjmmv long_contents[i] = '0' + (i % 10); 177260029Sjmmv long_contents[i] = '\0'; 178260029Sjmmv atf_utils_create_file("test.txt", "%s", long_contents); 179260029Sjmmv 180260029Sjmmv ATF_REQUIRE(!atf_utils_compare_file("test.txt", "")); 181260029Sjmmv ATF_REQUIRE(!atf_utils_compare_file("test.txt", "\n")); 182260029Sjmmv ATF_REQUIRE(!atf_utils_compare_file("test.txt", "0123456789")); 183260029Sjmmv long_contents[i - 1] = 'Z'; 184260029Sjmmv ATF_REQUIRE(!atf_utils_compare_file("test.txt", long_contents)); 185260029Sjmmv} 186260029Sjmmv 187260029SjmmvATF_TC_WITHOUT_HEAD(copy_file__empty); 188260029SjmmvATF_TC_BODY(copy_file__empty, tc) 189260029Sjmmv{ 190260029Sjmmv atf_utils_create_file("src.txt", "%s", ""); 191260029Sjmmv ATF_REQUIRE(chmod("src.txt", 0520) != -1); 192260029Sjmmv 193260029Sjmmv atf_utils_copy_file("src.txt", "dest.txt"); 194260029Sjmmv ATF_REQUIRE(atf_utils_compare_file("dest.txt", "")); 195260029Sjmmv struct stat sb; 196260029Sjmmv ATF_REQUIRE(stat("dest.txt", &sb) != -1); 197260029Sjmmv ATF_REQUIRE_EQ(0520, sb.st_mode & 0xfff); 198260029Sjmmv} 199260029Sjmmv 200260029SjmmvATF_TC_WITHOUT_HEAD(copy_file__some_contents); 201260029SjmmvATF_TC_BODY(copy_file__some_contents, tc) 202260029Sjmmv{ 203260029Sjmmv atf_utils_create_file("src.txt", "This is a\ntest file\n"); 204260029Sjmmv atf_utils_copy_file("src.txt", "dest.txt"); 205260029Sjmmv ATF_REQUIRE(atf_utils_compare_file("dest.txt", "This is a\ntest file\n")); 206260029Sjmmv} 207260029Sjmmv 208260029SjmmvATF_TC_WITHOUT_HEAD(create_file); 209260029SjmmvATF_TC_BODY(create_file, tc) 210260029Sjmmv{ 211260029Sjmmv atf_utils_create_file("test.txt", "This is a test with %d", 12345); 212260029Sjmmv 213260029Sjmmv char buffer[128]; 214260029Sjmmv read_file("test.txt", buffer, sizeof(buffer)); 215260029Sjmmv ATF_REQUIRE_STREQ("This is a test with 12345", buffer); 216260029Sjmmv} 217260029Sjmmv 218260029SjmmvATF_TC_WITHOUT_HEAD(file_exists); 219260029SjmmvATF_TC_BODY(file_exists, tc) 220260029Sjmmv{ 221260029Sjmmv atf_utils_create_file("test.txt", "foo"); 222260029Sjmmv 223260029Sjmmv ATF_REQUIRE( atf_utils_file_exists("test.txt")); 224260029Sjmmv ATF_REQUIRE( atf_utils_file_exists("./test.txt")); 225260029Sjmmv ATF_REQUIRE(!atf_utils_file_exists("./test.tx")); 226260029Sjmmv ATF_REQUIRE(!atf_utils_file_exists("test.txt2")); 227260029Sjmmv} 228260029Sjmmv 229260029SjmmvATF_TC_WITHOUT_HEAD(fork); 230260029SjmmvATF_TC_BODY(fork, tc) 231260029Sjmmv{ 232260029Sjmmv fprintf(stdout, "Should not get into child\n"); 233260029Sjmmv fprintf(stderr, "Should not get into child\n"); 234260029Sjmmv pid_t pid = atf_utils_fork(); 235260029Sjmmv if (pid == 0) { 236260029Sjmmv fprintf(stdout, "Child stdout\n"); 237260029Sjmmv fprintf(stderr, "Child stderr\n"); 238260029Sjmmv exit(EXIT_SUCCESS); 239260029Sjmmv } 240260029Sjmmv 241260029Sjmmv int status; 242260029Sjmmv ATF_REQUIRE(waitpid(pid, &status, 0) != -1); 243260029Sjmmv ATF_REQUIRE(WIFEXITED(status)); 244260029Sjmmv ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); 245260029Sjmmv 246275988Sngie atf_dynstr_t out_name; 247275988Sngie RE(atf_dynstr_init_fmt(&out_name, "atf_utils_fork_%d_out.txt", (int)pid)); 248275988Sngie atf_dynstr_t err_name; 249275988Sngie RE(atf_dynstr_init_fmt(&err_name, "atf_utils_fork_%d_err.txt", (int)pid)); 250275988Sngie 251260029Sjmmv char buffer[1024]; 252275988Sngie read_file(atf_dynstr_cstring(&out_name), buffer, sizeof(buffer)); 253260029Sjmmv ATF_REQUIRE_STREQ("Child stdout\n", buffer); 254275988Sngie read_file(atf_dynstr_cstring(&err_name), buffer, sizeof(buffer)); 255260029Sjmmv ATF_REQUIRE_STREQ("Child stderr\n", buffer); 256275988Sngie 257275988Sngie atf_dynstr_fini(&err_name); 258275988Sngie atf_dynstr_fini(&out_name); 259260029Sjmmv} 260260029Sjmmv 261260029SjmmvATF_TC_WITHOUT_HEAD(free_charpp__empty); 262260029SjmmvATF_TC_BODY(free_charpp__empty, tc) 263260029Sjmmv{ 264240116Smarcel char **array = malloc(sizeof(char *) * 1); 265240116Smarcel array[0] = NULL; 266240116Smarcel 267240116Smarcel atf_utils_free_charpp(array); 268240116Smarcel} 269240116Smarcel 270260029SjmmvATF_TC_WITHOUT_HEAD(free_charpp__some); 271260029SjmmvATF_TC_BODY(free_charpp__some, tc) 272240116Smarcel{ 273240116Smarcel char **array = malloc(sizeof(char *) * 4); 274240116Smarcel array[0] = strdup("first"); 275240116Smarcel array[1] = strdup("second"); 276240116Smarcel array[2] = strdup("third"); 277240116Smarcel array[3] = NULL; 278240116Smarcel 279240116Smarcel atf_utils_free_charpp(array); 280240116Smarcel} 281240116Smarcel 282260029SjmmvATF_TC_WITHOUT_HEAD(grep_file); 283260029SjmmvATF_TC_BODY(grep_file, tc) 284260029Sjmmv{ 285260029Sjmmv atf_utils_create_file("test.txt", "line1\nthe second line\naaaabbbb\n"); 286260029Sjmmv 287260029Sjmmv ATF_CHECK(atf_utils_grep_file("line1", "test.txt")); 288260029Sjmmv ATF_CHECK(atf_utils_grep_file("line%d", "test.txt", 1)); 289260029Sjmmv ATF_CHECK(atf_utils_grep_file("second line", "test.txt")); 290260029Sjmmv ATF_CHECK(atf_utils_grep_file("aa.*bb", "test.txt")); 291260029Sjmmv ATF_CHECK(!atf_utils_grep_file("foo", "test.txt")); 292260029Sjmmv ATF_CHECK(!atf_utils_grep_file("bar", "test.txt")); 293260029Sjmmv ATF_CHECK(!atf_utils_grep_file("aaaaa", "test.txt")); 294260029Sjmmv} 295260029Sjmmv 296260029SjmmvATF_TC_WITHOUT_HEAD(grep_string); 297260029SjmmvATF_TC_BODY(grep_string, tc) 298260029Sjmmv{ 299260029Sjmmv const char *str = "a string - aaaabbbb"; 300260029Sjmmv ATF_CHECK(atf_utils_grep_string("a string", str)); 301260029Sjmmv ATF_CHECK(atf_utils_grep_string("^a string", str)); 302260029Sjmmv ATF_CHECK(atf_utils_grep_string("aaaabbbb$", str)); 303260029Sjmmv ATF_CHECK(atf_utils_grep_string("a%s*bb", str, "a.")); 304260029Sjmmv ATF_CHECK(!atf_utils_grep_string("foo", str)); 305260029Sjmmv ATF_CHECK(!atf_utils_grep_string("bar", str)); 306260029Sjmmv ATF_CHECK(!atf_utils_grep_string("aaaaa", str)); 307260029Sjmmv} 308260029Sjmmv 309260029SjmmvATF_TC_WITHOUT_HEAD(readline__none); 310260029SjmmvATF_TC_BODY(readline__none, tc) 311260029Sjmmv{ 312260029Sjmmv atf_utils_create_file("empty.txt", "%s", ""); 313260029Sjmmv 314260029Sjmmv const int fd = open("empty.txt", O_RDONLY); 315260029Sjmmv ATF_REQUIRE(fd != -1); 316260029Sjmmv ATF_REQUIRE(atf_utils_readline(fd) == NULL); 317260029Sjmmv close(fd); 318260029Sjmmv} 319260029Sjmmv 320260029SjmmvATF_TC_WITHOUT_HEAD(readline__some); 321260029SjmmvATF_TC_BODY(readline__some, tc) 322260029Sjmmv{ 323260029Sjmmv const char *l1 = "First line with % formatting % characters %"; 324260029Sjmmv const char *l2 = "Second line; much longer than the first one"; 325260029Sjmmv const char *l3 = "Last line, without terminator"; 326260029Sjmmv 327260029Sjmmv atf_utils_create_file("test.txt", "%s\n%s\n%s", l1, l2, l3); 328260029Sjmmv 329260029Sjmmv const int fd = open("test.txt", O_RDONLY); 330260029Sjmmv ATF_REQUIRE(fd != -1); 331260029Sjmmv 332260029Sjmmv char *line; 333260029Sjmmv 334260029Sjmmv line = atf_utils_readline(fd); 335260029Sjmmv ATF_REQUIRE_STREQ(l1, line); 336260029Sjmmv free(line); 337260029Sjmmv 338260029Sjmmv line = atf_utils_readline(fd); 339260029Sjmmv ATF_REQUIRE_STREQ(l2, line); 340260029Sjmmv free(line); 341260029Sjmmv 342260029Sjmmv line = atf_utils_readline(fd); 343260029Sjmmv ATF_REQUIRE_STREQ(l3, line); 344260029Sjmmv free(line); 345260029Sjmmv 346260029Sjmmv close(fd); 347260029Sjmmv} 348260029Sjmmv 349260029SjmmvATF_TC_WITHOUT_HEAD(redirect__stdout); 350260029SjmmvATF_TC_BODY(redirect__stdout, tc) 351260029Sjmmv{ 352260029Sjmmv printf("Buffer this"); 353260029Sjmmv atf_utils_redirect(STDOUT_FILENO, "captured.txt"); 354260029Sjmmv printf("The printed message"); 355260029Sjmmv fflush(stdout); 356260029Sjmmv 357260029Sjmmv char buffer[1024]; 358260029Sjmmv read_file("captured.txt", buffer, sizeof(buffer)); 359260029Sjmmv ATF_REQUIRE_STREQ("The printed message", buffer); 360260029Sjmmv} 361260029Sjmmv 362260029SjmmvATF_TC_WITHOUT_HEAD(redirect__stderr); 363260029SjmmvATF_TC_BODY(redirect__stderr, tc) 364260029Sjmmv{ 365260029Sjmmv fprintf(stderr, "Buffer this"); 366260029Sjmmv atf_utils_redirect(STDERR_FILENO, "captured.txt"); 367260029Sjmmv fprintf(stderr, "The printed message"); 368260029Sjmmv fflush(stderr); 369260029Sjmmv 370260029Sjmmv char buffer[1024]; 371260029Sjmmv read_file("captured.txt", buffer, sizeof(buffer)); 372260029Sjmmv ATF_REQUIRE_STREQ("The printed message", buffer); 373260029Sjmmv} 374260029Sjmmv 375260029SjmmvATF_TC_WITHOUT_HEAD(redirect__other); 376260029SjmmvATF_TC_BODY(redirect__other, tc) 377260029Sjmmv{ 378260029Sjmmv const char *message = "Foo bar\nbaz\n"; 379260029Sjmmv atf_utils_redirect(15, "captured.txt"); 380260029Sjmmv ATF_REQUIRE(write(15, message, strlen(message)) != -1); 381260029Sjmmv close(15); 382260029Sjmmv 383260029Sjmmv char buffer[1024]; 384260029Sjmmv read_file("captured.txt", buffer, sizeof(buffer)); 385260029Sjmmv ATF_REQUIRE_STREQ(message, buffer); 386260029Sjmmv} 387260029Sjmmv 388260029Sjmmvstatic void 389260029Sjmmvfork_and_wait(const int exitstatus, const char* expout, const char* experr) 390260029Sjmmv{ 391260029Sjmmv const pid_t pid = atf_utils_fork(); 392275988Sngie ATF_REQUIRE(pid != -1); 393260029Sjmmv if (pid == 0) { 394260029Sjmmv fprintf(stdout, "Some output\n"); 395260029Sjmmv fprintf(stderr, "Some error\n"); 396260029Sjmmv exit(123); 397260029Sjmmv } 398260029Sjmmv atf_utils_wait(pid, exitstatus, expout, experr); 399260029Sjmmv exit(EXIT_SUCCESS); 400260029Sjmmv} 401260029Sjmmv 402260029SjmmvATF_TC_WITHOUT_HEAD(wait__ok); 403260029SjmmvATF_TC_BODY(wait__ok, tc) 404260029Sjmmv{ 405260029Sjmmv const pid_t control = fork(); 406260029Sjmmv ATF_REQUIRE(control != -1); 407260029Sjmmv if (control == 0) 408260029Sjmmv fork_and_wait(123, "Some output\n", "Some error\n"); 409260029Sjmmv else { 410260029Sjmmv int status; 411260029Sjmmv ATF_REQUIRE(waitpid(control, &status, 0) != -1); 412260029Sjmmv ATF_REQUIRE(WIFEXITED(status)); 413260029Sjmmv ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); 414260029Sjmmv } 415260029Sjmmv} 416260029Sjmmv 417275988SngieATF_TC_WITHOUT_HEAD(wait__ok_nested); 418275988SngieATF_TC_BODY(wait__ok_nested, tc) 419275988Sngie{ 420275988Sngie const pid_t parent = atf_utils_fork(); 421275988Sngie ATF_REQUIRE(parent != -1); 422275988Sngie if (parent == 0) { 423275988Sngie const pid_t child = atf_utils_fork(); 424275988Sngie ATF_REQUIRE(child != -1); 425275988Sngie if (child == 0) { 426275988Sngie fflush(stderr); 427275988Sngie fprintf(stdout, "Child output\n"); 428275988Sngie fflush(stdout); 429275988Sngie fprintf(stderr, "Child error\n"); 430275988Sngie exit(50); 431275988Sngie } else { 432275988Sngie fprintf(stdout, "Parent output\n"); 433275988Sngie fprintf(stderr, "Parent error\n"); 434275988Sngie atf_utils_wait(child, 50, "Child output\n", "Child error\n"); 435275988Sngie exit(40); 436275988Sngie } 437275988Sngie } else { 438275988Sngie atf_utils_wait(parent, 40, 439275988Sngie "Parent output\n" 440275988Sngie "subprocess stdout: Child output\n" 441275988Sngie "subprocess stderr: Child error\n", 442275988Sngie "Parent error\n"); 443275988Sngie } 444275988Sngie} 445275988Sngie 446260029SjmmvATF_TC_WITHOUT_HEAD(wait__invalid_exitstatus); 447260029SjmmvATF_TC_BODY(wait__invalid_exitstatus, tc) 448260029Sjmmv{ 449260029Sjmmv const pid_t control = fork(); 450260029Sjmmv ATF_REQUIRE(control != -1); 451260029Sjmmv if (control == 0) 452260029Sjmmv fork_and_wait(120, "Some output\n", "Some error\n"); 453260029Sjmmv else { 454260029Sjmmv int status; 455260029Sjmmv ATF_REQUIRE(waitpid(control, &status, 0) != -1); 456260029Sjmmv ATF_REQUIRE(WIFEXITED(status)); 457260029Sjmmv ATF_REQUIRE_EQ(EXIT_FAILURE, WEXITSTATUS(status)); 458260029Sjmmv } 459260029Sjmmv} 460260029Sjmmv 461260029SjmmvATF_TC_WITHOUT_HEAD(wait__invalid_stdout); 462260029SjmmvATF_TC_BODY(wait__invalid_stdout, tc) 463260029Sjmmv{ 464260029Sjmmv const pid_t control = fork(); 465260029Sjmmv ATF_REQUIRE(control != -1); 466260029Sjmmv if (control == 0) 467260029Sjmmv fork_and_wait(123, "Some output foo\n", "Some error\n"); 468260029Sjmmv else { 469260029Sjmmv int status; 470260029Sjmmv ATF_REQUIRE(waitpid(control, &status, 0) != -1); 471260029Sjmmv ATF_REQUIRE(WIFEXITED(status)); 472260029Sjmmv ATF_REQUIRE_EQ(EXIT_FAILURE, WEXITSTATUS(status)); 473260029Sjmmv } 474260029Sjmmv} 475260029Sjmmv 476260029SjmmvATF_TC_WITHOUT_HEAD(wait__invalid_stderr); 477260029SjmmvATF_TC_BODY(wait__invalid_stderr, tc) 478260029Sjmmv{ 479260029Sjmmv const pid_t control = fork(); 480260029Sjmmv ATF_REQUIRE(control != -1); 481260029Sjmmv if (control == 0) 482260029Sjmmv fork_and_wait(123, "Some output\n", "Some error foo\n"); 483260029Sjmmv else { 484260029Sjmmv int status; 485260029Sjmmv ATF_REQUIRE(waitpid(control, &status, 0) != -1); 486260029Sjmmv ATF_REQUIRE(WIFEXITED(status)); 487260029Sjmmv ATF_REQUIRE_EQ(EXIT_FAILURE, WEXITSTATUS(status)); 488260029Sjmmv } 489260029Sjmmv} 490260029Sjmmv 491260029SjmmvATF_TC_WITHOUT_HEAD(wait__save_stdout); 492260029SjmmvATF_TC_BODY(wait__save_stdout, tc) 493260029Sjmmv{ 494260029Sjmmv const pid_t control = fork(); 495260029Sjmmv ATF_REQUIRE(control != -1); 496260029Sjmmv if (control == 0) 497260029Sjmmv fork_and_wait(123, "save:my-output.txt", "Some error\n"); 498260029Sjmmv else { 499260029Sjmmv int status; 500260029Sjmmv ATF_REQUIRE(waitpid(control, &status, 0) != -1); 501260029Sjmmv ATF_REQUIRE(WIFEXITED(status)); 502260029Sjmmv ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); 503260029Sjmmv 504260029Sjmmv ATF_REQUIRE(atf_utils_compare_file("my-output.txt", "Some output\n")); 505260029Sjmmv } 506260029Sjmmv} 507260029Sjmmv 508260029SjmmvATF_TC_WITHOUT_HEAD(wait__save_stderr); 509260029SjmmvATF_TC_BODY(wait__save_stderr, tc) 510260029Sjmmv{ 511260029Sjmmv const pid_t control = fork(); 512260029Sjmmv ATF_REQUIRE(control != -1); 513260029Sjmmv if (control == 0) 514260029Sjmmv fork_and_wait(123, "Some output\n", "save:my-output.txt"); 515260029Sjmmv else { 516260029Sjmmv int status; 517260029Sjmmv ATF_REQUIRE(waitpid(control, &status, 0) != -1); 518260029Sjmmv ATF_REQUIRE(WIFEXITED(status)); 519260029Sjmmv ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); 520260029Sjmmv 521260029Sjmmv ATF_REQUIRE(atf_utils_compare_file("my-output.txt", "Some error\n")); 522260029Sjmmv } 523260029Sjmmv} 524260029Sjmmv 525240116SmarcelATF_TP_ADD_TCS(tp) 526240116Smarcel{ 527260029Sjmmv ATF_TP_ADD_TC(tp, cat_file__empty); 528260029Sjmmv ATF_TP_ADD_TC(tp, cat_file__one_line); 529260029Sjmmv ATF_TP_ADD_TC(tp, cat_file__several_lines); 530260029Sjmmv ATF_TP_ADD_TC(tp, cat_file__no_newline_eof); 531240116Smarcel 532260029Sjmmv ATF_TP_ADD_TC(tp, compare_file__empty__match); 533260029Sjmmv ATF_TP_ADD_TC(tp, compare_file__empty__not_match); 534260029Sjmmv ATF_TP_ADD_TC(tp, compare_file__short__match); 535260029Sjmmv ATF_TP_ADD_TC(tp, compare_file__short__not_match); 536260029Sjmmv ATF_TP_ADD_TC(tp, compare_file__long__match); 537260029Sjmmv ATF_TP_ADD_TC(tp, compare_file__long__not_match); 538260029Sjmmv 539260029Sjmmv ATF_TP_ADD_TC(tp, copy_file__empty); 540260029Sjmmv ATF_TP_ADD_TC(tp, copy_file__some_contents); 541260029Sjmmv 542260029Sjmmv ATF_TP_ADD_TC(tp, create_file); 543260029Sjmmv 544260029Sjmmv ATF_TP_ADD_TC(tp, file_exists); 545260029Sjmmv 546260029Sjmmv ATF_TP_ADD_TC(tp, fork); 547260029Sjmmv 548260029Sjmmv ATF_TP_ADD_TC(tp, free_charpp__empty); 549260029Sjmmv ATF_TP_ADD_TC(tp, free_charpp__some); 550260029Sjmmv 551260029Sjmmv ATF_TP_ADD_TC(tp, grep_file); 552260029Sjmmv ATF_TP_ADD_TC(tp, grep_string); 553260029Sjmmv 554260029Sjmmv ATF_TP_ADD_TC(tp, readline__none); 555260029Sjmmv ATF_TP_ADD_TC(tp, readline__some); 556260029Sjmmv 557260029Sjmmv ATF_TP_ADD_TC(tp, redirect__stdout); 558260029Sjmmv ATF_TP_ADD_TC(tp, redirect__stderr); 559260029Sjmmv ATF_TP_ADD_TC(tp, redirect__other); 560260029Sjmmv 561260029Sjmmv ATF_TP_ADD_TC(tp, wait__ok); 562275988Sngie ATF_TP_ADD_TC(tp, wait__ok_nested); 563260029Sjmmv ATF_TP_ADD_TC(tp, wait__save_stdout); 564260029Sjmmv ATF_TP_ADD_TC(tp, wait__save_stderr); 565260029Sjmmv ATF_TP_ADD_TC(tp, wait__invalid_exitstatus); 566260029Sjmmv ATF_TP_ADD_TC(tp, wait__invalid_stdout); 567260029Sjmmv ATF_TP_ADD_TC(tp, wait__invalid_stderr); 568260029Sjmmv 569240116Smarcel return atf_no_error(); 570240116Smarcel} 571