xref: /dragonfly/usr.bin/dfregress/testcase.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>
36a563ca70SAlex Hornung #include <signal.h>
37a563ca70SAlex Hornung #include <stdio.h>
38a563ca70SAlex Hornung #include <stdlib.h>
39a563ca70SAlex Hornung #include <stdint.h>
40a563ca70SAlex Hornung #include <string.h>
41a563ca70SAlex Hornung #include <unistd.h>
42a563ca70SAlex Hornung #include <pwd.h>
43a563ca70SAlex Hornung 
44a563ca70SAlex Hornung #include <err.h>
45a563ca70SAlex Hornung 
46a563ca70SAlex Hornung #include <libprop/proplib.h>
47a563ca70SAlex Hornung 
48a563ca70SAlex Hornung #include "parser.h"
49a563ca70SAlex Hornung #include "testcase.h"
50a563ca70SAlex Hornung #include "runlist.h"
51a563ca70SAlex Hornung #include "config.h"
52a563ca70SAlex Hornung #include <dfregress.h>
53a563ca70SAlex Hornung 
54a563ca70SAlex Hornung prop_dictionary_t
testcase_from_struct(struct testcase * testcase)55a563ca70SAlex Hornung testcase_from_struct(struct testcase *testcase)
56a563ca70SAlex Hornung {
57a563ca70SAlex Hornung 	int i, r;
58a563ca70SAlex Hornung 	prop_dictionary_t dict, testcase_dict;
59a563ca70SAlex Hornung 	prop_array_t a;
60a563ca70SAlex Hornung 	char *s;
61a563ca70SAlex Hornung 
62a563ca70SAlex Hornung 	testcase_dict = prop_dictionary_create();
63a563ca70SAlex Hornung 	if (testcase_dict == NULL)
64a563ca70SAlex Hornung 		err(1, "could not create testcase dict");
65a563ca70SAlex Hornung 	r = prop_dictionary_set_cstring(testcase_dict, "name", testcase->name);
66a563ca70SAlex Hornung 	if (r == 0)
67a563ca70SAlex Hornung 		err(1, "prop_dictionary operation failed");
68a563ca70SAlex Hornung 	r = prop_dictionary_set_cstring(testcase_dict, "type", testcase->type_str);
69a563ca70SAlex Hornung 	if (r == 0)
70a563ca70SAlex Hornung 		err(1, "prop_dictionary operation failed");
71a563ca70SAlex Hornung 
720d575305SAntonio Huete Jimenez 	r = prop_dictionary_set_int32(testcase_dict, "argc",
730d575305SAntonio Huete Jimenez 	    (int32_t)testcase->argc);
740d575305SAntonio Huete Jimenez 	if (r == 0)
750d575305SAntonio Huete Jimenez 		err(1, "prop_dictionary operation failed");
760d575305SAntonio Huete Jimenez 
77a563ca70SAlex Hornung 	a = prop_array_create_with_capacity(testcase->argc+1);
78a563ca70SAlex Hornung 	if (a == NULL)
79a563ca70SAlex Hornung 		err(1, "prop_array_create for argv failed");
80a563ca70SAlex Hornung 
81a563ca70SAlex Hornung 	s = strrchr(testcase->name, '/');
82a563ca70SAlex Hornung 	r = prop_array_set_cstring(a, 0, (s == NULL) ? testcase->name : s+1);
83a563ca70SAlex Hornung 	if (r == 0)
84a563ca70SAlex Hornung 		err(1, "prop_array_set_cstring operation failed");
85a563ca70SAlex Hornung 
86a563ca70SAlex Hornung 	for (i = 1; i <= testcase->argc; i++) {
87a563ca70SAlex Hornung 		r = prop_array_set_cstring(a, i, testcase->argv[i-1]);
88a563ca70SAlex Hornung 		if (r == 0)
89a563ca70SAlex Hornung 			err(1, "prop_array_set_cstring operation failed");
90a563ca70SAlex Hornung 	}
91a563ca70SAlex Hornung 
92a563ca70SAlex Hornung 	r = prop_dictionary_set(testcase_dict, "args", a);
93a563ca70SAlex Hornung 	if (r == 0)
94a563ca70SAlex Hornung 		err(1, "prop_dictionary_set \"args\" failed");
95a563ca70SAlex Hornung 
96a563ca70SAlex Hornung 	dict = prop_dictionary_create();
97a563ca70SAlex Hornung 	if (dict == NULL)
98a563ca70SAlex Hornung 		err(1, "could not create dict");
99a563ca70SAlex Hornung 
100a563ca70SAlex Hornung 	r = prop_dictionary_set_int32(dict, "timeout_in_secs",
101a563ca70SAlex Hornung 	    (int32_t)testcase->opts.timeout_in_secs);
102a563ca70SAlex Hornung 	if (r == 0)
103a563ca70SAlex Hornung 		err(1, "prop_dictionary operation failed");
104a563ca70SAlex Hornung 
105*039caa27SAntonio Huete Jimenez 	r = prop_dictionary_set_int32(dict, "rc",
106*039caa27SAntonio Huete Jimenez 	    (int32_t)testcase->opts.rc);
107*039caa27SAntonio Huete Jimenez 	if (r == 0)
108*039caa27SAntonio Huete Jimenez 		err(1, "prop_dictionary operation failed");
109*039caa27SAntonio Huete Jimenez 
110a563ca70SAlex Hornung 	r = prop_dictionary_set_uint32(dict, "flags", testcase->opts.flags);
111a563ca70SAlex Hornung 	if (r == 0)
112a563ca70SAlex Hornung 		err(1, "prop_dictionary operation failed");
113a563ca70SAlex Hornung 
114a563ca70SAlex Hornung 	if (testcase->opts.pre_cmd != NULL) {
115a563ca70SAlex Hornung 		r = prop_dictionary_set_cstring(dict, "pre_cmd",
116a563ca70SAlex Hornung 		    testcase->opts.pre_cmd);
117a563ca70SAlex Hornung 		if (r == 0)
118a563ca70SAlex Hornung 			err(1, "prop_dictionary operation failed");
119a563ca70SAlex Hornung 	}
120a563ca70SAlex Hornung 
121a563ca70SAlex Hornung 	if (testcase->opts.post_cmd != NULL) {
122a563ca70SAlex Hornung 		r = prop_dictionary_set_cstring(dict, "post_cmd",
123a563ca70SAlex Hornung 		    testcase->opts.post_cmd);
124a563ca70SAlex Hornung 		if (r == 0)
125a563ca70SAlex Hornung 			err(1, "prop_dictionary operation failed");
126a563ca70SAlex Hornung 	}
127a563ca70SAlex Hornung 
1280d575305SAntonio Huete Jimenez 	if (testcase->opts.interpreter != NULL) {
1290d575305SAntonio Huete Jimenez 		r = prop_dictionary_set_cstring(dict, "interpreter",
1300d575305SAntonio Huete Jimenez 		    testcase->opts.interpreter);
1310d575305SAntonio Huete Jimenez 		if (r == 0)
1320d575305SAntonio Huete Jimenez 			err(1, "prop_dictionary operation failed");
1330d575305SAntonio Huete Jimenez 	}
1340d575305SAntonio Huete Jimenez 
135a563ca70SAlex Hornung 	r = prop_dictionary_set_uint32(dict, "runas_uid",
136a563ca70SAlex Hornung 	    (uint32_t)testcase->opts.runas_uid);
137a563ca70SAlex Hornung 	if (r == 0)
138a563ca70SAlex Hornung 		err(1, "prop_dictionary operation failed");
139a563ca70SAlex Hornung 
140a563ca70SAlex Hornung 	r = prop_dictionary_set_cstring(dict, "make_cmd",
141a563ca70SAlex Hornung 	    (testcase->opts.make_cmd != NULL) ? testcase->opts.make_cmd : "make");
142a563ca70SAlex Hornung 	if (r == 0)
143a563ca70SAlex Hornung 		err(1, "prop_dictionary operation failed");
144a563ca70SAlex Hornung 
145a563ca70SAlex Hornung 	r = prop_dictionary_set(testcase_dict, "opts", dict);
146a563ca70SAlex Hornung 	if (r == 0)
147a563ca70SAlex Hornung 		err(1, "prop_dictionary operation failed");
148a563ca70SAlex Hornung 
149a563ca70SAlex Hornung 	return testcase_dict;
150a563ca70SAlex Hornung }
151a563ca70SAlex Hornung 
152a563ca70SAlex Hornung struct timeval *
testcase_get_timeout(prop_dictionary_t testcase)153a563ca70SAlex Hornung testcase_get_timeout(prop_dictionary_t testcase)
154a563ca70SAlex Hornung {
155a563ca70SAlex Hornung 	static struct timeval tv;
156a563ca70SAlex Hornung 	int32_t val;
157a563ca70SAlex Hornung 	int r;
158a563ca70SAlex Hornung 
159a563ca70SAlex Hornung 	r = prop_dictionary_get_int32(prop_dictionary_get(testcase, "opts"),
160a563ca70SAlex Hornung 	    "timeout_in_secs", &val);
161a563ca70SAlex Hornung 	if (r == 0)
162a563ca70SAlex Hornung 		err(1, "prop_dictionary operation failed");
163a563ca70SAlex Hornung 
164a563ca70SAlex Hornung 	tv.tv_usec = 0;
165a563ca70SAlex Hornung 	tv.tv_sec = (long)val;
166a563ca70SAlex Hornung 
167a563ca70SAlex Hornung 	return &tv;
168a563ca70SAlex Hornung }
169a563ca70SAlex Hornung 
170a563ca70SAlex Hornung int
testcase_get_type(prop_dictionary_t testcase)171a563ca70SAlex Hornung testcase_get_type(prop_dictionary_t testcase)
172a563ca70SAlex Hornung {
173a563ca70SAlex Hornung 	const char *type;
174a563ca70SAlex Hornung 	int r;
175a563ca70SAlex Hornung 
176a563ca70SAlex Hornung 	r = prop_dictionary_get_cstring_nocopy(testcase, "type", &type);
177a563ca70SAlex Hornung 	if (r == 0)
178a563ca70SAlex Hornung 		err(1, "prop_dictionary operation failed");
179a563ca70SAlex Hornung 
180a563ca70SAlex Hornung 	if (strcmp(type, "userland") == 0)
181a563ca70SAlex Hornung 		return TESTCASE_TYPE_USERLAND;
182a563ca70SAlex Hornung 	else if (strcmp(type, "kernel") == 0)
183a563ca70SAlex Hornung 		return TESTCASE_TYPE_KERNEL;
184a563ca70SAlex Hornung 	else if (strcmp(type, "buildonly") == 0)
185a563ca70SAlex Hornung 		return TESTCASE_TYPE_BUILDONLY;
186a563ca70SAlex Hornung 
187a563ca70SAlex Hornung 	return 0;
188a563ca70SAlex Hornung }
189a563ca70SAlex Hornung 
190a563ca70SAlex Hornung const char *
testcase_get_type_desc(prop_dictionary_t testcase)191a563ca70SAlex Hornung testcase_get_type_desc(prop_dictionary_t testcase)
192a563ca70SAlex Hornung {
193a563ca70SAlex Hornung 	const char *str;
194a563ca70SAlex Hornung 	int r;
195a563ca70SAlex Hornung 
196a563ca70SAlex Hornung 	r = prop_dictionary_get_cstring_nocopy(testcase, "type", &str);
197a563ca70SAlex Hornung 	if (r == 0)
198a563ca70SAlex Hornung 		err(1, "prop_dictionary operation failed");
199a563ca70SAlex Hornung 
200a563ca70SAlex Hornung 	return str;
201a563ca70SAlex Hornung }
202a563ca70SAlex Hornung 
203a563ca70SAlex Hornung const char *
testcase_get_name(prop_dictionary_t testcase)204a563ca70SAlex Hornung testcase_get_name(prop_dictionary_t testcase)
205a563ca70SAlex Hornung {
206a563ca70SAlex Hornung 	const char *str;
207a563ca70SAlex Hornung 	int r;
208a563ca70SAlex Hornung 
209a563ca70SAlex Hornung 	r = prop_dictionary_get_cstring_nocopy(testcase, "name", &str);
210a563ca70SAlex Hornung 	if (r == 0)
211a563ca70SAlex Hornung 		err(1, "prop_dictionary operation failed");
212a563ca70SAlex Hornung 
213a563ca70SAlex Hornung 	return str;
214a563ca70SAlex Hornung }
215a563ca70SAlex Hornung 
2160d575305SAntonio Huete Jimenez int
testcase_get_argc(prop_dictionary_t testcase)2170d575305SAntonio Huete Jimenez testcase_get_argc(prop_dictionary_t testcase)
2180d575305SAntonio Huete Jimenez {
2190d575305SAntonio Huete Jimenez 	int32_t argc;
2200d575305SAntonio Huete Jimenez 	int r;
2210d575305SAntonio Huete Jimenez 
2220d575305SAntonio Huete Jimenez 	r = prop_dictionary_get_int32(testcase, "argc", &argc);
2230d575305SAntonio Huete Jimenez 	if (r == 0)
2240d575305SAntonio Huete Jimenez 		err(1, "prop_dictionary operation failed for argc");
2250d575305SAntonio Huete Jimenez 
2260d575305SAntonio Huete Jimenez 	return argc;
2270d575305SAntonio Huete Jimenez }
2280d575305SAntonio Huete Jimenez 
229a563ca70SAlex Hornung const char **
testcase_get_args(prop_dictionary_t testcase)230a563ca70SAlex Hornung testcase_get_args(prop_dictionary_t testcase)
231a563ca70SAlex Hornung {
232a563ca70SAlex Hornung 	/* Sane limit of 63 arguments... who wants more than that? */
233a563ca70SAlex Hornung 	static const char *argv[64];
234a563ca70SAlex Hornung 	unsigned int i, count;
235a563ca70SAlex Hornung 	prop_array_t a;
236a563ca70SAlex Hornung 	int r;
237a563ca70SAlex Hornung 
238a563ca70SAlex Hornung 	a = prop_dictionary_get(testcase, "args");
239a563ca70SAlex Hornung 	if (a == NULL)
240a563ca70SAlex Hornung 		err(1, "testcase_get_args NULL array");
241a563ca70SAlex Hornung 
242a563ca70SAlex Hornung 	count = prop_array_count(a);
243a563ca70SAlex Hornung 
244a563ca70SAlex Hornung 	for (i = 0; i < count; i++) {
245a563ca70SAlex Hornung 		r = prop_array_get_cstring_nocopy(a, i, &argv[i]);
246a563ca70SAlex Hornung 		if (r == 0)
247a563ca70SAlex Hornung 			err(1, "error building argv");
248a563ca70SAlex Hornung 	}
249a563ca70SAlex Hornung 
250a563ca70SAlex Hornung 	argv[i] = NULL;
251a563ca70SAlex Hornung 
252a563ca70SAlex Hornung 	return argv;
253a563ca70SAlex Hornung }
254a563ca70SAlex Hornung 
255a563ca70SAlex Hornung uint32_t
testcase_get_flags(prop_dictionary_t testcase)256a563ca70SAlex Hornung testcase_get_flags(prop_dictionary_t testcase)
257a563ca70SAlex Hornung {
258a563ca70SAlex Hornung 	uint32_t flags;
259a563ca70SAlex Hornung 	int r;
260a563ca70SAlex Hornung 
261a563ca70SAlex Hornung 	r = prop_dictionary_get_uint32(prop_dictionary_get(testcase, "opts"),
262a563ca70SAlex Hornung 	    "flags", &flags);
263a563ca70SAlex Hornung 	if (r == 0)
264a563ca70SAlex Hornung 		err(1, "prop_dictionary operation failed");
265a563ca70SAlex Hornung 
266a563ca70SAlex Hornung 	return flags;
267a563ca70SAlex Hornung }
268a563ca70SAlex Hornung 
269a563ca70SAlex Hornung int
testcase_get_precmd_type(prop_dictionary_t testcase)270a563ca70SAlex Hornung testcase_get_precmd_type(prop_dictionary_t testcase)
271a563ca70SAlex Hornung {
272a563ca70SAlex Hornung 	uint32_t flags = testcase_get_flags(testcase);
273a563ca70SAlex Hornung 
274a563ca70SAlex Hornung 	return (flags & (TESTCASE_INT_PRE | TESTCASE_CUSTOM_PRE));
275a563ca70SAlex Hornung }
276a563ca70SAlex Hornung 
277a563ca70SAlex Hornung int
testcase_get_rc(prop_dictionary_t testcase)278*039caa27SAntonio Huete Jimenez testcase_get_rc(prop_dictionary_t testcase)
279*039caa27SAntonio Huete Jimenez {
280*039caa27SAntonio Huete Jimenez 	int32_t rc;
281*039caa27SAntonio Huete Jimenez 	int r;
282*039caa27SAntonio Huete Jimenez 
283*039caa27SAntonio Huete Jimenez 	r = prop_dictionary_get_int32(prop_dictionary_get(testcase, "opts"),
284*039caa27SAntonio Huete Jimenez 	    "rc", &rc);
285*039caa27SAntonio Huete Jimenez 	if (r == 0)
286*039caa27SAntonio Huete Jimenez 		err(1, "prop_dictionary operation failed for rc");
287*039caa27SAntonio Huete Jimenez 
288*039caa27SAntonio Huete Jimenez 	return rc;
289*039caa27SAntonio Huete Jimenez }
290*039caa27SAntonio Huete Jimenez 
291*039caa27SAntonio Huete Jimenez int
testcase_get_postcmd_type(prop_dictionary_t testcase)292a563ca70SAlex Hornung testcase_get_postcmd_type(prop_dictionary_t testcase)
293a563ca70SAlex Hornung {
294a563ca70SAlex Hornung 	uint32_t flags = testcase_get_flags(testcase);
295a563ca70SAlex Hornung 
296a563ca70SAlex Hornung 	return (flags & (TESTCASE_INT_POST | TESTCASE_CUSTOM_POST));
297a563ca70SAlex Hornung }
298a563ca70SAlex Hornung 
299a563ca70SAlex Hornung int
testcase_needs_setuid(prop_dictionary_t testcase)300a563ca70SAlex Hornung testcase_needs_setuid(prop_dictionary_t testcase)
301a563ca70SAlex Hornung {
302a563ca70SAlex Hornung 	uint32_t flags = testcase_get_flags(testcase);
303a563ca70SAlex Hornung 
304a563ca70SAlex Hornung 	return (flags & TESTCASE_RUN_AS);
305a563ca70SAlex Hornung }
306a563ca70SAlex Hornung 
307a563ca70SAlex Hornung uid_t
testcase_get_runas_uid(prop_dictionary_t testcase)308a563ca70SAlex Hornung testcase_get_runas_uid(prop_dictionary_t testcase)
309a563ca70SAlex Hornung {
310a563ca70SAlex Hornung 	uint32_t uid = 0;
31117b89cd0SSascha Wildner 	int r;
312a563ca70SAlex Hornung 
313a563ca70SAlex Hornung 	r = prop_dictionary_get_uint32(
314a563ca70SAlex Hornung 	    prop_dictionary_get(testcase, "opts"), "runas_uid", &uid);
31517b89cd0SSascha Wildner 	if (r == 0)
31617b89cd0SSascha Wildner 		err(1, "prop_dictionary operation failed");
317a563ca70SAlex Hornung 
318a563ca70SAlex Hornung 	return (uid_t)uid;
319a563ca70SAlex Hornung }
320a563ca70SAlex Hornung 
321a563ca70SAlex Hornung const char *
testcase_get_custom_precmd(prop_dictionary_t testcase)322a563ca70SAlex Hornung testcase_get_custom_precmd(prop_dictionary_t testcase)
323a563ca70SAlex Hornung {
324a563ca70SAlex Hornung 	const char *str;
325a563ca70SAlex Hornung 	int r;
326a563ca70SAlex Hornung 
327a563ca70SAlex Hornung 	r = prop_dictionary_get_cstring_nocopy(
328a563ca70SAlex Hornung 	    prop_dictionary_get(testcase, "opts"), "pre_cmd", &str);
329a563ca70SAlex Hornung 	if (r == 0)
330a563ca70SAlex Hornung 		err(1, "prop_dictionary operation failed");
331a563ca70SAlex Hornung 
332a563ca70SAlex Hornung 	return str;
333a563ca70SAlex Hornung }
334a563ca70SAlex Hornung 
335a563ca70SAlex Hornung const char *
testcase_get_custom_postcmd(prop_dictionary_t testcase)336a563ca70SAlex Hornung testcase_get_custom_postcmd(prop_dictionary_t testcase)
337a563ca70SAlex Hornung {
338a563ca70SAlex Hornung 	const char *str;
339a563ca70SAlex Hornung 	int r;
340a563ca70SAlex Hornung 
341a563ca70SAlex Hornung 	r = prop_dictionary_get_cstring_nocopy(
342a563ca70SAlex Hornung 	    prop_dictionary_get(testcase, "opts"), "pre_cmd", &str);
343a563ca70SAlex Hornung 	if (r == 0)
344a563ca70SAlex Hornung 		err(1, "prop_dictionary operation failed");
345a563ca70SAlex Hornung 
346a563ca70SAlex Hornung 	return str;
347a563ca70SAlex Hornung }
348a563ca70SAlex Hornung 
3490d575305SAntonio Huete Jimenez static const char *
_testcase_get_interpreter(prop_dictionary_t testcase,bool fatal)3500d575305SAntonio Huete Jimenez _testcase_get_interpreter(prop_dictionary_t testcase, bool fatal)
3510d575305SAntonio Huete Jimenez {
3520d575305SAntonio Huete Jimenez 	const char *str;
3530d575305SAntonio Huete Jimenez 	int r;
3540d575305SAntonio Huete Jimenez 
3550d575305SAntonio Huete Jimenez 	r = prop_dictionary_get_cstring_nocopy(
3560d575305SAntonio Huete Jimenez 	    prop_dictionary_get(testcase, "opts"), "interpreter", &str);
35729e6131eSAntonio Huete Jimenez 	if (r == 0) {
35829e6131eSAntonio Huete Jimenez 		if (fatal)
3590d575305SAntonio Huete Jimenez 			err(1, "prop_dictionary operation failed for interpreter");
3600d575305SAntonio Huete Jimenez 		else
3610d575305SAntonio Huete Jimenez 			return NULL;
36229e6131eSAntonio Huete Jimenez 	}
3630d575305SAntonio Huete Jimenez 
3640d575305SAntonio Huete Jimenez 	return str;
3650d575305SAntonio Huete Jimenez }
3660d575305SAntonio Huete Jimenez 
3670d575305SAntonio Huete Jimenez const char *
testcase_get_interpreter(prop_dictionary_t testcase)3680d575305SAntonio Huete Jimenez testcase_get_interpreter(prop_dictionary_t testcase)
3690d575305SAntonio Huete Jimenez {
3700d575305SAntonio Huete Jimenez 	return _testcase_get_interpreter(testcase, true);
3710d575305SAntonio Huete Jimenez }
3720d575305SAntonio Huete Jimenez 
3730d575305SAntonio Huete Jimenez const char *
testcase_get_interpreter_noexit(prop_dictionary_t testcase)3740d575305SAntonio Huete Jimenez testcase_get_interpreter_noexit(prop_dictionary_t testcase)
3750d575305SAntonio Huete Jimenez {
3760d575305SAntonio Huete Jimenez 	return _testcase_get_interpreter(testcase, false);
3770d575305SAntonio Huete Jimenez }
3780d575305SAntonio Huete Jimenez 
379a563ca70SAlex Hornung const char *
testcase_get_make_cmd(prop_dictionary_t testcase)380a563ca70SAlex Hornung testcase_get_make_cmd(prop_dictionary_t testcase)
381a563ca70SAlex Hornung {
382a563ca70SAlex Hornung 	const char *str;
383a563ca70SAlex Hornung 	int r;
384a563ca70SAlex Hornung 
385a563ca70SAlex Hornung 	r = prop_dictionary_get_cstring_nocopy(
386a563ca70SAlex Hornung 	    prop_dictionary_get(testcase, "opts"), "make_cmd", &str);
387a563ca70SAlex Hornung 	if (r == 0)
388a563ca70SAlex Hornung 		err(1, "prop_dictionary operation failed");
389a563ca70SAlex Hornung 
390a563ca70SAlex Hornung 	return str;
391a563ca70SAlex Hornung }
392a563ca70SAlex Hornung 
393a563ca70SAlex Hornung prop_dictionary_t
testcase_get_result_dict(prop_dictionary_t testcase)394a563ca70SAlex Hornung testcase_get_result_dict(prop_dictionary_t testcase)
395a563ca70SAlex Hornung {
396a563ca70SAlex Hornung 	prop_dictionary_t result_dict;
397a563ca70SAlex Hornung 	int r;
398a563ca70SAlex Hornung 
399a563ca70SAlex Hornung 	result_dict = prop_dictionary_get(testcase, "result");
400a563ca70SAlex Hornung 	if (result_dict == NULL) {
401a563ca70SAlex Hornung 		result_dict = prop_dictionary_create();
402a563ca70SAlex Hornung 		if (result_dict == NULL)
403a563ca70SAlex Hornung 			err(1, "could not allocate new result dict");
404a563ca70SAlex Hornung 
405a563ca70SAlex Hornung 		r = prop_dictionary_set(testcase, "result", result_dict);
406a563ca70SAlex Hornung 		if (r == 0)
407a563ca70SAlex Hornung 			err(1, "prop_dictionary operation failed");
408a563ca70SAlex Hornung 	}
409a563ca70SAlex Hornung 
410a563ca70SAlex Hornung 	return result_dict;
411a563ca70SAlex Hornung }
412a563ca70SAlex Hornung 
413a563ca70SAlex Hornung int
testcase_set_build_buf(prop_dictionary_t testcase,const char * buf)414a563ca70SAlex Hornung testcase_set_build_buf(prop_dictionary_t testcase, const char *buf)
415a563ca70SAlex Hornung {
416a563ca70SAlex Hornung 	prop_dictionary_t dict = testcase_get_result_dict(testcase);
417a563ca70SAlex Hornung 
418a563ca70SAlex Hornung 	return !prop_dictionary_set_cstring(dict, "build_buf", buf);
419a563ca70SAlex Hornung }
420a563ca70SAlex Hornung 
421a563ca70SAlex Hornung int
testcase_set_cleanup_buf(prop_dictionary_t testcase,const char * buf)422a563ca70SAlex Hornung testcase_set_cleanup_buf(prop_dictionary_t testcase, const char *buf)
423a563ca70SAlex Hornung {
424a563ca70SAlex Hornung 	prop_dictionary_t dict = testcase_get_result_dict(testcase);
425a563ca70SAlex Hornung 
426a563ca70SAlex Hornung 	return !prop_dictionary_set_cstring(dict, "cleanup_buf", buf);
427a563ca70SAlex Hornung }
428a563ca70SAlex Hornung 
429a563ca70SAlex Hornung int
testcase_set_sys_buf(prop_dictionary_t testcase,const char * buf)430a563ca70SAlex Hornung testcase_set_sys_buf(prop_dictionary_t testcase, const char *buf)
431a563ca70SAlex Hornung {
432a563ca70SAlex Hornung 	prop_dictionary_t dict = testcase_get_result_dict(testcase);
433a563ca70SAlex Hornung 
434a563ca70SAlex Hornung 	return !prop_dictionary_set_cstring(dict, "sys_buf", buf);
435a563ca70SAlex Hornung }
436a563ca70SAlex Hornung 
437a563ca70SAlex Hornung int
testcase_set_precmd_buf(prop_dictionary_t testcase,const char * buf)438a563ca70SAlex Hornung testcase_set_precmd_buf(prop_dictionary_t testcase, const char *buf)
439a563ca70SAlex Hornung {
440a563ca70SAlex Hornung 	prop_dictionary_t dict = testcase_get_result_dict(testcase);
441a563ca70SAlex Hornung 
442a563ca70SAlex Hornung 	return !prop_dictionary_set_cstring(dict, "precmd_buf", buf);
443a563ca70SAlex Hornung }
444a563ca70SAlex Hornung 
445a563ca70SAlex Hornung int
testcase_set_postcmd_buf(prop_dictionary_t testcase,const char * buf)446a563ca70SAlex Hornung testcase_set_postcmd_buf(prop_dictionary_t testcase, const char *buf)
447a563ca70SAlex Hornung {
448a563ca70SAlex Hornung 	prop_dictionary_t dict = testcase_get_result_dict(testcase);
449a563ca70SAlex Hornung 
450a563ca70SAlex Hornung 	return !prop_dictionary_set_cstring(dict, "postcmd_buf", buf);
451a563ca70SAlex Hornung }
452a563ca70SAlex Hornung 
453a563ca70SAlex Hornung int
testcase_set_stdout_buf(prop_dictionary_t testcase,const char * buf)454a563ca70SAlex Hornung testcase_set_stdout_buf(prop_dictionary_t testcase, const char *buf)
455a563ca70SAlex Hornung {
456a563ca70SAlex Hornung 	prop_dictionary_t dict = testcase_get_result_dict(testcase);
457a563ca70SAlex Hornung 
458a563ca70SAlex Hornung 	return !prop_dictionary_set_cstring(dict, "stdout_buf", buf);
459a563ca70SAlex Hornung }
460a563ca70SAlex Hornung 
461a563ca70SAlex Hornung int
testcase_set_stderr_buf(prop_dictionary_t testcase,const char * buf)462a563ca70SAlex Hornung testcase_set_stderr_buf(prop_dictionary_t testcase, const char *buf)
463a563ca70SAlex Hornung {
464a563ca70SAlex Hornung 	prop_dictionary_t dict = testcase_get_result_dict(testcase);
465a563ca70SAlex Hornung 
466a563ca70SAlex Hornung 	return !prop_dictionary_set_cstring(dict, "stderr_buf", buf);
467a563ca70SAlex Hornung }
468a563ca70SAlex Hornung 
469a563ca70SAlex Hornung int
testcase_set_result(prop_dictionary_t testcase,int result)470a563ca70SAlex Hornung testcase_set_result(prop_dictionary_t testcase, int result)
471a563ca70SAlex Hornung {
472a563ca70SAlex Hornung 	prop_dictionary_t dict = testcase_get_result_dict(testcase);
473a563ca70SAlex Hornung 
474a563ca70SAlex Hornung 	return !prop_dictionary_set_int32(dict, "result", result);
475a563ca70SAlex Hornung }
476a563ca70SAlex Hornung 
477a563ca70SAlex Hornung int
testcase_set_exit_value(prop_dictionary_t testcase,int exitval)478a563ca70SAlex Hornung testcase_set_exit_value(prop_dictionary_t testcase, int exitval)
479a563ca70SAlex Hornung {
480a563ca70SAlex Hornung 	prop_dictionary_t dict = testcase_get_result_dict(testcase);
481a563ca70SAlex Hornung 
482a563ca70SAlex Hornung 	return !prop_dictionary_set_int32(dict, "exit_value", exitval);
483a563ca70SAlex Hornung }
484a563ca70SAlex Hornung 
485a563ca70SAlex Hornung int
testcase_set_signal(prop_dictionary_t testcase,int sig)486a563ca70SAlex Hornung testcase_set_signal(prop_dictionary_t testcase, int sig)
487a563ca70SAlex Hornung {
488a563ca70SAlex Hornung 	prop_dictionary_t dict = testcase_get_result_dict(testcase);
489a563ca70SAlex Hornung 
490a563ca70SAlex Hornung 	return !prop_dictionary_set_int32(dict, "signal", sig);
491a563ca70SAlex Hornung }
492a563ca70SAlex Hornung 
493a563ca70SAlex Hornung const char *
testcase_get_build_buf(prop_dictionary_t testcase)494a563ca70SAlex Hornung testcase_get_build_buf(prop_dictionary_t testcase)
495a563ca70SAlex Hornung {
496a563ca70SAlex Hornung 	const char *str = "";
497a563ca70SAlex Hornung 
498a563ca70SAlex Hornung 	prop_dictionary_t dict = testcase_get_result_dict(testcase);
499a563ca70SAlex Hornung 	prop_dictionary_get_cstring_nocopy(dict, "build_buf", &str);
500a563ca70SAlex Hornung 
501a563ca70SAlex Hornung 	return str;
502a563ca70SAlex Hornung }
503a563ca70SAlex Hornung 
504a563ca70SAlex Hornung const char *
testcase_get_cleanup_buf(prop_dictionary_t testcase)505a563ca70SAlex Hornung testcase_get_cleanup_buf(prop_dictionary_t testcase)
506a563ca70SAlex Hornung {
507a563ca70SAlex Hornung 	const char *str = "";
508a563ca70SAlex Hornung 
509a563ca70SAlex Hornung 	prop_dictionary_t dict = testcase_get_result_dict(testcase);
510a563ca70SAlex Hornung 	prop_dictionary_get_cstring_nocopy(dict, "cleanup_buf", &str);
511a563ca70SAlex Hornung 
512a563ca70SAlex Hornung 	return str;
513a563ca70SAlex Hornung }
514a563ca70SAlex Hornung 
515a563ca70SAlex Hornung const char *
testcase_get_sys_buf(prop_dictionary_t testcase)516a563ca70SAlex Hornung testcase_get_sys_buf(prop_dictionary_t testcase)
517a563ca70SAlex Hornung {
518a563ca70SAlex Hornung 	const char *str = "";
519a563ca70SAlex Hornung 
520a563ca70SAlex Hornung 	prop_dictionary_t dict = testcase_get_result_dict(testcase);
521a563ca70SAlex Hornung 	prop_dictionary_get_cstring_nocopy(dict, "sys_buf", &str);
522a563ca70SAlex Hornung 
523a563ca70SAlex Hornung 	return str;
524a563ca70SAlex Hornung }
525a563ca70SAlex Hornung 
526a563ca70SAlex Hornung const char *
testcase_get_precmd_buf(prop_dictionary_t testcase)527a563ca70SAlex Hornung testcase_get_precmd_buf(prop_dictionary_t testcase)
528a563ca70SAlex Hornung {
529a563ca70SAlex Hornung 	const char *str = "";
530a563ca70SAlex Hornung 
531a563ca70SAlex Hornung 	prop_dictionary_t dict = testcase_get_result_dict(testcase);
532a563ca70SAlex Hornung 	prop_dictionary_get_cstring_nocopy(dict, "precmd_buf", &str);
533a563ca70SAlex Hornung 
534a563ca70SAlex Hornung 	return str;
535a563ca70SAlex Hornung }
536a563ca70SAlex Hornung 
537a563ca70SAlex Hornung const char *
testcase_get_postcmd_buf(prop_dictionary_t testcase)538a563ca70SAlex Hornung testcase_get_postcmd_buf(prop_dictionary_t testcase)
539a563ca70SAlex Hornung {
540a563ca70SAlex Hornung 	const char *str = "";
541a563ca70SAlex Hornung 
542a563ca70SAlex Hornung 	prop_dictionary_t dict = testcase_get_result_dict(testcase);
543a563ca70SAlex Hornung 	prop_dictionary_get_cstring_nocopy(dict, "postcmd_buf", &str);
544a563ca70SAlex Hornung 
545a563ca70SAlex Hornung 	return str;
546a563ca70SAlex Hornung }
547a563ca70SAlex Hornung 
548a563ca70SAlex Hornung const char *
testcase_get_stdout_buf(prop_dictionary_t testcase)549a563ca70SAlex Hornung testcase_get_stdout_buf(prop_dictionary_t testcase)
550a563ca70SAlex Hornung {
551a563ca70SAlex Hornung 	const char *str = "";
552a563ca70SAlex Hornung 
553a563ca70SAlex Hornung 	prop_dictionary_t dict = testcase_get_result_dict(testcase);
554a563ca70SAlex Hornung 	prop_dictionary_get_cstring_nocopy(dict, "stdout_buf", &str);
555a563ca70SAlex Hornung 
556a563ca70SAlex Hornung 	return str;
557a563ca70SAlex Hornung }
558a563ca70SAlex Hornung 
559a563ca70SAlex Hornung const char *
testcase_get_stderr_buf(prop_dictionary_t testcase)560a563ca70SAlex Hornung testcase_get_stderr_buf(prop_dictionary_t testcase)
561a563ca70SAlex Hornung {
562a563ca70SAlex Hornung 	const char *str = "";
563a563ca70SAlex Hornung 
564a563ca70SAlex Hornung 	prop_dictionary_t dict = testcase_get_result_dict(testcase);
565a563ca70SAlex Hornung 	prop_dictionary_get_cstring_nocopy(dict, "stderr_buf", &str);
566a563ca70SAlex Hornung 
567a563ca70SAlex Hornung 	return str;
568a563ca70SAlex Hornung }
569a563ca70SAlex Hornung 
570a563ca70SAlex Hornung int
testcase_get_result(prop_dictionary_t testcase)571a563ca70SAlex Hornung testcase_get_result(prop_dictionary_t testcase)
572a563ca70SAlex Hornung {
573a563ca70SAlex Hornung 	int32_t result = RESULT_NOTRUN;
574a563ca70SAlex Hornung 
575a563ca70SAlex Hornung 	prop_dictionary_t dict = testcase_get_result_dict(testcase);
576a563ca70SAlex Hornung 	prop_dictionary_get_int32(dict, "result", &result);
577a563ca70SAlex Hornung 
578a563ca70SAlex Hornung 	return (int)result;
579a563ca70SAlex Hornung }
580a563ca70SAlex Hornung 
581a563ca70SAlex Hornung const char *
testcase_get_result_desc(prop_dictionary_t testcase)582a563ca70SAlex Hornung testcase_get_result_desc(prop_dictionary_t testcase)
583a563ca70SAlex Hornung {
584a563ca70SAlex Hornung 	int result = testcase_get_result(testcase);
585a563ca70SAlex Hornung 
586a563ca70SAlex Hornung 	switch(result) {
587a563ca70SAlex Hornung 	case RESULT_TIMEOUT:	return "TIMEOUT";
588a563ca70SAlex Hornung 	case RESULT_SIGNALLED:	return "SIGNALLED";
589a563ca70SAlex Hornung 	case RESULT_NOTRUN:	return "NOT RUN";
590a563ca70SAlex Hornung 	case RESULT_FAIL:	return "FAIL";
591a563ca70SAlex Hornung 	case RESULT_PASS:	return "PASS";
592a563ca70SAlex Hornung 	case RESULT_PREFAIL:	return "PREFAIL";
593a563ca70SAlex Hornung 	case RESULT_POSTFAIL:	return "POSTFAIL";
594a563ca70SAlex Hornung 	case RESULT_BUILDFAIL:	return "BUILDFAIL";
595a563ca70SAlex Hornung 	default:		return "UNKNOWN";
596a563ca70SAlex Hornung 	}
597a563ca70SAlex Hornung }
598a563ca70SAlex Hornung 
599a563ca70SAlex Hornung int
testcase_get_exit_value(prop_dictionary_t testcase)600a563ca70SAlex Hornung testcase_get_exit_value(prop_dictionary_t testcase)
601a563ca70SAlex Hornung {
602a563ca70SAlex Hornung 	int32_t exitval;
603a563ca70SAlex Hornung 	int r;
604a563ca70SAlex Hornung 
605a563ca70SAlex Hornung 	prop_dictionary_t dict = testcase_get_result_dict(testcase);
606a563ca70SAlex Hornung 	r = prop_dictionary_get_int32(dict, "exit_value", &exitval);
607a563ca70SAlex Hornung 	if (r == 0)
608a563ca70SAlex Hornung 		err(1, "prop_dictionary operation failed");
609a563ca70SAlex Hornung 
610a563ca70SAlex Hornung 	return (int)exitval;
611a563ca70SAlex Hornung }
612a563ca70SAlex Hornung 
613a563ca70SAlex Hornung int
testcase_get_signal(prop_dictionary_t testcase)614a563ca70SAlex Hornung testcase_get_signal(prop_dictionary_t testcase)
615a563ca70SAlex Hornung {
616a563ca70SAlex Hornung 	int32_t sig;
617a563ca70SAlex Hornung 	int r;
618a563ca70SAlex Hornung 
619a563ca70SAlex Hornung 	prop_dictionary_t dict = testcase_get_result_dict(testcase);
620a563ca70SAlex Hornung 	r = prop_dictionary_get_int32(dict, "signal", &sig);
621a563ca70SAlex Hornung 	if (r == 0)
622a563ca70SAlex Hornung 		err(1, "prop_dictionary operation failed");
623a563ca70SAlex Hornung 
624a563ca70SAlex Hornung 	return (int)sig;
625a563ca70SAlex Hornung }
626a563ca70SAlex Hornung 
627a563ca70SAlex Hornung int
parse_testcase_option(struct testcase_options * opts,char * option)628a563ca70SAlex Hornung parse_testcase_option(struct testcase_options *opts, char *option)
629a563ca70SAlex Hornung {
630a563ca70SAlex Hornung 	struct passwd *pwd;
631a563ca70SAlex Hornung 	char	*parameter, *endptr;
632a563ca70SAlex Hornung 	long	lval;
633a563ca70SAlex Hornung 	int	noparam = 0;
634a563ca70SAlex Hornung 
635a563ca70SAlex Hornung 	parameter = strchr(option, '=');
636a563ca70SAlex Hornung 	noparam = (parameter == NULL);
637a563ca70SAlex Hornung 	if (!noparam)
638a563ca70SAlex Hornung 	{
639a563ca70SAlex Hornung 		*parameter = '\0';
640a563ca70SAlex Hornung 		++parameter;
641a563ca70SAlex Hornung 	}
642a563ca70SAlex Hornung 
643a563ca70SAlex Hornung 	if (strcmp(option, "timeout") == 0) {
644a563ca70SAlex Hornung 		if (noparam)
645a563ca70SAlex Hornung 			syntax_error("The option 'timeout' needs a parameter");
646a563ca70SAlex Hornung 			/* NOTREACHED */
647a563ca70SAlex Hornung 
648a563ca70SAlex Hornung 		lval = strtol(parameter, &endptr, 10);
649a563ca70SAlex Hornung 		if (*endptr != '\0')
650a563ca70SAlex Hornung 			syntax_error("The option 'timeout' expects an integer "
651a563ca70SAlex Hornung 			    "parameter, not '%s'", parameter);
652a563ca70SAlex Hornung 			/* NOTREACHED */
653a563ca70SAlex Hornung 
654a563ca70SAlex Hornung 		opts->timeout_in_secs = (long int)lval;
655*039caa27SAntonio Huete Jimenez 	} else if (strcmp(option, "rc") == 0) {
656*039caa27SAntonio Huete Jimenez 		if (noparam)
657*039caa27SAntonio Huete Jimenez 			syntax_error("The option 'timeout' needs a parameter");
658*039caa27SAntonio Huete Jimenez 		/* NOTREACHED */
659*039caa27SAntonio Huete Jimenez 
660*039caa27SAntonio Huete Jimenez 		lval = strtol(parameter, &endptr, 10);
661*039caa27SAntonio Huete Jimenez 		if (*endptr != '\0')
662*039caa27SAntonio Huete Jimenez 			syntax_error("The option 'timeout' expects an integer "
663*039caa27SAntonio Huete Jimenez 			    "parameter, not '%s'", parameter);
664*039caa27SAntonio Huete Jimenez 			/* NOTREACHED */
665*039caa27SAntonio Huete Jimenez 
666*039caa27SAntonio Huete Jimenez 		opts->rc = (int)lval;
667a563ca70SAlex Hornung 	} else if (strcmp(option, "intpre") == 0) {
668a563ca70SAlex Hornung 		opts->flags |= TESTCASE_INT_PRE;
669a563ca70SAlex Hornung 	} else if (strcmp(option, "intpost") == 0) {
670a563ca70SAlex Hornung 		opts->flags |= TESTCASE_INT_POST;
671a563ca70SAlex Hornung 	} else if (strcmp(option, "pre") == 0) {
672a563ca70SAlex Hornung 		if (noparam)
673a563ca70SAlex Hornung 			syntax_error("The option 'pre' needs a parameter");
674a563ca70SAlex Hornung 			/* NOTREACHED */
675a563ca70SAlex Hornung 
676a563ca70SAlex Hornung 		opts->flags |= TESTCASE_CUSTOM_PRE;
677a563ca70SAlex Hornung 		opts->pre_cmd = strdup(parameter);
678a563ca70SAlex Hornung 	} else if (strcmp(option, "post") == 0) {
679a563ca70SAlex Hornung 		if (noparam)
680a563ca70SAlex Hornung 			syntax_error("The option 'post' needs a parameter");
681a563ca70SAlex Hornung 			/* NOTREACHED */
682a563ca70SAlex Hornung 
683a563ca70SAlex Hornung 		opts->flags |= TESTCASE_CUSTOM_POST;
684a563ca70SAlex Hornung 		opts->post_cmd = strdup(parameter);
685a563ca70SAlex Hornung 	} else if (strcmp(option, "runas") == 0) {
686a563ca70SAlex Hornung 		if (noparam)
687a563ca70SAlex Hornung 			syntax_error("The option 'runas' needs a parameter");
688a563ca70SAlex Hornung 			/* NOTREACHED */
689a563ca70SAlex Hornung 
690a563ca70SAlex Hornung 		if ((pwd = getpwnam(parameter))) {
691a563ca70SAlex Hornung 			opts->runas_uid = pwd->pw_uid;
692a563ca70SAlex Hornung 			opts->flags |= TESTCASE_RUN_AS;
693a563ca70SAlex Hornung 		} else {
694a563ca70SAlex Hornung 			syntax_error("invalid user name for 'runas': %s",
695a563ca70SAlex Hornung 			    parameter);
696a563ca70SAlex Hornung 		}
697a563ca70SAlex Hornung 	} else if (strcmp(option, "nobuild") == 0) {
698a563ca70SAlex Hornung 		opts->flags |= TESTCASE_NOBUILD;
6990d575305SAntonio Huete Jimenez 	} else if (strcmp(option, "interpreter") == 0) {
7000d575305SAntonio Huete Jimenez 		if (noparam)
7010d575305SAntonio Huete Jimenez 			syntax_error("The option 'interpreter' needs a parameter");
7020d575305SAntonio Huete Jimenez 			/* NOTREACHED */
7030d575305SAntonio Huete Jimenez 		opts->interpreter = strdup(parameter);
704a563ca70SAlex Hornung 	} else if (strcmp(option, "make") == 0) {
705a563ca70SAlex Hornung 		if (noparam)
706a563ca70SAlex Hornung 			syntax_error("The option 'make' needs a parameter");
707a563ca70SAlex Hornung 			/* NOTREACHED */
708a563ca70SAlex Hornung 
709a563ca70SAlex Hornung 		opts->make_cmd = strdup(parameter);
710a563ca70SAlex Hornung 	} else if (strcmp(option, "defaults") == 0) {
711a563ca70SAlex Hornung 		/* Valid option, does nothing */
712a563ca70SAlex Hornung 	} else {
713a563ca70SAlex Hornung 		syntax_error("Unknown option: %s", option);
714a563ca70SAlex Hornung 		/* NOTREACHED */
715a563ca70SAlex Hornung 	}
716a563ca70SAlex Hornung 
717a563ca70SAlex Hornung 	return 0;
718a563ca70SAlex Hornung }
719a563ca70SAlex Hornung 
720a563ca70SAlex Hornung void
testcase_entry_parser(void * arg,char ** tokens)721a563ca70SAlex Hornung testcase_entry_parser(void *arg, char **tokens)
722a563ca70SAlex Hornung {
723a563ca70SAlex Hornung 	prop_array_t runlist;
724a563ca70SAlex Hornung 	prop_dictionary_t testcase_dict;
725a563ca70SAlex Hornung 	struct testcase *testcase;
726a563ca70SAlex Hornung 	char *options[256];
727a563ca70SAlex Hornung 	int i, r, nopts;
728a563ca70SAlex Hornung 
729a563ca70SAlex Hornung 	runlist = (prop_array_t)arg;
730a563ca70SAlex Hornung 
731a563ca70SAlex Hornung 	testcase = malloc(sizeof(struct testcase));
732a563ca70SAlex Hornung 	if (testcase == NULL)
733a563ca70SAlex Hornung 		err(1, "could not malloc testcase memory");
734a563ca70SAlex Hornung 
735a563ca70SAlex Hornung 	bzero(testcase, sizeof(struct testcase));
736a563ca70SAlex Hornung 
737a563ca70SAlex Hornung 	entry_check_num_args(tokens, 3);
738a563ca70SAlex Hornung 
739a563ca70SAlex Hornung 	testcase->argv = &tokens[3];
740a563ca70SAlex Hornung 	for (testcase->argc = 0; testcase->argv[testcase->argc] != NULL;
741a563ca70SAlex Hornung 	     testcase->argc++)
742a563ca70SAlex Hornung 		;
743a563ca70SAlex Hornung 
744a563ca70SAlex Hornung 	nopts = parse_options(tokens[2], options);
745a563ca70SAlex Hornung 
746a563ca70SAlex Hornung 	testcase->name = tokens[0];
747a563ca70SAlex Hornung 
748a563ca70SAlex Hornung 	if (strcmp(tokens[1], "userland") == 0) {
749a563ca70SAlex Hornung 		testcase->type = TESTCASE_TYPE_USERLAND;
750a563ca70SAlex Hornung 	} else if (strcmp(tokens[1], "kernel") == 0) {
751a563ca70SAlex Hornung 		testcase->type = TESTCASE_TYPE_KERNEL;
752a563ca70SAlex Hornung 	} else if (strcmp(tokens[1], "buildonly") == 0) {
753a563ca70SAlex Hornung 		testcase->type = TESTCASE_TYPE_BUILDONLY;
754a563ca70SAlex Hornung 	} else {
755a563ca70SAlex Hornung 		syntax_error("Unknown type: %s", tokens[1]);
756a563ca70SAlex Hornung 		/* NOTREACHED */
757a563ca70SAlex Hornung 	}
758a563ca70SAlex Hornung 
759a563ca70SAlex Hornung 	testcase->type_str = tokens[1];
760a563ca70SAlex Hornung 
761a563ca70SAlex Hornung 	config_get_defaults(&testcase->opts);
762a563ca70SAlex Hornung 
763a563ca70SAlex Hornung 	for (i = 0; i < nopts; i++)
764a563ca70SAlex Hornung 		parse_testcase_option(&testcase->opts, options[i]);
765a563ca70SAlex Hornung 
766a563ca70SAlex Hornung 	if ((testcase->type != TESTCASE_TYPE_USERLAND) &&
767a563ca70SAlex Hornung 	    (testcase->opts.flags & (TESTCASE_INT_PRE | TESTCASE_INT_POST)))
768a563ca70SAlex Hornung 		syntax_error("'intpre' and 'intpost' options are only valid "
769a563ca70SAlex Hornung 		    "with testcase type 'userland'");
770a563ca70SAlex Hornung 
771a563ca70SAlex Hornung 	if ((testcase->type == TESTCASE_TYPE_BUILDONLY) &&
772a563ca70SAlex Hornung 	    (testcase->opts.flags & TESTCASE_NOBUILD))
773a563ca70SAlex Hornung 		syntax_error("'nobuild' option is incompatible with type "
774a563ca70SAlex Hornung 		    "'buildonly'");
775a563ca70SAlex Hornung 
776a563ca70SAlex Hornung 	testcase_dict = testcase_from_struct(testcase);
777a563ca70SAlex Hornung 	if (testcase->opts.pre_cmd != NULL)
778a563ca70SAlex Hornung 		free(testcase->opts.pre_cmd);
779a563ca70SAlex Hornung 	if (testcase->opts.post_cmd != NULL)
780a563ca70SAlex Hornung 		free(testcase->opts.post_cmd);
7810d575305SAntonio Huete Jimenez 	if (testcase->opts.interpreter != NULL)
7820d575305SAntonio Huete Jimenez 		free(testcase->opts.interpreter);
783a563ca70SAlex Hornung 	if (testcase->opts.make_cmd != NULL)
784a563ca70SAlex Hornung 		free(testcase->opts.make_cmd);
785a563ca70SAlex Hornung 	free(testcase);
786a563ca70SAlex Hornung 
787a563ca70SAlex Hornung 	r = prop_array_add(runlist, testcase_dict);
788a563ca70SAlex Hornung 	if (r == 0)
789a563ca70SAlex Hornung 		err(1, "prop_array_add failed");
790a563ca70SAlex Hornung }
791