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