1 /* Copyright (c) 2010 The NetBSD Foundation, Inc. 2 * All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 14 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 15 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 16 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 20 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 22 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 24 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 25 26 #include "atf-c/utils.h" 27 28 #include <sys/stat.h> 29 #include <sys/wait.h> 30 31 #include <fcntl.h> 32 #include <stddef.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <unistd.h> 37 38 #include <atf-c.h> 39 40 #include "atf-c/detail/dynstr.h" 41 #include "atf-c/detail/test_helpers.h" 42 43 /** Reads the contents of a file into a buffer. 44 * 45 * Up to buflen-1 characters are read into buffer. If this function returns, 46 * the contents read into the buffer are guaranteed to be nul-terminated. 47 * Note, however, that if the file contains any nul characters itself, 48 * comparing it "as a string" will not work. 49 * 50 * \param path The file to be read, which must exist. 51 * \param buffer Buffer into which to store the file contents. 52 * \param buflen Size of the target buffer. 53 * 54 * \return The count of bytes read. */ 55 static ssize_t 56 read_file(const char *path, void *const buffer, const size_t buflen) 57 { 58 const int fd = open(path, O_RDONLY); 59 ATF_REQUIRE_MSG(fd != -1, "Cannot open %s", path); 60 const ssize_t length = read(fd, buffer, buflen - 1); 61 close(fd); 62 ATF_REQUIRE(length != -1); 63 ((char *)buffer)[length] = '\0'; 64 return length; 65 } 66 67 ATF_TC_WITHOUT_HEAD(cat_file__empty); 68 ATF_TC_BODY(cat_file__empty, tc) 69 { 70 atf_utils_create_file("file.txt", "%s", ""); 71 atf_utils_redirect(STDOUT_FILENO, "captured.txt"); 72 atf_utils_cat_file("file.txt", "PREFIX"); 73 fflush(stdout); 74 close(STDOUT_FILENO); 75 76 char buffer[1024]; 77 read_file("captured.txt", buffer, sizeof(buffer)); 78 ATF_REQUIRE_STREQ("", buffer); 79 } 80 81 ATF_TC_WITHOUT_HEAD(cat_file__one_line); 82 ATF_TC_BODY(cat_file__one_line, tc) 83 { 84 atf_utils_create_file("file.txt", "This is a single line\n"); 85 atf_utils_redirect(STDOUT_FILENO, "captured.txt"); 86 atf_utils_cat_file("file.txt", "PREFIX"); 87 fflush(stdout); 88 close(STDOUT_FILENO); 89 90 char buffer[1024]; 91 read_file("captured.txt", buffer, sizeof(buffer)); 92 ATF_REQUIRE_STREQ("PREFIXThis is a single line\n", buffer); 93 } 94 95 ATF_TC_WITHOUT_HEAD(cat_file__several_lines); 96 ATF_TC_BODY(cat_file__several_lines, tc) 97 { 98 atf_utils_create_file("file.txt", "First\nSecond line\nAnd third\n"); 99 atf_utils_redirect(STDOUT_FILENO, "captured.txt"); 100 atf_utils_cat_file("file.txt", ">"); 101 fflush(stdout); 102 close(STDOUT_FILENO); 103 104 char buffer[1024]; 105 read_file("captured.txt", buffer, sizeof(buffer)); 106 ATF_REQUIRE_STREQ(">First\n>Second line\n>And third\n", buffer); 107 } 108 109 ATF_TC_WITHOUT_HEAD(cat_file__no_newline_eof); 110 ATF_TC_BODY(cat_file__no_newline_eof, tc) 111 { 112 atf_utils_create_file("file.txt", "Foo\n bar baz"); 113 atf_utils_redirect(STDOUT_FILENO, "captured.txt"); 114 atf_utils_cat_file("file.txt", "PREFIX"); 115 fflush(stdout); 116 close(STDOUT_FILENO); 117 118 char buffer[1024]; 119 read_file("captured.txt", buffer, sizeof(buffer)); 120 ATF_REQUIRE_STREQ("PREFIXFoo\nPREFIX bar baz", buffer); 121 } 122 123 ATF_TC_WITHOUT_HEAD(compare_file__empty__match); 124 ATF_TC_BODY(compare_file__empty__match, tc) 125 { 126 atf_utils_create_file("test.txt", "%s", ""); 127 ATF_REQUIRE(atf_utils_compare_file("test.txt", "")); 128 } 129 130 ATF_TC_WITHOUT_HEAD(compare_file__empty__not_match); 131 ATF_TC_BODY(compare_file__empty__not_match, tc) 132 { 133 atf_utils_create_file("test.txt", "%s", ""); 134 ATF_REQUIRE(!atf_utils_compare_file("test.txt", "\n")); 135 ATF_REQUIRE(!atf_utils_compare_file("test.txt", "foo")); 136 ATF_REQUIRE(!atf_utils_compare_file("test.txt", " ")); 137 } 138 139 ATF_TC_WITHOUT_HEAD(compare_file__short__match); 140 ATF_TC_BODY(compare_file__short__match, tc) 141 { 142 atf_utils_create_file("test.txt", "this is a short file"); 143 ATF_REQUIRE(atf_utils_compare_file("test.txt", "this is a short file")); 144 } 145 146 ATF_TC_WITHOUT_HEAD(compare_file__short__not_match); 147 ATF_TC_BODY(compare_file__short__not_match, tc) 148 { 149 atf_utils_create_file("test.txt", "this is a short file"); 150 ATF_REQUIRE(!atf_utils_compare_file("test.txt", "")); 151 ATF_REQUIRE(!atf_utils_compare_file("test.txt", "\n")); 152 ATF_REQUIRE(!atf_utils_compare_file("test.txt", "this is a Short file")); 153 ATF_REQUIRE(!atf_utils_compare_file("test.txt", "this is a short fil")); 154 ATF_REQUIRE(!atf_utils_compare_file("test.txt", "this is a short file ")); 155 } 156 157 ATF_TC_WITHOUT_HEAD(compare_file__long__match); 158 ATF_TC_BODY(compare_file__long__match, tc) 159 { 160 char long_contents[3456]; 161 size_t i = 0; 162 for (; i < sizeof(long_contents) - 1; i++) 163 long_contents[i] = '0' + (i % 10); 164 long_contents[i] = '\0'; 165 atf_utils_create_file("test.txt", "%s", long_contents); 166 167 ATF_REQUIRE(atf_utils_compare_file("test.txt", long_contents)); 168 } 169 170 ATF_TC_WITHOUT_HEAD(compare_file__long__not_match); 171 ATF_TC_BODY(compare_file__long__not_match, tc) 172 { 173 char long_contents[3456]; 174 size_t i = 0; 175 for (; i < sizeof(long_contents) - 1; i++) 176 long_contents[i] = '0' + (i % 10); 177 long_contents[i] = '\0'; 178 atf_utils_create_file("test.txt", "%s", long_contents); 179 180 ATF_REQUIRE(!atf_utils_compare_file("test.txt", "")); 181 ATF_REQUIRE(!atf_utils_compare_file("test.txt", "\n")); 182 ATF_REQUIRE(!atf_utils_compare_file("test.txt", "0123456789")); 183 long_contents[i - 1] = 'Z'; 184 ATF_REQUIRE(!atf_utils_compare_file("test.txt", long_contents)); 185 } 186 187 ATF_TC_WITHOUT_HEAD(copy_file__empty); 188 ATF_TC_BODY(copy_file__empty, tc) 189 { 190 atf_utils_create_file("src.txt", "%s", ""); 191 ATF_REQUIRE(chmod("src.txt", 0520) != -1); 192 193 atf_utils_copy_file("src.txt", "dest.txt"); 194 ATF_REQUIRE(atf_utils_compare_file("dest.txt", "")); 195 struct stat sb; 196 ATF_REQUIRE(stat("dest.txt", &sb) != -1); 197 ATF_REQUIRE_EQ(0520, sb.st_mode & 0xfff); 198 } 199 200 ATF_TC_WITHOUT_HEAD(copy_file__some_contents); 201 ATF_TC_BODY(copy_file__some_contents, tc) 202 { 203 atf_utils_create_file("src.txt", "This is a\ntest file\n"); 204 atf_utils_copy_file("src.txt", "dest.txt"); 205 ATF_REQUIRE(atf_utils_compare_file("dest.txt", "This is a\ntest file\n")); 206 } 207 208 ATF_TC_WITHOUT_HEAD(create_file); 209 ATF_TC_BODY(create_file, tc) 210 { 211 atf_utils_create_file("test.txt", "This is a test with %d", 12345); 212 213 char buffer[128]; 214 read_file("test.txt", buffer, sizeof(buffer)); 215 ATF_REQUIRE_STREQ("This is a test with 12345", buffer); 216 } 217 218 ATF_TC_WITHOUT_HEAD(file_exists); 219 ATF_TC_BODY(file_exists, tc) 220 { 221 atf_utils_create_file("test.txt", "foo"); 222 223 ATF_REQUIRE( atf_utils_file_exists("test.txt")); 224 ATF_REQUIRE( atf_utils_file_exists("./test.txt")); 225 ATF_REQUIRE(!atf_utils_file_exists("./test.tx")); 226 ATF_REQUIRE(!atf_utils_file_exists("test.txt2")); 227 } 228 229 ATF_TC_WITHOUT_HEAD(fork); 230 ATF_TC_BODY(fork, tc) 231 { 232 fprintf(stdout, "Should not get into child\n"); 233 fprintf(stderr, "Should not get into child\n"); 234 pid_t pid = atf_utils_fork(); 235 if (pid == 0) { 236 fprintf(stdout, "Child stdout\n"); 237 fprintf(stderr, "Child stderr\n"); 238 exit(EXIT_SUCCESS); 239 } 240 241 int status; 242 ATF_REQUIRE(waitpid(pid, &status, 0) != -1); 243 ATF_REQUIRE(WIFEXITED(status)); 244 ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); 245 246 atf_dynstr_t out_name; 247 RE(atf_dynstr_init_fmt(&out_name, "atf_utils_fork_%d_out.txt", (int)pid)); 248 atf_dynstr_t err_name; 249 RE(atf_dynstr_init_fmt(&err_name, "atf_utils_fork_%d_err.txt", (int)pid)); 250 251 char buffer[1024]; 252 read_file(atf_dynstr_cstring(&out_name), buffer, sizeof(buffer)); 253 ATF_REQUIRE_STREQ("Child stdout\n", buffer); 254 read_file(atf_dynstr_cstring(&err_name), buffer, sizeof(buffer)); 255 ATF_REQUIRE_STREQ("Child stderr\n", buffer); 256 257 atf_dynstr_fini(&err_name); 258 atf_dynstr_fini(&out_name); 259 } 260 261 ATF_TC_WITHOUT_HEAD(free_charpp__empty); 262 ATF_TC_BODY(free_charpp__empty, tc) 263 { 264 char **array = malloc(sizeof(char *) * 1); 265 array[0] = NULL; 266 267 atf_utils_free_charpp(array); 268 } 269 270 ATF_TC_WITHOUT_HEAD(free_charpp__some); 271 ATF_TC_BODY(free_charpp__some, tc) 272 { 273 char **array = malloc(sizeof(char *) * 4); 274 array[0] = strdup("first"); 275 array[1] = strdup("second"); 276 array[2] = strdup("third"); 277 array[3] = NULL; 278 279 atf_utils_free_charpp(array); 280 } 281 282 ATF_TC_WITHOUT_HEAD(grep_file); 283 ATF_TC_BODY(grep_file, tc) 284 { 285 atf_utils_create_file("test.txt", "line1\nthe second line\naaaabbbb\n"); 286 287 ATF_CHECK(atf_utils_grep_file("line1", "test.txt")); 288 ATF_CHECK(atf_utils_grep_file("line%d", "test.txt", 1)); 289 ATF_CHECK(atf_utils_grep_file("second line", "test.txt")); 290 ATF_CHECK(atf_utils_grep_file("aa.*bb", "test.txt")); 291 ATF_CHECK(!atf_utils_grep_file("foo", "test.txt")); 292 ATF_CHECK(!atf_utils_grep_file("bar", "test.txt")); 293 ATF_CHECK(!atf_utils_grep_file("aaaaa", "test.txt")); 294 } 295 296 ATF_TC_WITHOUT_HEAD(grep_string); 297 ATF_TC_BODY(grep_string, tc) 298 { 299 const char *str = "a string - aaaabbbb"; 300 ATF_CHECK(atf_utils_grep_string("a string", str)); 301 ATF_CHECK(atf_utils_grep_string("^a string", str)); 302 ATF_CHECK(atf_utils_grep_string("aaaabbbb$", str)); 303 ATF_CHECK(atf_utils_grep_string("a%s*bb", str, "a.")); 304 ATF_CHECK(!atf_utils_grep_string("foo", str)); 305 ATF_CHECK(!atf_utils_grep_string("bar", str)); 306 ATF_CHECK(!atf_utils_grep_string("aaaaa", str)); 307 } 308 309 ATF_TC_WITHOUT_HEAD(readline__none); 310 ATF_TC_BODY(readline__none, tc) 311 { 312 atf_utils_create_file("empty.txt", "%s", ""); 313 314 const int fd = open("empty.txt", O_RDONLY); 315 ATF_REQUIRE(fd != -1); 316 ATF_REQUIRE(atf_utils_readline(fd) == NULL); 317 close(fd); 318 } 319 320 ATF_TC_WITHOUT_HEAD(readline__some); 321 ATF_TC_BODY(readline__some, tc) 322 { 323 const char *l1 = "First line with % formatting % characters %"; 324 const char *l2 = "Second line; much longer than the first one"; 325 const char *l3 = "Last line, without terminator"; 326 327 atf_utils_create_file("test.txt", "%s\n%s\n%s", l1, l2, l3); 328 329 const int fd = open("test.txt", O_RDONLY); 330 ATF_REQUIRE(fd != -1); 331 332 char *line; 333 334 line = atf_utils_readline(fd); 335 ATF_REQUIRE_STREQ(l1, line); 336 free(line); 337 338 line = atf_utils_readline(fd); 339 ATF_REQUIRE_STREQ(l2, line); 340 free(line); 341 342 line = atf_utils_readline(fd); 343 ATF_REQUIRE_STREQ(l3, line); 344 free(line); 345 346 close(fd); 347 } 348 349 ATF_TC_WITHOUT_HEAD(redirect__stdout); 350 ATF_TC_BODY(redirect__stdout, tc) 351 { 352 printf("Buffer this"); 353 atf_utils_redirect(STDOUT_FILENO, "captured.txt"); 354 printf("The printed message"); 355 fflush(stdout); 356 357 char buffer[1024]; 358 read_file("captured.txt", buffer, sizeof(buffer)); 359 ATF_REQUIRE_STREQ("The printed message", buffer); 360 } 361 362 ATF_TC_WITHOUT_HEAD(redirect__stderr); 363 ATF_TC_BODY(redirect__stderr, tc) 364 { 365 fprintf(stderr, "Buffer this"); 366 atf_utils_redirect(STDERR_FILENO, "captured.txt"); 367 fprintf(stderr, "The printed message"); 368 fflush(stderr); 369 370 char buffer[1024]; 371 read_file("captured.txt", buffer, sizeof(buffer)); 372 ATF_REQUIRE_STREQ("The printed message", buffer); 373 } 374 375 ATF_TC_WITHOUT_HEAD(redirect__other); 376 ATF_TC_BODY(redirect__other, tc) 377 { 378 const char *message = "Foo bar\nbaz\n"; 379 atf_utils_redirect(15, "captured.txt"); 380 ATF_REQUIRE(write(15, message, strlen(message)) != -1); 381 close(15); 382 383 char buffer[1024]; 384 read_file("captured.txt", buffer, sizeof(buffer)); 385 ATF_REQUIRE_STREQ(message, buffer); 386 } 387 388 static void 389 fork_and_wait(const int exitstatus, const char* expout, const char* experr) 390 { 391 const pid_t pid = atf_utils_fork(); 392 ATF_REQUIRE(pid != -1); 393 if (pid == 0) { 394 fprintf(stdout, "Some output\n"); 395 fprintf(stderr, "Some error\n"); 396 exit(123); 397 } 398 atf_utils_wait(pid, exitstatus, expout, experr); 399 exit(EXIT_SUCCESS); 400 } 401 402 ATF_TC_WITHOUT_HEAD(wait__ok); 403 ATF_TC_BODY(wait__ok, tc) 404 { 405 const pid_t control = fork(); 406 ATF_REQUIRE(control != -1); 407 if (control == 0) 408 fork_and_wait(123, "Some output\n", "Some error\n"); 409 else { 410 int status; 411 ATF_REQUIRE(waitpid(control, &status, 0) != -1); 412 ATF_REQUIRE(WIFEXITED(status)); 413 ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); 414 } 415 } 416 417 ATF_TC_WITHOUT_HEAD(wait__ok_nested); 418 ATF_TC_BODY(wait__ok_nested, tc) 419 { 420 const pid_t parent = atf_utils_fork(); 421 ATF_REQUIRE(parent != -1); 422 if (parent == 0) { 423 const pid_t child = atf_utils_fork(); 424 ATF_REQUIRE(child != -1); 425 if (child == 0) { 426 fflush(stderr); 427 fprintf(stdout, "Child output\n"); 428 fflush(stdout); 429 fprintf(stderr, "Child error\n"); 430 exit(50); 431 } else { 432 fprintf(stdout, "Parent output\n"); 433 fprintf(stderr, "Parent error\n"); 434 atf_utils_wait(child, 50, "Child output\n", "Child error\n"); 435 exit(40); 436 } 437 } else { 438 atf_utils_wait(parent, 40, 439 "Parent output\n" 440 "subprocess stdout: Child output\n" 441 "subprocess stderr: Child error\n", 442 "Parent error\n"); 443 } 444 } 445 446 ATF_TC_WITHOUT_HEAD(wait__invalid_exitstatus); 447 ATF_TC_BODY(wait__invalid_exitstatus, tc) 448 { 449 const pid_t control = fork(); 450 ATF_REQUIRE(control != -1); 451 if (control == 0) 452 fork_and_wait(120, "Some output\n", "Some error\n"); 453 else { 454 int status; 455 ATF_REQUIRE(waitpid(control, &status, 0) != -1); 456 ATF_REQUIRE(WIFEXITED(status)); 457 ATF_REQUIRE_EQ(EXIT_FAILURE, WEXITSTATUS(status)); 458 } 459 } 460 461 ATF_TC_WITHOUT_HEAD(wait__invalid_stdout); 462 ATF_TC_BODY(wait__invalid_stdout, tc) 463 { 464 const pid_t control = fork(); 465 ATF_REQUIRE(control != -1); 466 if (control == 0) 467 fork_and_wait(123, "Some output foo\n", "Some error\n"); 468 else { 469 int status; 470 ATF_REQUIRE(waitpid(control, &status, 0) != -1); 471 ATF_REQUIRE(WIFEXITED(status)); 472 ATF_REQUIRE_EQ(EXIT_FAILURE, WEXITSTATUS(status)); 473 } 474 } 475 476 ATF_TC_WITHOUT_HEAD(wait__invalid_stderr); 477 ATF_TC_BODY(wait__invalid_stderr, tc) 478 { 479 const pid_t control = fork(); 480 ATF_REQUIRE(control != -1); 481 if (control == 0) 482 fork_and_wait(123, "Some output\n", "Some error foo\n"); 483 else { 484 int status; 485 ATF_REQUIRE(waitpid(control, &status, 0) != -1); 486 ATF_REQUIRE(WIFEXITED(status)); 487 ATF_REQUIRE_EQ(EXIT_FAILURE, WEXITSTATUS(status)); 488 } 489 } 490 491 ATF_TC_WITHOUT_HEAD(wait__save_stdout); 492 ATF_TC_BODY(wait__save_stdout, tc) 493 { 494 const pid_t control = fork(); 495 ATF_REQUIRE(control != -1); 496 if (control == 0) 497 fork_and_wait(123, "save:my-output.txt", "Some error\n"); 498 else { 499 int status; 500 ATF_REQUIRE(waitpid(control, &status, 0) != -1); 501 ATF_REQUIRE(WIFEXITED(status)); 502 ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); 503 504 ATF_REQUIRE(atf_utils_compare_file("my-output.txt", "Some output\n")); 505 } 506 } 507 508 ATF_TC_WITHOUT_HEAD(wait__save_stderr); 509 ATF_TC_BODY(wait__save_stderr, tc) 510 { 511 const pid_t control = fork(); 512 ATF_REQUIRE(control != -1); 513 if (control == 0) 514 fork_and_wait(123, "Some output\n", "save:my-output.txt"); 515 else { 516 int status; 517 ATF_REQUIRE(waitpid(control, &status, 0) != -1); 518 ATF_REQUIRE(WIFEXITED(status)); 519 ATF_REQUIRE_EQ(EXIT_SUCCESS, WEXITSTATUS(status)); 520 521 ATF_REQUIRE(atf_utils_compare_file("my-output.txt", "Some error\n")); 522 } 523 } 524 525 ATF_TP_ADD_TCS(tp) 526 { 527 ATF_TP_ADD_TC(tp, cat_file__empty); 528 ATF_TP_ADD_TC(tp, cat_file__one_line); 529 ATF_TP_ADD_TC(tp, cat_file__several_lines); 530 ATF_TP_ADD_TC(tp, cat_file__no_newline_eof); 531 532 ATF_TP_ADD_TC(tp, compare_file__empty__match); 533 ATF_TP_ADD_TC(tp, compare_file__empty__not_match); 534 ATF_TP_ADD_TC(tp, compare_file__short__match); 535 ATF_TP_ADD_TC(tp, compare_file__short__not_match); 536 ATF_TP_ADD_TC(tp, compare_file__long__match); 537 ATF_TP_ADD_TC(tp, compare_file__long__not_match); 538 539 ATF_TP_ADD_TC(tp, copy_file__empty); 540 ATF_TP_ADD_TC(tp, copy_file__some_contents); 541 542 ATF_TP_ADD_TC(tp, create_file); 543 544 ATF_TP_ADD_TC(tp, file_exists); 545 546 ATF_TP_ADD_TC(tp, fork); 547 548 ATF_TP_ADD_TC(tp, free_charpp__empty); 549 ATF_TP_ADD_TC(tp, free_charpp__some); 550 551 ATF_TP_ADD_TC(tp, grep_file); 552 ATF_TP_ADD_TC(tp, grep_string); 553 554 ATF_TP_ADD_TC(tp, readline__none); 555 ATF_TP_ADD_TC(tp, readline__some); 556 557 ATF_TP_ADD_TC(tp, redirect__stdout); 558 ATF_TP_ADD_TC(tp, redirect__stderr); 559 ATF_TP_ADD_TC(tp, redirect__other); 560 561 ATF_TP_ADD_TC(tp, wait__ok); 562 ATF_TP_ADD_TC(tp, wait__ok_nested); 563 ATF_TP_ADD_TC(tp, wait__save_stdout); 564 ATF_TP_ADD_TC(tp, wait__save_stderr); 565 ATF_TP_ADD_TC(tp, wait__invalid_exitstatus); 566 ATF_TP_ADD_TC(tp, wait__invalid_stdout); 567 ATF_TP_ADD_TC(tp, wait__invalid_stderr); 568 569 return atf_no_error(); 570 } 571