check.c revision 1.1.1.7 1 1.1 jmmv /*
2 1.1 jmmv * Automated Testing Framework (atf)
3 1.1 jmmv *
4 1.1.1.7 jmmv * Copyright (c) 2008 The NetBSD Foundation, Inc.
5 1.1 jmmv * All rights reserved.
6 1.1 jmmv *
7 1.1 jmmv * Redistribution and use in source and binary forms, with or without
8 1.1 jmmv * modification, are permitted provided that the following conditions
9 1.1 jmmv * are met:
10 1.1 jmmv * 1. Redistributions of source code must retain the above copyright
11 1.1 jmmv * notice, this list of conditions and the following disclaimer.
12 1.1 jmmv * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 jmmv * notice, this list of conditions and the following disclaimer in the
14 1.1 jmmv * documentation and/or other materials provided with the distribution.
15 1.1 jmmv *
16 1.1 jmmv * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17 1.1 jmmv * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18 1.1 jmmv * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 1.1 jmmv * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 1.1 jmmv * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21 1.1 jmmv * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 1.1 jmmv * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23 1.1 jmmv * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 1.1 jmmv * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 1.1 jmmv * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 1.1 jmmv * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 1.1 jmmv * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 1.1 jmmv */
29 1.1 jmmv
30 1.1 jmmv #include <sys/wait.h>
31 1.1 jmmv
32 1.1 jmmv #include <errno.h>
33 1.1.1.2 jmmv #include <fcntl.h>
34 1.1 jmmv #include <stdio.h>
35 1.1 jmmv #include <stdlib.h>
36 1.1 jmmv #include <string.h>
37 1.1 jmmv #include <unistd.h>
38 1.1 jmmv
39 1.1.1.2 jmmv #include "atf-c/build.h"
40 1.1 jmmv #include "atf-c/check.h"
41 1.1 jmmv #include "atf-c/config.h"
42 1.1.1.2 jmmv #include "atf-c/defs.h"
43 1.1 jmmv #include "atf-c/error.h"
44 1.1.1.5 jmmv #include "atf-c/utils.h"
45 1.1.1.5 jmmv
46 1.1.1.5 jmmv #include "detail/dynstr.h"
47 1.1.1.5 jmmv #include "detail/fs.h"
48 1.1.1.5 jmmv #include "detail/list.h"
49 1.1.1.5 jmmv #include "detail/process.h"
50 1.1.1.5 jmmv #include "detail/sanity.h"
51 1.1 jmmv
52 1.1 jmmv /* ---------------------------------------------------------------------
53 1.1 jmmv * Auxiliary functions.
54 1.1 jmmv * --------------------------------------------------------------------- */
55 1.1 jmmv
56 1.1 jmmv static
57 1.1 jmmv atf_error_t
58 1.1.1.2 jmmv create_tmpdir(atf_fs_path_t *dir)
59 1.1 jmmv {
60 1.1 jmmv atf_error_t err;
61 1.1 jmmv
62 1.1.1.2 jmmv err = atf_fs_path_init_fmt(dir, "%s/check.XXXXXX",
63 1.1.1.2 jmmv atf_config_get("atf_workdir"));
64 1.1 jmmv if (atf_is_error(err))
65 1.1 jmmv goto out;
66 1.1 jmmv
67 1.1.1.2 jmmv err = atf_fs_mkdtemp(dir);
68 1.1.1.2 jmmv if (atf_is_error(err)) {
69 1.1.1.2 jmmv atf_fs_path_fini(dir);
70 1.1.1.2 jmmv goto out;
71 1.1.1.2 jmmv }
72 1.1 jmmv
73 1.1 jmmv INV(!atf_is_error(err));
74 1.1 jmmv out:
75 1.1 jmmv return err;
76 1.1 jmmv }
77 1.1 jmmv
78 1.1 jmmv static
79 1.1 jmmv void
80 1.1.1.2 jmmv cleanup_tmpdir(const atf_fs_path_t *dir, const atf_fs_path_t *outfile,
81 1.1.1.2 jmmv const atf_fs_path_t *errfile)
82 1.1.1.2 jmmv {
83 1.1.1.2 jmmv {
84 1.1.1.2 jmmv atf_error_t err = atf_fs_unlink(outfile);
85 1.1.1.2 jmmv if (atf_is_error(err)) {
86 1.1.1.2 jmmv INV(atf_error_is(err, "libc") &&
87 1.1.1.2 jmmv atf_libc_error_code(err) == ENOENT);
88 1.1.1.2 jmmv atf_error_free(err);
89 1.1.1.2 jmmv } else
90 1.1.1.2 jmmv INV(!atf_is_error(err));
91 1.1.1.2 jmmv }
92 1.1.1.2 jmmv
93 1.1.1.2 jmmv {
94 1.1.1.2 jmmv atf_error_t err = atf_fs_unlink(errfile);
95 1.1.1.2 jmmv if (atf_is_error(err)) {
96 1.1.1.2 jmmv INV(atf_error_is(err, "libc") &&
97 1.1.1.2 jmmv atf_libc_error_code(err) == ENOENT);
98 1.1.1.2 jmmv atf_error_free(err);
99 1.1.1.2 jmmv } else
100 1.1.1.2 jmmv INV(!atf_is_error(err));
101 1.1.1.2 jmmv }
102 1.1.1.2 jmmv
103 1.1.1.2 jmmv {
104 1.1.1.2 jmmv atf_error_t err = atf_fs_rmdir(dir);
105 1.1.1.2 jmmv INV(!atf_is_error(err));
106 1.1.1.2 jmmv }
107 1.1.1.2 jmmv }
108 1.1.1.2 jmmv
109 1.1.1.2 jmmv static
110 1.1.1.2 jmmv int
111 1.1.1.2 jmmv const_execvp(const char *file, const char *const *argv)
112 1.1.1.2 jmmv {
113 1.1.1.2 jmmv #define UNCONST(a) ((void *)(unsigned long)(const void *)(a))
114 1.1.1.2 jmmv return execvp(file, UNCONST(argv));
115 1.1.1.2 jmmv #undef UNCONST
116 1.1.1.2 jmmv }
117 1.1.1.2 jmmv
118 1.1.1.2 jmmv static
119 1.1.1.2 jmmv atf_error_t
120 1.1.1.2 jmmv init_sb(const atf_fs_path_t *path, atf_process_stream_t *sb)
121 1.1.1.2 jmmv {
122 1.1.1.2 jmmv atf_error_t err;
123 1.1.1.2 jmmv
124 1.1.1.2 jmmv if (path == NULL)
125 1.1.1.2 jmmv err = atf_process_stream_init_inherit(sb);
126 1.1.1.2 jmmv else
127 1.1.1.2 jmmv err = atf_process_stream_init_redirect_path(sb, path);
128 1.1.1.2 jmmv
129 1.1.1.2 jmmv return err;
130 1.1.1.2 jmmv }
131 1.1.1.2 jmmv
132 1.1.1.2 jmmv static
133 1.1.1.2 jmmv atf_error_t
134 1.1.1.2 jmmv init_sbs(const atf_fs_path_t *outfile, atf_process_stream_t *outsb,
135 1.1.1.2 jmmv const atf_fs_path_t *errfile, atf_process_stream_t *errsb)
136 1.1 jmmv {
137 1.1.1.2 jmmv atf_error_t err;
138 1.1.1.2 jmmv
139 1.1.1.2 jmmv err = init_sb(outfile, outsb);
140 1.1.1.2 jmmv if (atf_is_error(err))
141 1.1.1.2 jmmv goto out;
142 1.1 jmmv
143 1.1.1.2 jmmv err = init_sb(errfile, errsb);
144 1.1.1.2 jmmv if (atf_is_error(err)) {
145 1.1.1.2 jmmv atf_process_stream_fini(outsb);
146 1.1.1.2 jmmv goto out;
147 1.1.1.2 jmmv }
148 1.1.1.2 jmmv
149 1.1.1.2 jmmv out:
150 1.1.1.2 jmmv return err;
151 1.1.1.2 jmmv }
152 1.1.1.2 jmmv
153 1.1.1.2 jmmv struct exec_data {
154 1.1.1.2 jmmv const char *const *m_argv;
155 1.1.1.2 jmmv };
156 1.1.1.2 jmmv
157 1.1.1.2 jmmv static void exec_child(void *) ATF_DEFS_ATTRIBUTE_NORETURN;
158 1.1.1.2 jmmv
159 1.1.1.2 jmmv static
160 1.1.1.2 jmmv void
161 1.1.1.2 jmmv exec_child(void *v)
162 1.1.1.2 jmmv {
163 1.1.1.2 jmmv struct exec_data *ea = v;
164 1.1 jmmv
165 1.1.1.2 jmmv const_execvp(ea->m_argv[0], ea->m_argv);
166 1.1.1.2 jmmv fprintf(stderr, "execvp(%s) failed: %s\n", ea->m_argv[0], strerror(errno));
167 1.1.1.2 jmmv exit(127);
168 1.1 jmmv }
169 1.1 jmmv
170 1.1 jmmv static
171 1.1 jmmv atf_error_t
172 1.1.1.2 jmmv fork_and_wait(const char *const *argv, const atf_fs_path_t *outfile,
173 1.1.1.2 jmmv const atf_fs_path_t *errfile, atf_process_status_t *status)
174 1.1 jmmv {
175 1.1 jmmv atf_error_t err;
176 1.1.1.2 jmmv atf_process_child_t child;
177 1.1.1.2 jmmv atf_process_stream_t outsb, errsb;
178 1.1.1.2 jmmv struct exec_data ea = { argv };
179 1.1 jmmv
180 1.1.1.2 jmmv err = init_sbs(outfile, &outsb, errfile, &errsb);
181 1.1 jmmv if (atf_is_error(err))
182 1.1 jmmv goto out;
183 1.1 jmmv
184 1.1.1.2 jmmv err = atf_process_fork(&child, exec_child, &outsb, &errsb, &ea);
185 1.1.1.2 jmmv if (atf_is_error(err))
186 1.1.1.2 jmmv goto out_sbs;
187 1.1.1.2 jmmv
188 1.1.1.2 jmmv err = atf_process_child_wait(&child, status);
189 1.1.1.2 jmmv
190 1.1.1.2 jmmv out_sbs:
191 1.1.1.2 jmmv atf_process_stream_fini(&errsb);
192 1.1.1.2 jmmv atf_process_stream_fini(&outsb);
193 1.1.1.2 jmmv out:
194 1.1.1.2 jmmv return err;
195 1.1.1.2 jmmv }
196 1.1.1.2 jmmv
197 1.1.1.2 jmmv static
198 1.1.1.2 jmmv void
199 1.1.1.2 jmmv update_success_from_status(const char *progname,
200 1.1.1.2 jmmv const atf_process_status_t *status, bool *success)
201 1.1.1.2 jmmv {
202 1.1.1.2 jmmv bool s = atf_process_status_exited(status) &&
203 1.1.1.2 jmmv atf_process_status_exitstatus(status) == EXIT_SUCCESS;
204 1.1.1.2 jmmv
205 1.1.1.2 jmmv if (atf_process_status_exited(status)) {
206 1.1.1.2 jmmv if (atf_process_status_exitstatus(status) == EXIT_SUCCESS)
207 1.1.1.2 jmmv INV(s);
208 1.1.1.2 jmmv else {
209 1.1.1.2 jmmv INV(!s);
210 1.1.1.2 jmmv fprintf(stderr, "%s failed with exit code %d\n", progname,
211 1.1.1.2 jmmv atf_process_status_exitstatus(status));
212 1.1.1.2 jmmv }
213 1.1.1.2 jmmv } else if (atf_process_status_signaled(status)) {
214 1.1.1.2 jmmv INV(!s);
215 1.1.1.2 jmmv fprintf(stderr, "%s failed due to signal %d%s\n", progname,
216 1.1.1.2 jmmv atf_process_status_termsig(status),
217 1.1.1.2 jmmv atf_process_status_coredump(status) ? " (core dumped)" : "");
218 1.1 jmmv } else {
219 1.1.1.2 jmmv INV(!s);
220 1.1.1.2 jmmv fprintf(stderr, "%s failed due to unknown reason\n", progname);
221 1.1.1.2 jmmv }
222 1.1.1.2 jmmv
223 1.1.1.2 jmmv *success = s;
224 1.1.1.2 jmmv }
225 1.1.1.2 jmmv
226 1.1.1.2 jmmv static
227 1.1.1.2 jmmv atf_error_t
228 1.1.1.2 jmmv array_to_list(const char *const *a, atf_list_t *l)
229 1.1.1.2 jmmv {
230 1.1.1.2 jmmv atf_error_t err;
231 1.1.1.2 jmmv
232 1.1.1.2 jmmv err = atf_list_init(l);
233 1.1.1.2 jmmv if (atf_is_error(err))
234 1.1.1.2 jmmv goto out;
235 1.1.1.2 jmmv
236 1.1.1.2 jmmv while (*a != NULL) {
237 1.1.1.2 jmmv char *item = strdup(*a);
238 1.1.1.2 jmmv if (item == NULL) {
239 1.1.1.2 jmmv err = atf_no_memory_error();
240 1.1.1.2 jmmv goto out;
241 1.1 jmmv }
242 1.1.1.2 jmmv
243 1.1.1.2 jmmv err = atf_list_append(l, item, true);
244 1.1.1.2 jmmv if (atf_is_error(err))
245 1.1.1.2 jmmv goto out;
246 1.1.1.2 jmmv
247 1.1.1.2 jmmv a++;
248 1.1 jmmv }
249 1.1 jmmv
250 1.1 jmmv out:
251 1.1 jmmv return err;
252 1.1 jmmv }
253 1.1 jmmv
254 1.1.1.5 jmmv static void
255 1.1.1.5 jmmv print_array(const char *const *array, const char *pfx)
256 1.1.1.2 jmmv {
257 1.1.1.5 jmmv const char *const *ptr;
258 1.1.1.2 jmmv
259 1.1.1.2 jmmv printf("%s", pfx);
260 1.1.1.5 jmmv for (ptr = array; *ptr != NULL; ptr++)
261 1.1.1.5 jmmv printf(" %s", *ptr);
262 1.1.1.2 jmmv printf("\n");
263 1.1.1.2 jmmv }
264 1.1.1.2 jmmv
265 1.1.1.2 jmmv static
266 1.1.1.2 jmmv atf_error_t
267 1.1.1.5 jmmv check_build_run(const char *const *argv, bool *success)
268 1.1.1.2 jmmv {
269 1.1.1.2 jmmv atf_error_t err;
270 1.1.1.2 jmmv atf_process_status_t status;
271 1.1.1.2 jmmv
272 1.1.1.5 jmmv print_array(argv, ">");
273 1.1.1.2 jmmv
274 1.1.1.5 jmmv err = fork_and_wait(argv, NULL, NULL, &status);
275 1.1.1.2 jmmv if (atf_is_error(err))
276 1.1.1.2 jmmv goto out;
277 1.1.1.2 jmmv
278 1.1.1.5 jmmv update_success_from_status(argv[0], &status, success);
279 1.1.1.2 jmmv atf_process_status_fini(&status);
280 1.1.1.2 jmmv
281 1.1.1.2 jmmv INV(!atf_is_error(err));
282 1.1.1.2 jmmv out:
283 1.1.1.2 jmmv return err;
284 1.1.1.2 jmmv }
285 1.1.1.2 jmmv
286 1.1 jmmv /* ---------------------------------------------------------------------
287 1.1 jmmv * The "atf_check_result" type.
288 1.1 jmmv * --------------------------------------------------------------------- */
289 1.1 jmmv
290 1.1.1.5 jmmv struct atf_check_result_impl {
291 1.1.1.5 jmmv atf_list_t m_argv;
292 1.1.1.5 jmmv atf_fs_path_t m_dir;
293 1.1.1.5 jmmv atf_fs_path_t m_stdout;
294 1.1.1.5 jmmv atf_fs_path_t m_stderr;
295 1.1.1.5 jmmv atf_process_status_t m_status;
296 1.1.1.5 jmmv };
297 1.1.1.5 jmmv
298 1.1.1.2 jmmv static
299 1.1 jmmv atf_error_t
300 1.1.1.2 jmmv atf_check_result_init(atf_check_result_t *r, const char *const *argv,
301 1.1.1.2 jmmv const atf_fs_path_t *dir)
302 1.1 jmmv {
303 1.1 jmmv atf_error_t err;
304 1.1 jmmv
305 1.1.1.5 jmmv r->pimpl = malloc(sizeof(struct atf_check_result_impl));
306 1.1.1.5 jmmv if (r->pimpl == NULL)
307 1.1.1.5 jmmv return atf_no_memory_error();
308 1.1.1.5 jmmv
309 1.1.1.5 jmmv err = array_to_list(argv, &r->pimpl->m_argv);
310 1.1 jmmv if (atf_is_error(err))
311 1.1 jmmv goto out;
312 1.1 jmmv
313 1.1.1.5 jmmv err = atf_fs_path_copy(&r->pimpl->m_dir, dir);
314 1.1.1.2 jmmv if (atf_is_error(err))
315 1.1.1.2 jmmv goto err_argv;
316 1.1.1.2 jmmv
317 1.1.1.5 jmmv err = atf_fs_path_init_fmt(&r->pimpl->m_stdout, "%s/stdout",
318 1.1.1.2 jmmv atf_fs_path_cstring(dir));
319 1.1.1.2 jmmv if (atf_is_error(err))
320 1.1.1.2 jmmv goto err_dir;
321 1.1.1.2 jmmv
322 1.1.1.5 jmmv err = atf_fs_path_init_fmt(&r->pimpl->m_stderr, "%s/stderr",
323 1.1.1.2 jmmv atf_fs_path_cstring(dir));
324 1.1 jmmv if (atf_is_error(err))
325 1.1 jmmv goto err_stdout;
326 1.1 jmmv
327 1.1 jmmv INV(!atf_is_error(err));
328 1.1 jmmv goto out;
329 1.1 jmmv
330 1.1 jmmv err_stdout:
331 1.1.1.5 jmmv atf_fs_path_fini(&r->pimpl->m_stdout);
332 1.1.1.2 jmmv err_dir:
333 1.1.1.5 jmmv atf_fs_path_fini(&r->pimpl->m_dir);
334 1.1.1.2 jmmv err_argv:
335 1.1.1.5 jmmv atf_list_fini(&r->pimpl->m_argv);
336 1.1 jmmv out:
337 1.1 jmmv return err;
338 1.1 jmmv }
339 1.1 jmmv
340 1.1 jmmv void
341 1.1 jmmv atf_check_result_fini(atf_check_result_t *r)
342 1.1 jmmv {
343 1.1.1.5 jmmv atf_process_status_fini(&r->pimpl->m_status);
344 1.1 jmmv
345 1.1.1.5 jmmv cleanup_tmpdir(&r->pimpl->m_dir, &r->pimpl->m_stdout,
346 1.1.1.5 jmmv &r->pimpl->m_stderr);
347 1.1.1.5 jmmv atf_fs_path_fini(&r->pimpl->m_stdout);
348 1.1.1.5 jmmv atf_fs_path_fini(&r->pimpl->m_stderr);
349 1.1.1.5 jmmv atf_fs_path_fini(&r->pimpl->m_dir);
350 1.1.1.2 jmmv
351 1.1.1.5 jmmv atf_list_fini(&r->pimpl->m_argv);
352 1.1 jmmv
353 1.1.1.5 jmmv free(r->pimpl);
354 1.1.1.2 jmmv }
355 1.1.1.2 jmmv
356 1.1.1.5 jmmv const char *
357 1.1 jmmv atf_check_result_stdout(const atf_check_result_t *r)
358 1.1 jmmv {
359 1.1.1.5 jmmv return atf_fs_path_cstring(&r->pimpl->m_stdout);
360 1.1 jmmv }
361 1.1 jmmv
362 1.1.1.5 jmmv const char *
363 1.1 jmmv atf_check_result_stderr(const atf_check_result_t *r)
364 1.1 jmmv {
365 1.1.1.5 jmmv return atf_fs_path_cstring(&r->pimpl->m_stderr);
366 1.1 jmmv }
367 1.1 jmmv
368 1.1 jmmv bool
369 1.1 jmmv atf_check_result_exited(const atf_check_result_t *r)
370 1.1 jmmv {
371 1.1.1.5 jmmv return atf_process_status_exited(&r->pimpl->m_status);
372 1.1 jmmv }
373 1.1 jmmv
374 1.1 jmmv int
375 1.1 jmmv atf_check_result_exitcode(const atf_check_result_t *r)
376 1.1 jmmv {
377 1.1.1.5 jmmv return atf_process_status_exitstatus(&r->pimpl->m_status);
378 1.1 jmmv }
379 1.1 jmmv
380 1.1.1.4 jmmv bool
381 1.1.1.4 jmmv atf_check_result_signaled(const atf_check_result_t *r)
382 1.1.1.4 jmmv {
383 1.1.1.5 jmmv return atf_process_status_signaled(&r->pimpl->m_status);
384 1.1.1.4 jmmv }
385 1.1.1.4 jmmv
386 1.1.1.4 jmmv int
387 1.1.1.4 jmmv atf_check_result_termsig(const atf_check_result_t *r)
388 1.1.1.4 jmmv {
389 1.1.1.5 jmmv return atf_process_status_termsig(&r->pimpl->m_status);
390 1.1.1.4 jmmv }
391 1.1.1.4 jmmv
392 1.1 jmmv /* ---------------------------------------------------------------------
393 1.1 jmmv * Free functions.
394 1.1 jmmv * --------------------------------------------------------------------- */
395 1.1 jmmv
396 1.1.1.2 jmmv /* XXX: This function shouldn't be in this module. It messes with stdout
397 1.1.1.2 jmmv * and stderr, and it provides a very high-end interface. This belongs,
398 1.1.1.2 jmmv * probably, somewhere related to test cases (such as in the tc module). */
399 1.1.1.2 jmmv atf_error_t
400 1.1.1.2 jmmv atf_check_build_c_o(const char *sfile,
401 1.1.1.2 jmmv const char *ofile,
402 1.1.1.2 jmmv const char *const optargs[],
403 1.1.1.2 jmmv bool *success)
404 1.1.1.2 jmmv {
405 1.1.1.2 jmmv atf_error_t err;
406 1.1.1.5 jmmv char **argv;
407 1.1.1.2 jmmv
408 1.1.1.2 jmmv err = atf_build_c_o(sfile, ofile, optargs, &argv);
409 1.1.1.2 jmmv if (atf_is_error(err))
410 1.1.1.2 jmmv goto out;
411 1.1.1.2 jmmv
412 1.1.1.5 jmmv err = check_build_run((const char *const *)argv, success);
413 1.1.1.2 jmmv
414 1.1.1.5 jmmv atf_utils_free_charpp(argv);
415 1.1.1.2 jmmv out:
416 1.1.1.2 jmmv return err;
417 1.1.1.2 jmmv }
418 1.1.1.2 jmmv
419 1.1 jmmv atf_error_t
420 1.1.1.2 jmmv atf_check_build_cpp(const char *sfile,
421 1.1.1.2 jmmv const char *ofile,
422 1.1.1.2 jmmv const char *const optargs[],
423 1.1.1.2 jmmv bool *success)
424 1.1 jmmv {
425 1.1 jmmv atf_error_t err;
426 1.1.1.5 jmmv char **argv;
427 1.1 jmmv
428 1.1.1.2 jmmv err = atf_build_cpp(sfile, ofile, optargs, &argv);
429 1.1 jmmv if (atf_is_error(err))
430 1.1 jmmv goto out;
431 1.1 jmmv
432 1.1.1.5 jmmv err = check_build_run((const char *const *)argv, success);
433 1.1.1.2 jmmv
434 1.1.1.5 jmmv atf_utils_free_charpp(argv);
435 1.1.1.2 jmmv out:
436 1.1.1.2 jmmv return err;
437 1.1.1.2 jmmv }
438 1.1.1.2 jmmv
439 1.1.1.2 jmmv atf_error_t
440 1.1.1.2 jmmv atf_check_build_cxx_o(const char *sfile,
441 1.1.1.2 jmmv const char *ofile,
442 1.1.1.2 jmmv const char *const optargs[],
443 1.1.1.2 jmmv bool *success)
444 1.1.1.2 jmmv {
445 1.1.1.2 jmmv atf_error_t err;
446 1.1.1.5 jmmv char **argv;
447 1.1.1.2 jmmv
448 1.1.1.2 jmmv err = atf_build_cxx_o(sfile, ofile, optargs, &argv);
449 1.1 jmmv if (atf_is_error(err))
450 1.1.1.2 jmmv goto out;
451 1.1.1.2 jmmv
452 1.1.1.5 jmmv err = check_build_run((const char *const *)argv, success);
453 1.1 jmmv
454 1.1.1.5 jmmv atf_utils_free_charpp(argv);
455 1.1.1.2 jmmv out:
456 1.1.1.2 jmmv return err;
457 1.1.1.2 jmmv }
458 1.1.1.2 jmmv
459 1.1.1.2 jmmv atf_error_t
460 1.1.1.2 jmmv atf_check_exec_array(const char *const *argv, atf_check_result_t *r)
461 1.1.1.2 jmmv {
462 1.1.1.2 jmmv atf_error_t err;
463 1.1.1.2 jmmv atf_fs_path_t dir;
464 1.1.1.2 jmmv
465 1.1.1.2 jmmv err = create_tmpdir(&dir);
466 1.1.1.2 jmmv if (atf_is_error(err))
467 1.1.1.2 jmmv goto out;
468 1.1.1.2 jmmv
469 1.1.1.2 jmmv err = atf_check_result_init(r, argv, &dir);
470 1.1.1.6 jmmv if (atf_is_error(err)) {
471 1.1.1.6 jmmv atf_error_t err2 = atf_fs_rmdir(&dir);
472 1.1.1.6 jmmv INV(!atf_is_error(err2));
473 1.1.1.6 jmmv goto out;
474 1.1.1.6 jmmv }
475 1.1.1.2 jmmv
476 1.1.1.5 jmmv err = fork_and_wait(argv, &r->pimpl->m_stdout, &r->pimpl->m_stderr,
477 1.1.1.5 jmmv &r->pimpl->m_status);
478 1.1.1.6 jmmv if (atf_is_error(err)) {
479 1.1.1.6 jmmv atf_check_result_fini(r);
480 1.1.1.6 jmmv goto out;
481 1.1.1.6 jmmv }
482 1.1 jmmv
483 1.1 jmmv INV(!atf_is_error(err));
484 1.1 jmmv
485 1.1.1.2 jmmv atf_fs_path_fini(&dir);
486 1.1.1.2 jmmv out:
487 1.1.1.2 jmmv return err;
488 1.1.1.2 jmmv }
489