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 r = prop_dictionary_set_int32(testcase_dict, "argc",
73 (int32_t)testcase->argc);
75 err(1, "prop_dictionary operation failed");
77 a = prop_array_create_with_capacity(testcase->argc+1);
79 err(1, "prop_array_create for argv failed");
81 s = strrchr(testcase->name, '/');
82 r = prop_array_set_cstring(a, 0, (s == NULL) ? testcase->name : s+1);
84 err(1, "prop_array_set_cstring operation failed");
86 for (i = 1; i <= testcase->argc; i++) {
87 r = prop_array_set_cstring(a, i, testcase->argv[i-1]);
89 err(1, "prop_array_set_cstring operation failed");
92 r = prop_dictionary_set(testcase_dict, "args", a);
94 err(1, "prop_dictionary_set \"args\" failed");
96 dict = prop_dictionary_create();
98 err(1, "could not create dict");
100 r = prop_dictionary_set_int32(dict, "timeout_in_secs",
101 (int32_t)testcase->opts.timeout_in_secs);
103 err(1, "prop_dictionary operation failed");
105 r = prop_dictionary_set_int32(dict, "rc",
106 (int32_t)testcase->opts.rc);
108 err(1, "prop_dictionary operation failed");
110 r = prop_dictionary_set_uint32(dict, "flags", testcase->opts.flags);
112 err(1, "prop_dictionary operation failed");
114 if (testcase->opts.pre_cmd != NULL) {
115 r = prop_dictionary_set_cstring(dict, "pre_cmd",
116 testcase->opts.pre_cmd);
118 err(1, "prop_dictionary operation failed");
121 if (testcase->opts.post_cmd != NULL) {
122 r = prop_dictionary_set_cstring(dict, "post_cmd",
123 testcase->opts.post_cmd);
125 err(1, "prop_dictionary operation failed");
128 if (testcase->opts.interpreter != NULL) {
129 r = prop_dictionary_set_cstring(dict, "interpreter",
130 testcase->opts.interpreter);
132 err(1, "prop_dictionary operation failed");
135 r = prop_dictionary_set_uint32(dict, "runas_uid",
136 (uint32_t)testcase->opts.runas_uid);
138 err(1, "prop_dictionary operation failed");
140 r = prop_dictionary_set_cstring(dict, "make_cmd",
141 (testcase->opts.make_cmd != NULL) ? testcase->opts.make_cmd : "make");
143 err(1, "prop_dictionary operation failed");
145 r = prop_dictionary_set(testcase_dict, "opts", dict);
147 err(1, "prop_dictionary operation failed");
149 return testcase_dict;
153 testcase_get_timeout(prop_dictionary_t testcase)
155 static struct timeval tv;
159 r = prop_dictionary_get_int32(prop_dictionary_get(testcase, "opts"),
160 "timeout_in_secs", &val);
162 err(1, "prop_dictionary operation failed");
165 tv.tv_sec = (long)val;
171 testcase_get_type(prop_dictionary_t testcase)
176 r = prop_dictionary_get_cstring_nocopy(testcase, "type", &type);
178 err(1, "prop_dictionary operation failed");
180 if (strcmp(type, "userland") == 0)
181 return TESTCASE_TYPE_USERLAND;
182 else if (strcmp(type, "kernel") == 0)
183 return TESTCASE_TYPE_KERNEL;
184 else if (strcmp(type, "buildonly") == 0)
185 return TESTCASE_TYPE_BUILDONLY;
191 testcase_get_type_desc(prop_dictionary_t testcase)
196 r = prop_dictionary_get_cstring_nocopy(testcase, "type", &str);
198 err(1, "prop_dictionary operation failed");
204 testcase_get_name(prop_dictionary_t testcase)
209 r = prop_dictionary_get_cstring_nocopy(testcase, "name", &str);
211 err(1, "prop_dictionary operation failed");
217 testcase_get_argc(prop_dictionary_t testcase)
222 r = prop_dictionary_get_int32(testcase, "argc", &argc);
224 err(1, "prop_dictionary operation failed for argc");
230 testcase_get_args(prop_dictionary_t testcase)
232 /* Sane limit of 63 arguments... who wants more than that? */
233 static const char *argv[64];
234 unsigned int i, count;
238 a = prop_dictionary_get(testcase, "args");
240 err(1, "testcase_get_args NULL array");
242 count = prop_array_count(a);
244 for (i = 0; i < count; i++) {
245 r = prop_array_get_cstring_nocopy(a, i, &argv[i]);
247 err(1, "error building argv");
256 testcase_get_flags(prop_dictionary_t testcase)
261 r = prop_dictionary_get_uint32(prop_dictionary_get(testcase, "opts"),
264 err(1, "prop_dictionary operation failed");
270 testcase_get_precmd_type(prop_dictionary_t testcase)
272 uint32_t flags = testcase_get_flags(testcase);
274 return (flags & (TESTCASE_INT_PRE | TESTCASE_CUSTOM_PRE));
278 testcase_get_rc(prop_dictionary_t testcase)
283 r = prop_dictionary_get_int32(prop_dictionary_get(testcase, "opts"),
286 err(1, "prop_dictionary operation failed for rc");
292 testcase_get_postcmd_type(prop_dictionary_t testcase)
294 uint32_t flags = testcase_get_flags(testcase);
296 return (flags & (TESTCASE_INT_POST | TESTCASE_CUSTOM_POST));
300 testcase_needs_setuid(prop_dictionary_t testcase)
302 uint32_t flags = testcase_get_flags(testcase);
304 return (flags & TESTCASE_RUN_AS);
308 testcase_get_runas_uid(prop_dictionary_t testcase)
313 r = prop_dictionary_get_uint32(
314 prop_dictionary_get(testcase, "opts"), "runas_uid", &uid);
316 err(1, "prop_dictionary operation failed");
322 testcase_get_custom_precmd(prop_dictionary_t testcase)
327 r = prop_dictionary_get_cstring_nocopy(
328 prop_dictionary_get(testcase, "opts"), "pre_cmd", &str);
330 err(1, "prop_dictionary operation failed");
336 testcase_get_custom_postcmd(prop_dictionary_t testcase)
341 r = prop_dictionary_get_cstring_nocopy(
342 prop_dictionary_get(testcase, "opts"), "pre_cmd", &str);
344 err(1, "prop_dictionary operation failed");
350 _testcase_get_interpreter(prop_dictionary_t testcase, bool fatal)
355 r = prop_dictionary_get_cstring_nocopy(
356 prop_dictionary_get(testcase, "opts"), "interpreter", &str);
359 err(1, "prop_dictionary operation failed for interpreter");
368 testcase_get_interpreter(prop_dictionary_t testcase)
370 return _testcase_get_interpreter(testcase, true);
374 testcase_get_interpreter_noexit(prop_dictionary_t testcase)
376 return _testcase_get_interpreter(testcase, false);
380 testcase_get_make_cmd(prop_dictionary_t testcase)
385 r = prop_dictionary_get_cstring_nocopy(
386 prop_dictionary_get(testcase, "opts"), "make_cmd", &str);
388 err(1, "prop_dictionary operation failed");
394 testcase_get_result_dict(prop_dictionary_t testcase)
396 prop_dictionary_t result_dict;
399 result_dict = prop_dictionary_get(testcase, "result");
400 if (result_dict == NULL) {
401 result_dict = prop_dictionary_create();
402 if (result_dict == NULL)
403 err(1, "could not allocate new result dict");
405 r = prop_dictionary_set(testcase, "result", result_dict);
407 err(1, "prop_dictionary operation failed");
414 testcase_set_build_buf(prop_dictionary_t testcase, const char *buf)
416 prop_dictionary_t dict = testcase_get_result_dict(testcase);
418 return !prop_dictionary_set_cstring(dict, "build_buf", buf);
422 testcase_set_cleanup_buf(prop_dictionary_t testcase, const char *buf)
424 prop_dictionary_t dict = testcase_get_result_dict(testcase);
426 return !prop_dictionary_set_cstring(dict, "cleanup_buf", buf);
430 testcase_set_sys_buf(prop_dictionary_t testcase, const char *buf)
432 prop_dictionary_t dict = testcase_get_result_dict(testcase);
434 return !prop_dictionary_set_cstring(dict, "sys_buf", buf);
438 testcase_set_precmd_buf(prop_dictionary_t testcase, const char *buf)
440 prop_dictionary_t dict = testcase_get_result_dict(testcase);
442 return !prop_dictionary_set_cstring(dict, "precmd_buf", buf);
446 testcase_set_postcmd_buf(prop_dictionary_t testcase, const char *buf)
448 prop_dictionary_t dict = testcase_get_result_dict(testcase);
450 return !prop_dictionary_set_cstring(dict, "postcmd_buf", buf);
454 testcase_set_stdout_buf(prop_dictionary_t testcase, const char *buf)
456 prop_dictionary_t dict = testcase_get_result_dict(testcase);
458 return !prop_dictionary_set_cstring(dict, "stdout_buf", buf);
462 testcase_set_stderr_buf(prop_dictionary_t testcase, const char *buf)
464 prop_dictionary_t dict = testcase_get_result_dict(testcase);
466 return !prop_dictionary_set_cstring(dict, "stderr_buf", buf);
470 testcase_set_result(prop_dictionary_t testcase, int result)
472 prop_dictionary_t dict = testcase_get_result_dict(testcase);
474 return !prop_dictionary_set_int32(dict, "result", result);
478 testcase_set_exit_value(prop_dictionary_t testcase, int exitval)
480 prop_dictionary_t dict = testcase_get_result_dict(testcase);
482 return !prop_dictionary_set_int32(dict, "exit_value", exitval);
486 testcase_set_signal(prop_dictionary_t testcase, int sig)
488 prop_dictionary_t dict = testcase_get_result_dict(testcase);
490 return !prop_dictionary_set_int32(dict, "signal", sig);
494 testcase_get_build_buf(prop_dictionary_t testcase)
496 const char *str = "";
498 prop_dictionary_t dict = testcase_get_result_dict(testcase);
499 prop_dictionary_get_cstring_nocopy(dict, "build_buf", &str);
505 testcase_get_cleanup_buf(prop_dictionary_t testcase)
507 const char *str = "";
509 prop_dictionary_t dict = testcase_get_result_dict(testcase);
510 prop_dictionary_get_cstring_nocopy(dict, "cleanup_buf", &str);
516 testcase_get_sys_buf(prop_dictionary_t testcase)
518 const char *str = "";
520 prop_dictionary_t dict = testcase_get_result_dict(testcase);
521 prop_dictionary_get_cstring_nocopy(dict, "sys_buf", &str);
527 testcase_get_precmd_buf(prop_dictionary_t testcase)
529 const char *str = "";
531 prop_dictionary_t dict = testcase_get_result_dict(testcase);
532 prop_dictionary_get_cstring_nocopy(dict, "precmd_buf", &str);
538 testcase_get_postcmd_buf(prop_dictionary_t testcase)
540 const char *str = "";
542 prop_dictionary_t dict = testcase_get_result_dict(testcase);
543 prop_dictionary_get_cstring_nocopy(dict, "postcmd_buf", &str);
549 testcase_get_stdout_buf(prop_dictionary_t testcase)
551 const char *str = "";
553 prop_dictionary_t dict = testcase_get_result_dict(testcase);
554 prop_dictionary_get_cstring_nocopy(dict, "stdout_buf", &str);
560 testcase_get_stderr_buf(prop_dictionary_t testcase)
562 const char *str = "";
564 prop_dictionary_t dict = testcase_get_result_dict(testcase);
565 prop_dictionary_get_cstring_nocopy(dict, "stderr_buf", &str);
571 testcase_get_result(prop_dictionary_t testcase)
573 int32_t result = RESULT_NOTRUN;
575 prop_dictionary_t dict = testcase_get_result_dict(testcase);
576 prop_dictionary_get_int32(dict, "result", &result);
582 testcase_get_result_desc(prop_dictionary_t testcase)
584 int result = testcase_get_result(testcase);
587 case RESULT_TIMEOUT: return "TIMEOUT";
588 case RESULT_SIGNALLED: return "SIGNALLED";
589 case RESULT_NOTRUN: return "NOT RUN";
590 case RESULT_FAIL: return "FAIL";
591 case RESULT_PASS: return "PASS";
592 case RESULT_PREFAIL: return "PREFAIL";
593 case RESULT_POSTFAIL: return "POSTFAIL";
594 case RESULT_BUILDFAIL: return "BUILDFAIL";
595 default: return "UNKNOWN";
600 testcase_get_exit_value(prop_dictionary_t testcase)
605 prop_dictionary_t dict = testcase_get_result_dict(testcase);
606 r = prop_dictionary_get_int32(dict, "exit_value", &exitval);
608 err(1, "prop_dictionary operation failed");
614 testcase_get_signal(prop_dictionary_t testcase)
619 prop_dictionary_t dict = testcase_get_result_dict(testcase);
620 r = prop_dictionary_get_int32(dict, "signal", &sig);
622 err(1, "prop_dictionary operation failed");
628 parse_testcase_option(struct testcase_options *opts, char *option)
631 char *parameter, *endptr;
635 parameter = strchr(option, '=');
636 noparam = (parameter == NULL);
643 if (strcmp(option, "timeout") == 0) {
645 syntax_error("The option 'timeout' needs a parameter");
648 lval = strtol(parameter, &endptr, 10);
650 syntax_error("The option 'timeout' expects an integer "
651 "parameter, not '%s'", parameter);
654 opts->timeout_in_secs = (long int)lval;
655 } else if (strcmp(option, "rc") == 0) {
657 syntax_error("The option 'timeout' needs a parameter");
660 lval = strtol(parameter, &endptr, 10);
662 syntax_error("The option 'timeout' expects an integer "
663 "parameter, not '%s'", parameter);
666 opts->rc = (int)lval;
667 } else if (strcmp(option, "intpre") == 0) {
668 opts->flags |= TESTCASE_INT_PRE;
669 } else if (strcmp(option, "intpost") == 0) {
670 opts->flags |= TESTCASE_INT_POST;
671 } else if (strcmp(option, "pre") == 0) {
673 syntax_error("The option 'pre' needs a parameter");
676 opts->flags |= TESTCASE_CUSTOM_PRE;
677 opts->pre_cmd = strdup(parameter);
678 } else if (strcmp(option, "post") == 0) {
680 syntax_error("The option 'post' needs a parameter");
683 opts->flags |= TESTCASE_CUSTOM_POST;
684 opts->post_cmd = strdup(parameter);
685 } else if (strcmp(option, "runas") == 0) {
687 syntax_error("The option 'runas' needs a parameter");
690 if ((pwd = getpwnam(parameter))) {
691 opts->runas_uid = pwd->pw_uid;
692 opts->flags |= TESTCASE_RUN_AS;
694 syntax_error("invalid user name for 'runas': %s",
697 } else if (strcmp(option, "nobuild") == 0) {
698 opts->flags |= TESTCASE_NOBUILD;
699 } else if (strcmp(option, "interpreter") == 0) {
701 syntax_error("The option 'interpreter' needs a parameter");
703 opts->interpreter = strdup(parameter);
704 } else if (strcmp(option, "make") == 0) {
706 syntax_error("The option 'make' needs a parameter");
709 opts->make_cmd = strdup(parameter);
710 } else if (strcmp(option, "defaults") == 0) {
711 /* Valid option, does nothing */
713 syntax_error("Unknown option: %s", option);
721 testcase_entry_parser(void *arg, char **tokens)
723 prop_array_t runlist;
724 prop_dictionary_t testcase_dict;
725 struct testcase *testcase;
729 runlist = (prop_array_t)arg;
731 testcase = malloc(sizeof(struct testcase));
732 if (testcase == NULL)
733 err(1, "could not malloc testcase memory");
735 bzero(testcase, sizeof(struct testcase));
737 entry_check_num_args(tokens, 3);
739 testcase->argv = &tokens[3];
740 for (testcase->argc = 0; testcase->argv[testcase->argc] != NULL;
744 nopts = parse_options(tokens[2], options);
746 testcase->name = tokens[0];
748 if (strcmp(tokens[1], "userland") == 0) {
749 testcase->type = TESTCASE_TYPE_USERLAND;
750 } else if (strcmp(tokens[1], "kernel") == 0) {
751 testcase->type = TESTCASE_TYPE_KERNEL;
752 } else if (strcmp(tokens[1], "buildonly") == 0) {
753 testcase->type = TESTCASE_TYPE_BUILDONLY;
755 syntax_error("Unknown type: %s", tokens[1]);
759 testcase->type_str = tokens[1];
761 config_get_defaults(&testcase->opts);
763 for (i = 0; i < nopts; i++)
764 parse_testcase_option(&testcase->opts, options[i]);
766 if ((testcase->type != TESTCASE_TYPE_USERLAND) &&
767 (testcase->opts.flags & (TESTCASE_INT_PRE | TESTCASE_INT_POST)))
768 syntax_error("'intpre' and 'intpost' options are only valid "
769 "with testcase type 'userland'");
771 if ((testcase->type == TESTCASE_TYPE_BUILDONLY) &&
772 (testcase->opts.flags & TESTCASE_NOBUILD))
773 syntax_error("'nobuild' option is incompatible with type "
776 testcase_dict = testcase_from_struct(testcase);
777 if (testcase->opts.pre_cmd != NULL)
778 free(testcase->opts.pre_cmd);
779 if (testcase->opts.post_cmd != NULL)
780 free(testcase->opts.post_cmd);
781 if (testcase->opts.interpreter != NULL)
782 free(testcase->opts.interpreter);
783 if (testcase->opts.make_cmd != NULL)
784 free(testcase->opts.make_cmd);
787 r = prop_array_add(runlist, testcase_dict);
789 err(1, "prop_array_add failed");