usr.sbin/makefs: Sync with sys/vfs/hammer2
[dragonfly.git] / usr.bin / dfregress / runlist.c
blob723069e2d8e46c0cf114e9731af81d9315ec8e94
1 /*
2 * Copyright (c) 2011 Alex Hornung <alex@alexhornung.com>.
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
14 * distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
30 #include <sys/resource.h>
31 #include <sys/time.h>
32 #include <sys/types.h>
33 #include <sys/wait.h>
35 #include <errno.h>
36 #include <limits.h>
37 #include <fcntl.h>
38 #include <signal.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <stdint.h>
42 #include <string.h>
43 #include <unistd.h>
44 #include <pwd.h>
46 #include <err.h>
48 #include <libprop/proplib.h>
50 #include "parser.h"
51 #include "testcase.h"
52 #include "runlist.h"
53 #include "userland.h"
54 #include "kernel.h"
55 #include <dfregress.h>
57 char output_file[PATH_MAX+1];
58 char testcase_dir[PATH_MAX+1];
59 char prepost_dir[PATH_MAX+1];
61 prop_array_t
62 runlist_load_from_text(const char *runlist_file)
64 prop_array_t runlist;
66 runlist = prop_array_create_with_capacity(2048);
68 process_file(runlist_file, testcase_entry_parser, runlist, NULL);
70 return runlist;
73 prop_array_t
74 runlist_load(const char *runlist_file)
76 return prop_array_internalize_from_file(runlist_file);
79 int
80 runlist_save(const char *runlist_file, prop_array_t runlist)
82 return !prop_array_externalize_to_file(runlist, runlist_file);
85 int
86 runlist_iterate(prop_array_t runlist, runlist_iterator_t iterator, void *arg)
88 prop_object_iterator_t it;
89 prop_dictionary_t testcase;
90 int r = 0;
92 it = prop_array_iterator(runlist);
93 if (it == NULL)
94 err(1, "could not get runlist iterator");
96 while ((testcase = prop_object_iterator_next(it)) != NULL) {
97 r = iterator(arg, testcase);
98 if (r != 0)
99 break;
102 prop_object_iterator_release(it);
103 return r;
107 runlist_run_test(void *arg, prop_dictionary_t testcase)
109 prop_array_t runlist = (prop_array_t)arg;
110 struct testcase_result tr;
111 char testcase_path[FILENAME_MAX+2];
112 char testcase_dir_only[FILENAME_MAX];
113 char prepost_path[FILENAME_MAX+2];
114 char errbuf[FILENAME_MAX*2];
115 int r, nopre, nopost;
116 char *str;
118 sprintf(testcase_path, "%s/%s", testcase_dir,
119 testcase_get_name(testcase));
120 strcpy(testcase_dir_only, testcase_path);
121 str = strrchr(testcase_dir_only, '/');
122 if (str != NULL)
123 *str = '\0';
125 printf("Running testcase %s... ", testcase_get_name(testcase));
126 fflush(stdout);
128 /* Switch to testcase directory */
129 r = chdir(testcase_dir_only);
130 if (r < 0) {
131 sprintf(errbuf, "could not switch working directory to %s: %s\n",
132 testcase_dir_only, strerror(errno));
133 testcase_set_result(testcase, RESULT_PREFAIL);
134 testcase_set_sys_buf(testcase, errbuf);
135 goto out;
138 /* build unless nobuild flag is set */
139 if ((testcase_get_flags(testcase) & TESTCASE_NOBUILD) == 0) {
140 r = run_simple_cmd(testcase_get_make_cmd(testcase), NULL,
141 errbuf, sizeof(errbuf), &tr);
142 if (r != 0) {
143 testcase_set_sys_buf(testcase, errbuf);
144 testcase_set_result(testcase, RESULT_PREFAIL);
145 goto out;
148 if (tr.stdout_buf != NULL) {
149 testcase_set_build_buf(testcase, tr.stdout_buf);
150 free(tr.stdout_buf);
153 if (tr.result != RESULT_PASS) {
154 if (testcase_get_type(testcase)
155 == TESTCASE_TYPE_BUILDONLY)
156 testcase_set_result(testcase, tr.result);
157 else
158 testcase_set_result(testcase, RESULT_BUILDFAIL);
160 testcase_set_exit_value(testcase, tr.exit_value);
161 testcase_set_signal(testcase, tr.signal);
163 goto out;
168 /* Pre-execution run */
169 switch (testcase_get_precmd_type(testcase)) {
170 case TESTCASE_INT_PRE:
171 /* Test case has internal but explicit PRE - code */
172 r = run_simple_cmd(testcase_path, "pre", errbuf,
173 sizeof(errbuf), &tr);
174 nopre = 0;
175 break;
177 case TESTCASE_CUSTOM_PRE:
178 /* Test case uses external and explicit PRE command */
179 sprintf(prepost_path, "%s/%s", prepost_dir,
180 testcase_get_custom_precmd(testcase));
182 r = run_simple_cmd(prepost_path, NULL, errbuf, sizeof(errbuf),
183 &tr);
184 nopre = 0;
185 break;
187 default:
188 nopre = 1;
189 r = 0;
190 break;
193 if (!nopre) {
194 if (r != 0) {
195 testcase_set_sys_buf(testcase, errbuf);
196 testcase_set_result(testcase, RESULT_PREFAIL);
197 goto out;
200 if (tr.stdout_buf != NULL) {
201 testcase_set_precmd_buf(testcase, tr.stdout_buf);
202 free(tr.stdout_buf);
205 if (tr.result != RESULT_PASS) {
206 testcase_set_result(testcase, RESULT_PREFAIL);
207 goto out;
211 switch (testcase_get_type(testcase)) {
212 case TESTCASE_TYPE_BUILDONLY:
213 testcase_set_result(testcase, RESULT_PASS);
214 testcase_set_exit_value(testcase, 0);
215 break;
217 case TESTCASE_TYPE_USERLAND:
218 /* Main testcase execution */
219 r = run_userland(testcase_path,
220 testcase_get_argc(testcase),
221 testcase_get_args(testcase),
222 testcase_get_interpreter_noexit(testcase),
223 testcase_needs_setuid(testcase),
224 testcase_get_runas_uid(testcase),
225 testcase_get_timeout(testcase),
226 testcase_get_rc(testcase),
227 0, errbuf, sizeof(errbuf), &tr);
229 if (r == 0) {
230 testcase_set_result(testcase, tr.result);
231 testcase_set_exit_value(testcase, tr.exit_value);
232 testcase_set_signal(testcase, tr.signal);
234 if (tr.stdout_buf != NULL) {
235 testcase_set_stdout_buf(testcase, tr.stdout_buf);
236 free(tr.stdout_buf);
239 if (tr.stderr_buf != NULL) {
240 testcase_set_stderr_buf(testcase, tr.stderr_buf);
241 free(tr.stderr_buf);
243 } else {
244 /* driver/monitor error */
245 testcase_set_sys_buf(testcase, errbuf);
248 break;
250 case TESTCASE_TYPE_KERNEL:
251 run_kernel(testcase_path, testcase);
252 break;
256 /* Post-execution run */
257 switch (testcase_get_postcmd_type(testcase)) {
258 case TESTCASE_INT_POST:
259 /* Test case has internal but explicit POST - code */
260 r = run_simple_cmd(testcase_path, "post", errbuf,
261 sizeof(errbuf), &tr);
262 nopost = 0;
263 break;
265 case TESTCASE_CUSTOM_POST:
266 /* Test case uses external and explicit POST command */
267 sprintf(prepost_path, "%s/%s", prepost_dir,
268 testcase_get_custom_postcmd(testcase));
270 r = run_simple_cmd(prepost_path, NULL, errbuf, sizeof(errbuf),
271 &tr);
272 nopost = 0;
273 break;
275 default:
276 r = 0;
277 nopost = 1;
278 break;
281 if (!nopost) {
282 if (r != 0) {
283 testcase_set_sys_buf(testcase, errbuf);
284 testcase_set_result(testcase, RESULT_POSTFAIL);
285 goto out;
288 if (tr.stdout_buf != NULL) {
289 testcase_set_postcmd_buf(testcase, tr.stdout_buf);
290 free(tr.stdout_buf);
293 if (tr.result != RESULT_PASS) {
294 testcase_set_result(testcase, RESULT_POSTFAIL);
295 goto out;
301 out:
302 /* clean build unless nobuild flag is set */
303 if ((testcase_get_flags(testcase) & TESTCASE_NOBUILD) == 0) {
304 r = run_simple_cmd(testcase_get_make_cmd(testcase), "clean",
305 errbuf, sizeof(errbuf), &tr);
307 if (tr.stdout_buf != NULL) {
308 testcase_set_cleanup_buf(testcase, tr.stdout_buf);
309 free(tr.stdout_buf);
312 if (r != 0)
313 testcase_set_cleanup_buf(testcase, errbuf);
317 /* ... and save results */
318 runlist_save(output_file, runlist);
320 printf("done.\n");
321 return 0;