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
do_exec(const atf_tc_t * tc,const char * helper_name,atf_check_result_t * r)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
do_exec_with_arg(const atf_tc_t * tc,const char * helper_name,const char * arg,atf_check_result_t * r)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
check_line(int fd,const char * exp)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);
ATF_TC_HEAD(h_build_c_o_ok,tc)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 }
ATF_TC_BODY(h_build_c_o_ok,tc)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);
ATF_TC_HEAD(h_build_c_o_fail,tc)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 }
ATF_TC_BODY(h_build_c_o_fail,tc)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);
ATF_TC_HEAD(h_build_cpp_ok,tc)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 }
ATF_TC_BODY(h_build_cpp_ok,tc)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);
ATF_TC_HEAD(h_build_cpp_fail,tc)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 }
ATF_TC_BODY(h_build_cpp_fail,tc)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);
ATF_TC_HEAD(h_build_cxx_o_ok,tc)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 }
ATF_TC_BODY(h_build_cxx_o_ok,tc)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);
ATF_TC_HEAD(h_build_cxx_o_fail,tc)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 }
ATF_TC_BODY(h_build_cxx_o_fail,tc)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
init_and_run_h_tc(atf_tc_t * tc,const atf_tc_pack_t * tcpack,const char * outname,const char * errname)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);
ATF_TC_HEAD(build_c_o,tc)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 }
ATF_TC_BODY(build_c_o,tc)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);
ATF_TC_HEAD(build_cpp,tc)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 }
ATF_TC_BODY(build_cpp,tc)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);
ATF_TC_HEAD(build_cxx_o,tc)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 }
ATF_TC_BODY(build_cxx_o,tc)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);
ATF_TC_HEAD(exec_array,tc)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 }
ATF_TC_BODY(exec_array,tc)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);
ATF_TC_HEAD(exec_cleanup,tc)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 }
ATF_TC_BODY(exec_cleanup,tc)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);
ATF_TC_HEAD(exec_exitstatus,tc)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 }
ATF_TC_BODY(exec_exitstatus,tc)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);
ATF_TC_HEAD(exec_stdout_stderr,tc)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 }
ATF_TC_BODY(exec_stdout_stderr,tc)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);
ATF_TC_HEAD(exec_umask,tc)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 }
ATF_TC_BODY(exec_umask,tc)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);
ATF_TC_HEAD(exec_unknown,tc)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 }
ATF_TC_BODY(exec_unknown,tc)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
ATF_TP_ADD_TCS(tp)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