2 * Copyright (c) 2011 Alex Hornung <alex@alexhornung.com>.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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
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
30 #include <sys/resource.h>
32 #include <sys/types.h>
46 #include <libprop/proplib.h>
52 #include <dfregress.h>
55 testcase_from_struct(struct testcase *testcase)
58 prop_dictionary_t dict, testcase_dict;
62 testcase_dict = prop_dictionary_create();
63 if (testcase_dict == NULL)
64 err(1, "could not create testcase dict");
65 r = prop_dictionary_set_cstring(testcase_dict, "name", testcase->name);
67 err(1, "prop_dictionary operation failed");
68 r = prop_dictionary_set_cstring(testcase_dict, "type", testcase->type_str);
70 err(1, "prop_dictionary operation failed");
72 a = prop_array_create_with_capacity(testcase->argc+1);
74 err(1, "prop_array_create for argv failed");
76 s = strrchr(testcase->name, '/');
77 r = prop_array_set_cstring(a, 0, (s == NULL) ? testcase->name : s+1);
79 err(1, "prop_array_set_cstring operation failed");
81 for (i = 1; i <= testcase->argc; i++) {
82 r = prop_array_set_cstring(a, i, testcase->argv[i-1]);
84 err(1, "prop_array_set_cstring operation failed");
87 r = prop_dictionary_set(testcase_dict, "args", a);
89 err(1, "prop_dictionary_set \"args\" failed");
91 dict = prop_dictionary_create();
93 err(1, "could not create dict");
95 r = prop_dictionary_set_int32(dict, "timeout_in_secs",
96 (int32_t)testcase->opts.timeout_in_secs);
98 err(1, "prop_dictionary operation failed");
100 r = prop_dictionary_set_uint32(dict, "flags", testcase->opts.flags);
102 err(1, "prop_dictionary operation failed");
104 if (testcase->opts.pre_cmd != NULL) {
105 r = prop_dictionary_set_cstring(dict, "pre_cmd",
106 testcase->opts.pre_cmd);
108 err(1, "prop_dictionary operation failed");
111 if (testcase->opts.post_cmd != NULL) {
112 r = prop_dictionary_set_cstring(dict, "post_cmd",
113 testcase->opts.post_cmd);
115 err(1, "prop_dictionary operation failed");
118 r = prop_dictionary_set_uint32(dict, "runas_uid",
119 (uint32_t)testcase->opts.runas_uid);
121 err(1, "prop_dictionary operation failed");
123 r = prop_dictionary_set_cstring(dict, "make_cmd",
124 (testcase->opts.make_cmd != NULL) ? testcase->opts.make_cmd : "make");
126 err(1, "prop_dictionary operation failed");
128 r = prop_dictionary_set(testcase_dict, "opts", dict);
130 err(1, "prop_dictionary operation failed");
132 return testcase_dict;
136 testcase_get_timeout(prop_dictionary_t testcase)
138 static struct timeval tv;
142 r = prop_dictionary_get_int32(prop_dictionary_get(testcase, "opts"),
143 "timeout_in_secs", &val);
145 err(1, "prop_dictionary operation failed");
148 tv.tv_sec = (long)val;
154 testcase_get_type(prop_dictionary_t testcase)
159 r = prop_dictionary_get_cstring_nocopy(testcase, "type", &type);
161 err(1, "prop_dictionary operation failed");
163 if (strcmp(type, "userland") == 0)
164 return TESTCASE_TYPE_USERLAND;
165 else if (strcmp(type, "kernel") == 0)
166 return TESTCASE_TYPE_KERNEL;
167 else if (strcmp(type, "buildonly") == 0)
168 return TESTCASE_TYPE_BUILDONLY;
174 testcase_get_type_desc(prop_dictionary_t testcase)
179 r = prop_dictionary_get_cstring_nocopy(testcase, "type", &str);
181 err(1, "prop_dictionary operation failed");
187 testcase_get_name(prop_dictionary_t testcase)
192 r = prop_dictionary_get_cstring_nocopy(testcase, "name", &str);
194 err(1, "prop_dictionary operation failed");
200 testcase_get_args(prop_dictionary_t testcase)
202 /* Sane limit of 63 arguments... who wants more than that? */
203 static const char *argv[64];
204 unsigned int i, count;
208 a = prop_dictionary_get(testcase, "args");
210 err(1, "testcase_get_args NULL array");
212 count = prop_array_count(a);
214 for (i = 0; i < count; i++) {
215 r = prop_array_get_cstring_nocopy(a, i, &argv[i]);
217 err(1, "error building argv");
226 testcase_get_flags(prop_dictionary_t testcase)
231 r = prop_dictionary_get_uint32(prop_dictionary_get(testcase, "opts"),
234 err(1, "prop_dictionary operation failed");
240 testcase_get_precmd_type(prop_dictionary_t testcase)
242 uint32_t flags = testcase_get_flags(testcase);
244 return (flags & (TESTCASE_INT_PRE | TESTCASE_CUSTOM_PRE));
248 testcase_get_postcmd_type(prop_dictionary_t testcase)
250 uint32_t flags = testcase_get_flags(testcase);
252 return (flags & (TESTCASE_INT_POST | TESTCASE_CUSTOM_POST));
256 testcase_needs_setuid(prop_dictionary_t testcase)
258 uint32_t flags = testcase_get_flags(testcase);
260 return (flags & TESTCASE_RUN_AS);
264 testcase_get_runas_uid(prop_dictionary_t testcase)
269 r = prop_dictionary_get_uint32(
270 prop_dictionary_get(testcase, "opts"), "runas_uid", &uid);
276 testcase_get_custom_precmd(prop_dictionary_t testcase)
281 r = prop_dictionary_get_cstring_nocopy(
282 prop_dictionary_get(testcase, "opts"), "pre_cmd", &str);
284 err(1, "prop_dictionary operation failed");
290 testcase_get_custom_postcmd(prop_dictionary_t testcase)
295 r = prop_dictionary_get_cstring_nocopy(
296 prop_dictionary_get(testcase, "opts"), "pre_cmd", &str);
298 err(1, "prop_dictionary operation failed");
304 testcase_get_make_cmd(prop_dictionary_t testcase)
309 r = prop_dictionary_get_cstring_nocopy(
310 prop_dictionary_get(testcase, "opts"), "make_cmd", &str);
312 err(1, "prop_dictionary operation failed");
318 testcase_get_result_dict(prop_dictionary_t testcase)
320 prop_dictionary_t result_dict;
323 result_dict = prop_dictionary_get(testcase, "result");
324 if (result_dict == NULL) {
325 result_dict = prop_dictionary_create();
326 if (result_dict == NULL)
327 err(1, "could not allocate new result dict");
329 r = prop_dictionary_set(testcase, "result", result_dict);
331 err(1, "prop_dictionary operation failed");
338 testcase_set_build_buf(prop_dictionary_t testcase, const char *buf)
340 prop_dictionary_t dict = testcase_get_result_dict(testcase);
342 return !prop_dictionary_set_cstring(dict, "build_buf", buf);
346 testcase_set_cleanup_buf(prop_dictionary_t testcase, const char *buf)
348 prop_dictionary_t dict = testcase_get_result_dict(testcase);
350 return !prop_dictionary_set_cstring(dict, "cleanup_buf", buf);
354 testcase_set_sys_buf(prop_dictionary_t testcase, const char *buf)
356 prop_dictionary_t dict = testcase_get_result_dict(testcase);
358 return !prop_dictionary_set_cstring(dict, "sys_buf", buf);
362 testcase_set_precmd_buf(prop_dictionary_t testcase, const char *buf)
364 prop_dictionary_t dict = testcase_get_result_dict(testcase);
366 return !prop_dictionary_set_cstring(dict, "precmd_buf", buf);
370 testcase_set_postcmd_buf(prop_dictionary_t testcase, const char *buf)
372 prop_dictionary_t dict = testcase_get_result_dict(testcase);
374 return !prop_dictionary_set_cstring(dict, "postcmd_buf", buf);
378 testcase_set_stdout_buf(prop_dictionary_t testcase, const char *buf)
380 prop_dictionary_t dict = testcase_get_result_dict(testcase);
382 return !prop_dictionary_set_cstring(dict, "stdout_buf", buf);
386 testcase_set_stderr_buf(prop_dictionary_t testcase, const char *buf)
388 prop_dictionary_t dict = testcase_get_result_dict(testcase);
390 return !prop_dictionary_set_cstring(dict, "stderr_buf", buf);
394 testcase_set_result(prop_dictionary_t testcase, int result)
396 prop_dictionary_t dict = testcase_get_result_dict(testcase);
398 return !prop_dictionary_set_int32(dict, "result", result);
402 testcase_set_exit_value(prop_dictionary_t testcase, int exitval)
404 prop_dictionary_t dict = testcase_get_result_dict(testcase);
406 return !prop_dictionary_set_int32(dict, "exit_value", exitval);
410 testcase_set_signal(prop_dictionary_t testcase, int sig)
412 prop_dictionary_t dict = testcase_get_result_dict(testcase);
414 return !prop_dictionary_set_int32(dict, "signal", sig);
418 testcase_get_build_buf(prop_dictionary_t testcase)
420 const char *str = "";
422 prop_dictionary_t dict = testcase_get_result_dict(testcase);
423 prop_dictionary_get_cstring_nocopy(dict, "build_buf", &str);
429 testcase_get_cleanup_buf(prop_dictionary_t testcase)
431 const char *str = "";
433 prop_dictionary_t dict = testcase_get_result_dict(testcase);
434 prop_dictionary_get_cstring_nocopy(dict, "cleanup_buf", &str);
440 testcase_get_sys_buf(prop_dictionary_t testcase)
442 const char *str = "";
444 prop_dictionary_t dict = testcase_get_result_dict(testcase);
445 prop_dictionary_get_cstring_nocopy(dict, "sys_buf", &str);
451 testcase_get_precmd_buf(prop_dictionary_t testcase)
453 const char *str = "";
455 prop_dictionary_t dict = testcase_get_result_dict(testcase);
456 prop_dictionary_get_cstring_nocopy(dict, "precmd_buf", &str);
462 testcase_get_postcmd_buf(prop_dictionary_t testcase)
464 const char *str = "";
466 prop_dictionary_t dict = testcase_get_result_dict(testcase);
467 prop_dictionary_get_cstring_nocopy(dict, "postcmd_buf", &str);
473 testcase_get_stdout_buf(prop_dictionary_t testcase)
475 const char *str = "";
477 prop_dictionary_t dict = testcase_get_result_dict(testcase);
478 prop_dictionary_get_cstring_nocopy(dict, "stdout_buf", &str);
484 testcase_get_stderr_buf(prop_dictionary_t testcase)
486 const char *str = "";
488 prop_dictionary_t dict = testcase_get_result_dict(testcase);
489 prop_dictionary_get_cstring_nocopy(dict, "stderr_buf", &str);
495 testcase_get_result(prop_dictionary_t testcase)
497 int32_t result = RESULT_NOTRUN;
499 prop_dictionary_t dict = testcase_get_result_dict(testcase);
500 prop_dictionary_get_int32(dict, "result", &result);
506 testcase_get_result_desc(prop_dictionary_t testcase)
508 int result = testcase_get_result(testcase);
511 case RESULT_TIMEOUT: return "TIMEOUT";
512 case RESULT_SIGNALLED: return "SIGNALLED";
513 case RESULT_NOTRUN: return "NOT RUN";
514 case RESULT_FAIL: return "FAIL";
515 case RESULT_PASS: return "PASS";
516 case RESULT_PREFAIL: return "PREFAIL";
517 case RESULT_POSTFAIL: return "POSTFAIL";
518 case RESULT_BUILDFAIL: return "BUILDFAIL";
519 default: return "UNKNOWN";
524 testcase_get_exit_value(prop_dictionary_t testcase)
529 prop_dictionary_t dict = testcase_get_result_dict(testcase);
530 r = prop_dictionary_get_int32(dict, "exit_value", &exitval);
532 err(1, "prop_dictionary operation failed");
538 testcase_get_signal(prop_dictionary_t testcase)
543 prop_dictionary_t dict = testcase_get_result_dict(testcase);
544 r = prop_dictionary_get_int32(dict, "signal", &sig);
546 err(1, "prop_dictionary operation failed");
552 parse_testcase_option(struct testcase_options *opts, char *option)
555 char *parameter, *endptr;
559 parameter = strchr(option, '=');
560 noparam = (parameter == NULL);
567 if (strcmp(option, "timeout") == 0) {
569 syntax_error("The option 'timeout' needs a parameter");
572 lval = strtol(parameter, &endptr, 10);
574 syntax_error("The option 'timeout' expects an integer "
575 "parameter, not '%s'", parameter);
578 opts->timeout_in_secs = (long int)lval;
579 } else if (strcmp(option, "intpre") == 0) {
580 opts->flags |= TESTCASE_INT_PRE;
581 } else if (strcmp(option, "intpost") == 0) {
582 opts->flags |= TESTCASE_INT_POST;
583 } else if (strcmp(option, "pre") == 0) {
585 syntax_error("The option 'pre' needs a parameter");
588 opts->flags |= TESTCASE_CUSTOM_PRE;
589 opts->pre_cmd = strdup(parameter);
590 } else if (strcmp(option, "post") == 0) {
592 syntax_error("The option 'post' needs a parameter");
595 opts->flags |= TESTCASE_CUSTOM_POST;
596 opts->post_cmd = strdup(parameter);
597 } else if (strcmp(option, "runas") == 0) {
599 syntax_error("The option 'runas' needs a parameter");
602 if ((pwd = getpwnam(parameter))) {
603 opts->runas_uid = pwd->pw_uid;
604 opts->flags |= TESTCASE_RUN_AS;
606 syntax_error("invalid user name for 'runas': %s",
609 } else if (strcmp(option, "nobuild") == 0) {
610 opts->flags |= TESTCASE_NOBUILD;
611 } else if (strcmp(option, "make") == 0) {
613 syntax_error("The option 'make' needs a parameter");
616 opts->make_cmd = strdup(parameter);
617 } else if (strcmp(option, "defaults") == 0) {
618 /* Valid option, does nothing */
620 syntax_error("Unknown option: %s", option);
628 testcase_entry_parser(void *arg, char **tokens)
630 prop_array_t runlist;
631 prop_dictionary_t testcase_dict;
632 struct testcase *testcase;
636 runlist = (prop_array_t)arg;
638 testcase = malloc(sizeof(struct testcase));
639 if (testcase == NULL)
640 err(1, "could not malloc testcase memory");
642 bzero(testcase, sizeof(struct testcase));
644 entry_check_num_args(tokens, 3);
646 testcase->argv = &tokens[3];
647 for (testcase->argc = 0; testcase->argv[testcase->argc] != NULL;
651 nopts = parse_options(tokens[2], options);
653 testcase->name = tokens[0];
655 if (strcmp(tokens[1], "userland") == 0) {
656 testcase->type = TESTCASE_TYPE_USERLAND;
657 } else if (strcmp(tokens[1], "kernel") == 0) {
658 testcase->type = TESTCASE_TYPE_KERNEL;
659 } else if (strcmp(tokens[1], "buildonly") == 0) {
660 testcase->type = TESTCASE_TYPE_BUILDONLY;
662 syntax_error("Unknown type: %s", tokens[1]);
666 testcase->type_str = tokens[1];
668 config_get_defaults(&testcase->opts);
670 for (i = 0; i < nopts; i++)
671 parse_testcase_option(&testcase->opts, options[i]);
673 if ((testcase->type != TESTCASE_TYPE_USERLAND) &&
674 (testcase->opts.flags & (TESTCASE_INT_PRE | TESTCASE_INT_POST)))
675 syntax_error("'intpre' and 'intpost' options are only valid "
676 "with testcase type 'userland'");
678 if ((testcase->type == TESTCASE_TYPE_BUILDONLY) &&
679 (testcase->opts.flags & TESTCASE_NOBUILD))
680 syntax_error("'nobuild' option is incompatible with type "
683 testcase_dict = testcase_from_struct(testcase);
684 if (testcase->opts.pre_cmd != NULL)
685 free(testcase->opts.pre_cmd);
686 if (testcase->opts.post_cmd != NULL)
687 free(testcase->opts.post_cmd);
688 if (testcase->opts.make_cmd != NULL)
689 free(testcase->opts.make_cmd);
692 r = prop_array_add(runlist, testcase_dict);
694 err(1, "prop_array_add failed");