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