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