]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/atf/atf-c/check_test.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / atf / atf-c / check_test.c
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
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
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
91 check_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
107 ATF_TC(h_build_c_o_ok);
108 ATF_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 }
112 ATF_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
125 ATF_TC(h_build_c_o_fail);
126 ATF_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 }
130 ATF_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
143 ATF_TC(h_build_cpp_ok);
144 ATF_TC_HEAD(h_build_cpp_ok, tc)
145 {
146     atf_tc_set_md_var(tc, "descr", "Helper test case for build_cpp");
147 }
148 ATF_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
169 ATF_TC(h_build_cpp_fail);
170 ATF_TC_HEAD(h_build_cpp_fail, tc)
171 {
172     atf_tc_set_md_var(tc, "descr", "Helper test case for build_cpp");
173 }
174 ATF_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
187 ATF_TC(h_build_cxx_o_ok);
188 ATF_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 }
192 ATF_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
205 ATF_TC(h_build_cxx_o_fail);
206 ATF_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 }
210 ATF_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
227 static
228 void
229 init_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
239 ATF_TC(build_c_o);
240 ATF_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 }
245 ATF_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
260 ATF_TC(build_cpp);
261 ATF_TC_HEAD(build_cpp, tc)
262 {
263     atf_tc_set_md_var(tc, "descr", "Checks the atf_check_build_cpp "
264                       "function");
265 }
266 ATF_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
282 ATF_TC(build_cxx_o);
283 ATF_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 }
288 ATF_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
303 ATF_TC(exec_array);
304 ATF_TC_HEAD(exec_array, tc)
305 {
306     atf_tc_set_md_var(tc, "descr", "Checks that atf_check_exec_array "
307                       "works properly");
308 }
309 ATF_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
339 ATF_TC(exec_cleanup);
340 ATF_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 }
345 ATF_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
365 ATF_TC(exec_exitstatus);
366 ATF_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 }
372 ATF_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
402 ATF_TC(exec_stdout_stderr);
403 ATF_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 }
409 ATF_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
466 ATF_TC(exec_umask);
467 ATF_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 }
473 ATF_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
493 ATF_TC(exec_unknown);
494 ATF_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 }
499 ATF_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
520 HEADER_TC(include, "atf-c/check.h");
521
522 /* ---------------------------------------------------------------------
523  * Main.
524  * --------------------------------------------------------------------- */
525
526 ATF_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 }