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