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