xref: /freebsd/contrib/atf/atf-c/detail/test_helpers.c (revision c243e4902be8df1e643c76b5f18b68bb77cc5268)
1*c243e490SMarcel Moolenaar /*
2*c243e490SMarcel Moolenaar  * Automated Testing Framework (atf)
3*c243e490SMarcel Moolenaar  *
4*c243e490SMarcel Moolenaar  * Copyright (c) 2008 The NetBSD Foundation, Inc.
5*c243e490SMarcel Moolenaar  * All rights reserved.
6*c243e490SMarcel Moolenaar  *
7*c243e490SMarcel Moolenaar  * Redistribution and use in source and binary forms, with or without
8*c243e490SMarcel Moolenaar  * modification, are permitted provided that the following conditions
9*c243e490SMarcel Moolenaar  * are met:
10*c243e490SMarcel Moolenaar  * 1. Redistributions of source code must retain the above copyright
11*c243e490SMarcel Moolenaar  *    notice, this list of conditions and the following disclaimer.
12*c243e490SMarcel Moolenaar  * 2. Redistributions in binary form must reproduce the above copyright
13*c243e490SMarcel Moolenaar  *    notice, this list of conditions and the following disclaimer in the
14*c243e490SMarcel Moolenaar  *    documentation and/or other materials provided with the distribution.
15*c243e490SMarcel Moolenaar  *
16*c243e490SMarcel Moolenaar  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17*c243e490SMarcel Moolenaar  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18*c243e490SMarcel Moolenaar  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19*c243e490SMarcel Moolenaar  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20*c243e490SMarcel Moolenaar  * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21*c243e490SMarcel Moolenaar  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*c243e490SMarcel Moolenaar  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23*c243e490SMarcel Moolenaar  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24*c243e490SMarcel Moolenaar  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25*c243e490SMarcel Moolenaar  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26*c243e490SMarcel Moolenaar  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27*c243e490SMarcel Moolenaar  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*c243e490SMarcel Moolenaar  */
29*c243e490SMarcel Moolenaar 
30*c243e490SMarcel Moolenaar #include <fcntl.h>
31*c243e490SMarcel Moolenaar #include <stdio.h>
32*c243e490SMarcel Moolenaar #include <stdlib.h>
33*c243e490SMarcel Moolenaar #include <regex.h>
34*c243e490SMarcel Moolenaar #include <unistd.h>
35*c243e490SMarcel Moolenaar 
36*c243e490SMarcel Moolenaar #include "atf-c/build.h"
37*c243e490SMarcel Moolenaar #include "atf-c/check.h"
38*c243e490SMarcel Moolenaar #include "atf-c/config.h"
39*c243e490SMarcel Moolenaar #include "atf-c/error.h"
40*c243e490SMarcel Moolenaar #include "atf-c/macros.h"
41*c243e490SMarcel Moolenaar 
42*c243e490SMarcel Moolenaar #include "dynstr.h"
43*c243e490SMarcel Moolenaar #include "fs.h"
44*c243e490SMarcel Moolenaar #include "process.h"
45*c243e490SMarcel Moolenaar #include "test_helpers.h"
46*c243e490SMarcel Moolenaar 
47*c243e490SMarcel Moolenaar static
48*c243e490SMarcel Moolenaar void
49*c243e490SMarcel Moolenaar build_check_c_o_aux(const char *path, const char *failmsg,
50*c243e490SMarcel Moolenaar                     const bool expect_pass)
51*c243e490SMarcel Moolenaar {
52*c243e490SMarcel Moolenaar     bool success;
53*c243e490SMarcel Moolenaar     atf_dynstr_t iflag;
54*c243e490SMarcel Moolenaar     const char *optargs[4];
55*c243e490SMarcel Moolenaar 
56*c243e490SMarcel Moolenaar     RE(atf_dynstr_init_fmt(&iflag, "-I%s", atf_config_get("atf_includedir")));
57*c243e490SMarcel Moolenaar 
58*c243e490SMarcel Moolenaar     optargs[0] = atf_dynstr_cstring(&iflag);
59*c243e490SMarcel Moolenaar     optargs[1] = "-Wall";
60*c243e490SMarcel Moolenaar     optargs[2] = "-Werror";
61*c243e490SMarcel Moolenaar     optargs[3] = NULL;
62*c243e490SMarcel Moolenaar 
63*c243e490SMarcel Moolenaar     RE(atf_check_build_c_o(path, "test.o", optargs, &success));
64*c243e490SMarcel Moolenaar 
65*c243e490SMarcel Moolenaar     atf_dynstr_fini(&iflag);
66*c243e490SMarcel Moolenaar 
67*c243e490SMarcel Moolenaar     if ((expect_pass && !success) || (!expect_pass && success))
68*c243e490SMarcel Moolenaar         atf_tc_fail("%s", failmsg);
69*c243e490SMarcel Moolenaar }
70*c243e490SMarcel Moolenaar 
71*c243e490SMarcel Moolenaar void
72*c243e490SMarcel Moolenaar build_check_c_o(const atf_tc_t *tc, const char *sfile, const char *failmsg,
73*c243e490SMarcel Moolenaar                 const bool expect_pass)
74*c243e490SMarcel Moolenaar {
75*c243e490SMarcel Moolenaar     atf_fs_path_t path;
76*c243e490SMarcel Moolenaar 
77*c243e490SMarcel Moolenaar     RE(atf_fs_path_init_fmt(&path, "%s/%s",
78*c243e490SMarcel Moolenaar                             atf_tc_get_config_var(tc, "srcdir"), sfile));
79*c243e490SMarcel Moolenaar     build_check_c_o_aux(atf_fs_path_cstring(&path), failmsg, expect_pass);
80*c243e490SMarcel Moolenaar     atf_fs_path_fini(&path);
81*c243e490SMarcel Moolenaar }
82*c243e490SMarcel Moolenaar 
83*c243e490SMarcel Moolenaar void
84*c243e490SMarcel Moolenaar header_check(const char *hdrname)
85*c243e490SMarcel Moolenaar {
86*c243e490SMarcel Moolenaar     FILE *srcfile;
87*c243e490SMarcel Moolenaar     char failmsg[128];
88*c243e490SMarcel Moolenaar 
89*c243e490SMarcel Moolenaar     srcfile = fopen("test.c", "w");
90*c243e490SMarcel Moolenaar     ATF_REQUIRE(srcfile != NULL);
91*c243e490SMarcel Moolenaar     fprintf(srcfile, "#include <%s>\n", hdrname);
92*c243e490SMarcel Moolenaar     fclose(srcfile);
93*c243e490SMarcel Moolenaar 
94*c243e490SMarcel Moolenaar     snprintf(failmsg, sizeof(failmsg),
95*c243e490SMarcel Moolenaar              "Header check failed; %s is not self-contained", hdrname);
96*c243e490SMarcel Moolenaar 
97*c243e490SMarcel Moolenaar     build_check_c_o_aux("test.c", failmsg, true);
98*c243e490SMarcel Moolenaar }
99*c243e490SMarcel Moolenaar 
100*c243e490SMarcel Moolenaar void
101*c243e490SMarcel Moolenaar get_process_helpers_path(const atf_tc_t *tc, const bool is_detail,
102*c243e490SMarcel Moolenaar                          atf_fs_path_t *path)
103*c243e490SMarcel Moolenaar {
104*c243e490SMarcel Moolenaar     RE(atf_fs_path_init_fmt(path, "%s/%sprocess_helpers",
105*c243e490SMarcel Moolenaar                             atf_tc_get_config_var(tc, "srcdir"),
106*c243e490SMarcel Moolenaar                             is_detail ? "" : "detail/"));
107*c243e490SMarcel Moolenaar }
108*c243e490SMarcel Moolenaar 
109*c243e490SMarcel Moolenaar bool
110*c243e490SMarcel Moolenaar grep_string(const atf_dynstr_t *str, const char *regex)
111*c243e490SMarcel Moolenaar {
112*c243e490SMarcel Moolenaar     int res;
113*c243e490SMarcel Moolenaar     regex_t preg;
114*c243e490SMarcel Moolenaar 
115*c243e490SMarcel Moolenaar     printf("Looking for '%s' in '%s'\n", regex, atf_dynstr_cstring(str));
116*c243e490SMarcel Moolenaar     ATF_REQUIRE(regcomp(&preg, regex, REG_EXTENDED) == 0);
117*c243e490SMarcel Moolenaar 
118*c243e490SMarcel Moolenaar     res = regexec(&preg, atf_dynstr_cstring(str), 0, NULL, 0);
119*c243e490SMarcel Moolenaar     ATF_REQUIRE(res == 0 || res == REG_NOMATCH);
120*c243e490SMarcel Moolenaar 
121*c243e490SMarcel Moolenaar     regfree(&preg);
122*c243e490SMarcel Moolenaar 
123*c243e490SMarcel Moolenaar     return res == 0;
124*c243e490SMarcel Moolenaar }
125*c243e490SMarcel Moolenaar 
126*c243e490SMarcel Moolenaar bool
127*c243e490SMarcel Moolenaar grep_file(const char *file, const char *regex, ...)
128*c243e490SMarcel Moolenaar {
129*c243e490SMarcel Moolenaar     bool done, found;
130*c243e490SMarcel Moolenaar     int fd;
131*c243e490SMarcel Moolenaar     va_list ap;
132*c243e490SMarcel Moolenaar     atf_dynstr_t formatted;
133*c243e490SMarcel Moolenaar 
134*c243e490SMarcel Moolenaar     va_start(ap, regex);
135*c243e490SMarcel Moolenaar     RE(atf_dynstr_init_ap(&formatted, regex, ap));
136*c243e490SMarcel Moolenaar     va_end(ap);
137*c243e490SMarcel Moolenaar 
138*c243e490SMarcel Moolenaar     done = false;
139*c243e490SMarcel Moolenaar     found = false;
140*c243e490SMarcel Moolenaar     ATF_REQUIRE((fd = open(file, O_RDONLY)) != -1);
141*c243e490SMarcel Moolenaar     do {
142*c243e490SMarcel Moolenaar         atf_dynstr_t line;
143*c243e490SMarcel Moolenaar 
144*c243e490SMarcel Moolenaar         RE(atf_dynstr_init(&line));
145*c243e490SMarcel Moolenaar 
146*c243e490SMarcel Moolenaar         done = read_line(fd, &line);
147*c243e490SMarcel Moolenaar         if (!done)
148*c243e490SMarcel Moolenaar             found = grep_string(&line, atf_dynstr_cstring(&formatted));
149*c243e490SMarcel Moolenaar 
150*c243e490SMarcel Moolenaar         atf_dynstr_fini(&line);
151*c243e490SMarcel Moolenaar     } while (!found && !done);
152*c243e490SMarcel Moolenaar     close(fd);
153*c243e490SMarcel Moolenaar 
154*c243e490SMarcel Moolenaar     atf_dynstr_fini(&formatted);
155*c243e490SMarcel Moolenaar 
156*c243e490SMarcel Moolenaar     return found;
157*c243e490SMarcel Moolenaar }
158*c243e490SMarcel Moolenaar 
159*c243e490SMarcel Moolenaar bool
160*c243e490SMarcel Moolenaar read_line(int fd, atf_dynstr_t *dest)
161*c243e490SMarcel Moolenaar {
162*c243e490SMarcel Moolenaar     char ch;
163*c243e490SMarcel Moolenaar     ssize_t cnt;
164*c243e490SMarcel Moolenaar 
165*c243e490SMarcel Moolenaar     while ((cnt = read(fd, &ch, sizeof(ch))) == sizeof(ch) &&
166*c243e490SMarcel Moolenaar            ch != '\n') {
167*c243e490SMarcel Moolenaar         const atf_error_t err = atf_dynstr_append_fmt(dest, "%c", ch);
168*c243e490SMarcel Moolenaar         ATF_REQUIRE(!atf_is_error(err));
169*c243e490SMarcel Moolenaar     }
170*c243e490SMarcel Moolenaar     ATF_REQUIRE(cnt != -1);
171*c243e490SMarcel Moolenaar 
172*c243e490SMarcel Moolenaar     return cnt == 0;
173*c243e490SMarcel Moolenaar }
174*c243e490SMarcel Moolenaar 
175*c243e490SMarcel Moolenaar struct run_h_tc_data {
176*c243e490SMarcel Moolenaar     atf_tc_t *m_tc;
177*c243e490SMarcel Moolenaar     const char *m_resname;
178*c243e490SMarcel Moolenaar };
179*c243e490SMarcel Moolenaar 
180*c243e490SMarcel Moolenaar static
181*c243e490SMarcel Moolenaar void
182*c243e490SMarcel Moolenaar run_h_tc_child(void *v)
183*c243e490SMarcel Moolenaar {
184*c243e490SMarcel Moolenaar     struct run_h_tc_data *data = (struct run_h_tc_data *)v;
185*c243e490SMarcel Moolenaar 
186*c243e490SMarcel Moolenaar     RE(atf_tc_run(data->m_tc, data->m_resname));
187*c243e490SMarcel Moolenaar }
188*c243e490SMarcel Moolenaar 
189*c243e490SMarcel Moolenaar /* TODO: Investigate if it's worth to add this functionality as part of
190*c243e490SMarcel Moolenaar  * the public API.  I.e. a function to easily run a test case body in a
191*c243e490SMarcel Moolenaar  * subprocess. */
192*c243e490SMarcel Moolenaar void
193*c243e490SMarcel Moolenaar run_h_tc(atf_tc_t *tc, const char *outname, const char *errname,
194*c243e490SMarcel Moolenaar          const char *resname)
195*c243e490SMarcel Moolenaar {
196*c243e490SMarcel Moolenaar     atf_fs_path_t outpath, errpath;
197*c243e490SMarcel Moolenaar     atf_process_stream_t outb, errb;
198*c243e490SMarcel Moolenaar     atf_process_child_t child;
199*c243e490SMarcel Moolenaar     atf_process_status_t status;
200*c243e490SMarcel Moolenaar 
201*c243e490SMarcel Moolenaar     RE(atf_fs_path_init_fmt(&outpath, outname));
202*c243e490SMarcel Moolenaar     RE(atf_fs_path_init_fmt(&errpath, errname));
203*c243e490SMarcel Moolenaar 
204*c243e490SMarcel Moolenaar     struct run_h_tc_data data = { tc, resname };
205*c243e490SMarcel Moolenaar 
206*c243e490SMarcel Moolenaar     RE(atf_process_stream_init_redirect_path(&outb, &outpath));
207*c243e490SMarcel Moolenaar     RE(atf_process_stream_init_redirect_path(&errb, &errpath));
208*c243e490SMarcel Moolenaar     RE(atf_process_fork(&child, run_h_tc_child, &outb, &errb, &data));
209*c243e490SMarcel Moolenaar     atf_process_stream_fini(&errb);
210*c243e490SMarcel Moolenaar     atf_process_stream_fini(&outb);
211*c243e490SMarcel Moolenaar 
212*c243e490SMarcel Moolenaar     RE(atf_process_child_wait(&child, &status));
213*c243e490SMarcel Moolenaar     ATF_CHECK(atf_process_status_exited(&status));
214*c243e490SMarcel Moolenaar     atf_process_status_fini(&status);
215*c243e490SMarcel Moolenaar 
216*c243e490SMarcel Moolenaar     atf_fs_path_fini(&errpath);
217*c243e490SMarcel Moolenaar     atf_fs_path_fini(&outpath);
218*c243e490SMarcel Moolenaar }
219