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