1 /* Copyright (c) 2008 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/check.h" 27 28 #include <fcntl.h> 29 #include <signal.h> 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <string.h> 33 #include <unistd.h> 34 35 #include <atf-c.h> 36 37 #include "atf-c/detail/fs.h" 38 #include "atf-c/detail/map.h" 39 #include "atf-c/detail/process.h" 40 #include "atf-c/detail/test_helpers.h" 41 42 /* --------------------------------------------------------------------- 43 * Auxiliary functions. 44 * --------------------------------------------------------------------- */ 45 46 static 47 void 48 do_exec(const atf_tc_t *tc, const char *helper_name, atf_check_result_t *r) 49 { 50 atf_fs_path_t process_helpers; 51 const char *argv[3]; 52 53 get_process_helpers_path(tc, false, &process_helpers); 54 55 argv[0] = atf_fs_path_cstring(&process_helpers); 56 argv[1] = helper_name; 57 argv[2] = NULL; 58 printf("Executing %s %s\n", argv[0], argv[1]); 59 RE(atf_check_exec_array(argv, r)); 60 61 atf_fs_path_fini(&process_helpers); 62 } 63 64 static 65 void 66 do_exec_with_arg(const atf_tc_t *tc, const char *helper_name, const char *arg, 67 atf_check_result_t *r) 68 { 69 atf_fs_path_t process_helpers; 70 const char *argv[4]; 71 72 get_process_helpers_path(tc, false, &process_helpers); 73 74 argv[0] = atf_fs_path_cstring(&process_helpers); 75 argv[1] = helper_name; 76 argv[2] = arg; 77 argv[3] = NULL; 78 printf("Executing %s %s %s\n", argv[0], argv[1], argv[2]); 79 RE(atf_check_exec_array(argv, r)); 80 81 atf_fs_path_fini(&process_helpers); 82 } 83 84 static 85 void 86 check_line(int fd, const char *exp) 87 { 88 char *line = atf_utils_readline(fd); 89 ATF_CHECK(line != NULL); 90 ATF_CHECK_STREQ_MSG(exp, line, "read: '%s', expected: '%s'", line, exp); 91 free(line); 92 } 93 94 /* --------------------------------------------------------------------- 95 * Helper test cases for the free functions. 96 * --------------------------------------------------------------------- */ 97 98 ATF_TC(h_build_c_o_ok); 99 ATF_TC_HEAD(h_build_c_o_ok, tc) 100 { 101 atf_tc_set_md_var(tc, "descr", "Helper test case for build_c_o"); 102 } 103 ATF_TC_BODY(h_build_c_o_ok, tc) 104 { 105 FILE *sfile; 106 bool success; 107 108 ATF_REQUIRE((sfile = fopen("test.c", "w")) != NULL); 109 fprintf(sfile, "#include <stdio.h>\n"); 110 fclose(sfile); 111 112 RE(atf_check_build_c_o("test.c", "test.o", NULL, &success)); 113 ATF_REQUIRE(success); 114 } 115 116 ATF_TC(h_build_c_o_fail); 117 ATF_TC_HEAD(h_build_c_o_fail, tc) 118 { 119 atf_tc_set_md_var(tc, "descr", "Helper test case for build_c_o"); 120 } 121 ATF_TC_BODY(h_build_c_o_fail, tc) 122 { 123 FILE *sfile; 124 bool success; 125 126 ATF_REQUIRE((sfile = fopen("test.c", "w")) != NULL); 127 fprintf(sfile, "void foo(void) { int a = UNDEFINED_SYMBOL; }\n"); 128 fclose(sfile); 129 130 RE(atf_check_build_c_o("test.c", "test.o", NULL, &success)); 131 ATF_REQUIRE(!success); 132 } 133 134 ATF_TC(h_build_cpp_ok); 135 ATF_TC_HEAD(h_build_cpp_ok, tc) 136 { 137 atf_tc_set_md_var(tc, "descr", "Helper test case for build_cpp"); 138 } 139 ATF_TC_BODY(h_build_cpp_ok, tc) 140 { 141 FILE *sfile; 142 bool success; 143 atf_fs_path_t test_p; 144 145 RE(atf_fs_path_init_fmt(&test_p, "test.p")); 146 147 ATF_REQUIRE((sfile = fopen("test.c", "w")) != NULL); 148 fprintf(sfile, "#define A foo\n"); 149 fprintf(sfile, "#define B bar\n"); 150 fprintf(sfile, "A B\n"); 151 fclose(sfile); 152 153 RE(atf_check_build_cpp("test.c", atf_fs_path_cstring(&test_p), NULL, 154 &success)); 155 ATF_REQUIRE(success); 156 157 atf_fs_path_fini(&test_p); 158 } 159 160 ATF_TC(h_build_cpp_fail); 161 ATF_TC_HEAD(h_build_cpp_fail, tc) 162 { 163 atf_tc_set_md_var(tc, "descr", "Helper test case for build_cpp"); 164 } 165 ATF_TC_BODY(h_build_cpp_fail, tc) 166 { 167 FILE *sfile; 168 bool success; 169 170 ATF_REQUIRE((sfile = fopen("test.c", "w")) != NULL); 171 fprintf(sfile, "#include \"./non-existent.h\"\n"); 172 fclose(sfile); 173 174 RE(atf_check_build_cpp("test.c", "test.p", NULL, &success)); 175 ATF_REQUIRE(!success); 176 } 177 178 ATF_TC(h_build_cxx_o_ok); 179 ATF_TC_HEAD(h_build_cxx_o_ok, tc) 180 { 181 atf_tc_set_md_var(tc, "descr", "Helper test case for build_cxx_o"); 182 } 183 ATF_TC_BODY(h_build_cxx_o_ok, tc) 184 { 185 FILE *sfile; 186 bool success; 187 188 ATF_REQUIRE((sfile = fopen("test.cpp", "w")) != NULL); 189 fprintf(sfile, "#include <iostream>\n"); 190 fclose(sfile); 191 192 RE(atf_check_build_cxx_o("test.cpp", "test.o", NULL, &success)); 193 ATF_REQUIRE(success); 194 } 195 196 ATF_TC(h_build_cxx_o_fail); 197 ATF_TC_HEAD(h_build_cxx_o_fail, tc) 198 { 199 atf_tc_set_md_var(tc, "descr", "Helper test case for build_cxx_o"); 200 } 201 ATF_TC_BODY(h_build_cxx_o_fail, tc) 202 { 203 FILE *sfile; 204 bool success; 205 206 ATF_REQUIRE((sfile = fopen("test.cpp", "w")) != NULL); 207 fprintf(sfile, "void foo(void) { int a = UNDEFINED_SYMBOL; }\n"); 208 fclose(sfile); 209 210 RE(atf_check_build_cxx_o("test.cpp", "test.o", NULL, &success)); 211 ATF_REQUIRE(!success); 212 } 213 214 /* --------------------------------------------------------------------- 215 * Test cases for the free functions. 216 * --------------------------------------------------------------------- */ 217 218 static 219 void 220 init_and_run_h_tc(atf_tc_t *tc, const atf_tc_pack_t *tcpack, 221 const char *outname, const char *errname) 222 { 223 const char *const config[] = { NULL }; 224 225 RE(atf_tc_init_pack(tc, tcpack, config)); 226 run_h_tc(tc, outname, errname, "result"); 227 atf_tc_fini(tc); 228 } 229 230 ATF_TC(build_c_o); 231 ATF_TC_HEAD(build_c_o, tc) 232 { 233 atf_tc_set_md_var(tc, "descr", "Checks the atf_check_build_c_o " 234 "function"); 235 } 236 ATF_TC_BODY(build_c_o, tc) 237 { 238 init_and_run_h_tc(&ATF_TC_NAME(h_build_c_o_ok), 239 &ATF_TC_PACK_NAME(h_build_c_o_ok), "stdout", "stderr"); 240 ATF_CHECK(atf_utils_grep_file("-o test.o", "stdout")); 241 ATF_CHECK(atf_utils_grep_file("-c test.c", "stdout")); 242 243 init_and_run_h_tc(&ATF_TC_NAME(h_build_c_o_fail), 244 &ATF_TC_PACK_NAME(h_build_c_o_fail), "stdout", "stderr"); 245 ATF_CHECK(atf_utils_grep_file("-o test.o", "stdout")); 246 ATF_CHECK(atf_utils_grep_file("-c test.c", "stdout")); 247 ATF_CHECK(atf_utils_grep_file("test.c", "stderr")); 248 ATF_CHECK(atf_utils_grep_file("UNDEFINED_SYMBOL", "stderr")); 249 } 250 251 ATF_TC(build_cpp); 252 ATF_TC_HEAD(build_cpp, tc) 253 { 254 atf_tc_set_md_var(tc, "descr", "Checks the atf_check_build_cpp " 255 "function"); 256 } 257 ATF_TC_BODY(build_cpp, tc) 258 { 259 init_and_run_h_tc(&ATF_TC_NAME(h_build_cpp_ok), 260 &ATF_TC_PACK_NAME(h_build_cpp_ok), "stdout", "stderr"); 261 ATF_CHECK(atf_utils_grep_file("-o.*test.p", "stdout")); 262 ATF_CHECK(atf_utils_grep_file("test.c", "stdout")); 263 ATF_CHECK(atf_utils_grep_file("foo bar", "test.p")); 264 265 init_and_run_h_tc(&ATF_TC_NAME(h_build_cpp_fail), 266 &ATF_TC_PACK_NAME(h_build_cpp_fail), "stdout", "stderr"); 267 ATF_CHECK(atf_utils_grep_file("-o test.p", "stdout")); 268 ATF_CHECK(atf_utils_grep_file("test.c", "stdout")); 269 ATF_CHECK(atf_utils_grep_file("test.c", "stderr")); 270 ATF_CHECK(atf_utils_grep_file("non-existent.h", "stderr")); 271 } 272 273 ATF_TC(build_cxx_o); 274 ATF_TC_HEAD(build_cxx_o, tc) 275 { 276 atf_tc_set_md_var(tc, "descr", "Checks the atf_check_build_cxx_o " 277 "function"); 278 } 279 ATF_TC_BODY(build_cxx_o, tc) 280 { 281 init_and_run_h_tc(&ATF_TC_NAME(h_build_cxx_o_ok), 282 &ATF_TC_PACK_NAME(h_build_cxx_o_ok), "stdout", "stderr"); 283 ATF_CHECK(atf_utils_grep_file("-o test.o", "stdout")); 284 ATF_CHECK(atf_utils_grep_file("-c test.cpp", "stdout")); 285 286 init_and_run_h_tc(&ATF_TC_NAME(h_build_cxx_o_fail), 287 &ATF_TC_PACK_NAME(h_build_cxx_o_fail), "stdout", "stderr"); 288 ATF_CHECK(atf_utils_grep_file("-o test.o", "stdout")); 289 ATF_CHECK(atf_utils_grep_file("-c test.cpp", "stdout")); 290 ATF_CHECK(atf_utils_grep_file("test.cpp", "stderr")); 291 ATF_CHECK(atf_utils_grep_file("UNDEFINED_SYMBOL", "stderr")); 292 } 293 294 ATF_TC(exec_array); 295 ATF_TC_HEAD(exec_array, tc) 296 { 297 atf_tc_set_md_var(tc, "descr", "Checks that atf_check_exec_array " 298 "works properly"); 299 } 300 ATF_TC_BODY(exec_array, tc) 301 { 302 atf_fs_path_t process_helpers; 303 atf_check_result_t result; 304 305 get_process_helpers_path(tc, false, &process_helpers); 306 307 const char *argv[4]; 308 argv[0] = atf_fs_path_cstring(&process_helpers); 309 argv[1] = "echo"; 310 argv[2] = "test-message"; 311 argv[3] = NULL; 312 313 RE(atf_check_exec_array(argv, &result)); 314 315 ATF_CHECK(atf_check_result_exited(&result)); 316 ATF_CHECK(atf_check_result_exitcode(&result) == EXIT_SUCCESS); 317 318 { 319 const char *path = atf_check_result_stdout(&result); 320 int fd = open(path, O_RDONLY); 321 ATF_CHECK(fd != -1); 322 check_line(fd, "test-message"); 323 close(fd); 324 } 325 326 atf_check_result_fini(&result); 327 atf_fs_path_fini(&process_helpers); 328 } 329 330 ATF_TC(exec_cleanup); 331 ATF_TC_HEAD(exec_cleanup, tc) 332 { 333 atf_tc_set_md_var(tc, "descr", "Checks that atf_check_exec_array " 334 "properly cleans up the temporary files it creates"); 335 } 336 ATF_TC_BODY(exec_cleanup, tc) 337 { 338 atf_fs_path_t out, err; 339 atf_check_result_t result; 340 bool exists; 341 342 do_exec(tc, "exit-success", &result); 343 RE(atf_fs_path_init_fmt(&out, "%s", atf_check_result_stdout(&result))); 344 RE(atf_fs_path_init_fmt(&err, "%s", atf_check_result_stderr(&result))); 345 346 RE(atf_fs_exists(&out, &exists)); ATF_CHECK(exists); 347 RE(atf_fs_exists(&err, &exists)); ATF_CHECK(exists); 348 atf_check_result_fini(&result); 349 RE(atf_fs_exists(&out, &exists)); ATF_CHECK(!exists); 350 RE(atf_fs_exists(&err, &exists)); ATF_CHECK(!exists); 351 352 atf_fs_path_fini(&err); 353 atf_fs_path_fini(&out); 354 } 355 356 ATF_TC(exec_exitstatus); 357 ATF_TC_HEAD(exec_exitstatus, tc) 358 { 359 atf_tc_set_md_var(tc, "descr", "Checks that atf_check_exec_array " 360 "properly captures the exit status of the executed " 361 "command"); 362 } 363 ATF_TC_BODY(exec_exitstatus, tc) 364 { 365 { 366 atf_check_result_t result; 367 do_exec(tc, "exit-success", &result); 368 ATF_CHECK(atf_check_result_exited(&result)); 369 ATF_CHECK(!atf_check_result_signaled(&result)); 370 ATF_CHECK(atf_check_result_exitcode(&result) == EXIT_SUCCESS); 371 atf_check_result_fini(&result); 372 } 373 374 { 375 atf_check_result_t result; 376 do_exec(tc, "exit-failure", &result); 377 ATF_CHECK(atf_check_result_exited(&result)); 378 ATF_CHECK(!atf_check_result_signaled(&result)); 379 ATF_CHECK(atf_check_result_exitcode(&result) == EXIT_FAILURE); 380 atf_check_result_fini(&result); 381 } 382 383 { 384 atf_check_result_t result; 385 do_exec(tc, "exit-signal", &result); 386 ATF_CHECK(!atf_check_result_exited(&result)); 387 ATF_CHECK(atf_check_result_signaled(&result)); 388 ATF_CHECK(atf_check_result_termsig(&result) == SIGKILL); 389 atf_check_result_fini(&result); 390 } 391 } 392 393 ATF_TC(exec_stdout_stderr); 394 ATF_TC_HEAD(exec_stdout_stderr, tc) 395 { 396 atf_tc_set_md_var(tc, "descr", "Checks that atf_check_exec_array " 397 "properly captures the stdout and stderr streams " 398 "of the child process"); 399 } 400 ATF_TC_BODY(exec_stdout_stderr, tc) 401 { 402 atf_check_result_t result1, result2; 403 const char *out1, *out2; 404 const char *err1, *err2; 405 406 do_exec_with_arg(tc, "stdout-stderr", "result1", &result1); 407 ATF_CHECK(atf_check_result_exited(&result1)); 408 ATF_CHECK(atf_check_result_exitcode(&result1) == EXIT_SUCCESS); 409 410 do_exec_with_arg(tc, "stdout-stderr", "result2", &result2); 411 ATF_CHECK(atf_check_result_exited(&result2)); 412 ATF_CHECK(atf_check_result_exitcode(&result2) == EXIT_SUCCESS); 413 414 out1 = atf_check_result_stdout(&result1); 415 out2 = atf_check_result_stdout(&result2); 416 err1 = atf_check_result_stderr(&result1); 417 err2 = atf_check_result_stderr(&result2); 418 419 ATF_CHECK(strstr(out1, "check.XXXXXX") == NULL); 420 ATF_CHECK(strstr(out2, "check.XXXXXX") == NULL); 421 ATF_CHECK(strstr(err1, "check.XXXXXX") == NULL); 422 ATF_CHECK(strstr(err2, "check.XXXXXX") == NULL); 423 424 ATF_CHECK(strstr(out1, "/check") != NULL); 425 ATF_CHECK(strstr(out2, "/check") != NULL); 426 ATF_CHECK(strstr(err1, "/check") != NULL); 427 ATF_CHECK(strstr(err2, "/check") != NULL); 428 429 ATF_CHECK(strstr(out1, "/stdout") != NULL); 430 ATF_CHECK(strstr(out2, "/stdout") != NULL); 431 ATF_CHECK(strstr(err1, "/stderr") != NULL); 432 ATF_CHECK(strstr(err2, "/stderr") != NULL); 433 434 ATF_CHECK(strcmp(out1, out2) != 0); 435 ATF_CHECK(strcmp(err1, err2) != 0); 436 437 #define CHECK_LINES(path, outname, resname) \ 438 do { \ 439 int fd = open(path, O_RDONLY); \ 440 ATF_CHECK(fd != -1); \ 441 check_line(fd, "Line 1 to " outname " for " resname); \ 442 check_line(fd, "Line 2 to " outname " for " resname); \ 443 close(fd); \ 444 } while (false) 445 446 CHECK_LINES(out1, "stdout", "result1"); 447 CHECK_LINES(out2, "stdout", "result2"); 448 CHECK_LINES(err1, "stderr", "result1"); 449 CHECK_LINES(err2, "stderr", "result2"); 450 451 #undef CHECK_LINES 452 453 atf_check_result_fini(&result2); 454 atf_check_result_fini(&result1); 455 } 456 457 ATF_TC(exec_umask); 458 ATF_TC_HEAD(exec_umask, tc) 459 { 460 atf_tc_set_md_var(tc, "descr", "Checks that atf_check_exec_array " 461 "correctly reports an error if the umask is too " 462 "restrictive to create temporary files"); 463 } 464 ATF_TC_BODY(exec_umask, tc) 465 { 466 atf_check_result_t result; 467 atf_fs_path_t process_helpers; 468 const char *argv[3]; 469 470 get_process_helpers_path(tc, false, &process_helpers); 471 argv[0] = atf_fs_path_cstring(&process_helpers); 472 argv[1] = "exit-success"; 473 argv[2] = NULL; 474 475 umask(0222); 476 atf_error_t err = atf_check_exec_array(argv, &result); 477 ATF_CHECK(atf_is_error(err)); 478 ATF_CHECK(atf_error_is(err, "invalid_umask")); 479 atf_error_free(err); 480 481 atf_fs_path_fini(&process_helpers); 482 } 483 484 ATF_TC(exec_unknown); 485 ATF_TC_HEAD(exec_unknown, tc) 486 { 487 atf_tc_set_md_var(tc, "descr", "Checks that running a non-existing " 488 "binary is handled correctly"); 489 } 490 ATF_TC_BODY(exec_unknown, tc) 491 { 492 const char *argv[2]; 493 argv[0] = "/foo/bar/non-existent"; 494 argv[1] = NULL; 495 496 atf_check_result_t result; 497 RE(atf_check_exec_array(argv, &result)); 498 ATF_CHECK(atf_check_result_exited(&result)); 499 ATF_CHECK(atf_check_result_exitcode(&result) == 127); 500 atf_check_result_fini(&result); 501 } 502 503 /* --------------------------------------------------------------------- 504 * Main. 505 * --------------------------------------------------------------------- */ 506 507 ATF_TP_ADD_TCS(tp) 508 { 509 /* Add the test cases for the free functions. */ 510 ATF_TP_ADD_TC(tp, build_c_o); 511 ATF_TP_ADD_TC(tp, build_cpp); 512 ATF_TP_ADD_TC(tp, build_cxx_o); 513 ATF_TP_ADD_TC(tp, exec_array); 514 ATF_TP_ADD_TC(tp, exec_cleanup); 515 ATF_TP_ADD_TC(tp, exec_exitstatus); 516 ATF_TP_ADD_TC(tp, exec_stdout_stderr); 517 ATF_TP_ADD_TC(tp, exec_umask); 518 ATF_TP_ADD_TC(tp, exec_unknown); 519 520 return atf_no_error(); 521 } 522