1 /* 2 * Copyright (c) 2011 Alex Hornung <alex@alexhornung.com>. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 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. 15 * 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. 28 */ 29 30 #include <sys/resource.h> 31 #include <sys/time.h> 32 #include <sys/types.h> 33 #include <sys/wait.h> 34 35 #include <errno.h> 36 #include <signal.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <stdint.h> 40 #include <string.h> 41 #include <unistd.h> 42 #include <pwd.h> 43 44 #include <err.h> 45 46 #include <libprop/proplib.h> 47 48 #include "parser.h" 49 #include "testcase.h" 50 #include "runlist.h" 51 #include "config.h" 52 #include <dfregress.h> 53 54 prop_dictionary_t 55 testcase_from_struct(struct testcase *testcase) 56 { 57 int i, r; 58 prop_dictionary_t dict, testcase_dict; 59 prop_array_t a; 60 char *s; 61 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); 66 if (r == 0) 67 err(1, "prop_dictionary operation failed"); 68 r = prop_dictionary_set_cstring(testcase_dict, "type", testcase->type_str); 69 if (r == 0) 70 err(1, "prop_dictionary operation failed"); 71 72 r = prop_dictionary_set_int32(testcase_dict, "argc", 73 (int32_t)testcase->argc); 74 if (r == 0) 75 err(1, "prop_dictionary operation failed"); 76 77 a = prop_array_create_with_capacity(testcase->argc+1); 78 if (a == NULL) 79 err(1, "prop_array_create for argv failed"); 80 81 s = strrchr(testcase->name, '/'); 82 r = prop_array_set_cstring(a, 0, (s == NULL) ? testcase->name : s+1); 83 if (r == 0) 84 err(1, "prop_array_set_cstring operation failed"); 85 86 for (i = 1; i <= testcase->argc; i++) { 87 r = prop_array_set_cstring(a, i, testcase->argv[i-1]); 88 if (r == 0) 89 err(1, "prop_array_set_cstring operation failed"); 90 } 91 92 r = prop_dictionary_set(testcase_dict, "args", a); 93 if (r == 0) 94 err(1, "prop_dictionary_set \"args\" failed"); 95 96 dict = prop_dictionary_create(); 97 if (dict == NULL) 98 err(1, "could not create dict"); 99 100 r = prop_dictionary_set_int32(dict, "timeout_in_secs", 101 (int32_t)testcase->opts.timeout_in_secs); 102 if (r == 0) 103 err(1, "prop_dictionary operation failed"); 104 105 r = prop_dictionary_set_int32(dict, "rc", 106 (int32_t)testcase->opts.rc); 107 if (r == 0) 108 err(1, "prop_dictionary operation failed"); 109 110 r = prop_dictionary_set_uint32(dict, "flags", testcase->opts.flags); 111 if (r == 0) 112 err(1, "prop_dictionary operation failed"); 113 114 if (testcase->opts.pre_cmd != NULL) { 115 r = prop_dictionary_set_cstring(dict, "pre_cmd", 116 testcase->opts.pre_cmd); 117 if (r == 0) 118 err(1, "prop_dictionary operation failed"); 119 } 120 121 if (testcase->opts.post_cmd != NULL) { 122 r = prop_dictionary_set_cstring(dict, "post_cmd", 123 testcase->opts.post_cmd); 124 if (r == 0) 125 err(1, "prop_dictionary operation failed"); 126 } 127 128 if (testcase->opts.interpreter != NULL) { 129 r = prop_dictionary_set_cstring(dict, "interpreter", 130 testcase->opts.interpreter); 131 if (r == 0) 132 err(1, "prop_dictionary operation failed"); 133 } 134 135 r = prop_dictionary_set_uint32(dict, "runas_uid", 136 (uint32_t)testcase->opts.runas_uid); 137 if (r == 0) 138 err(1, "prop_dictionary operation failed"); 139 140 r = prop_dictionary_set_cstring(dict, "make_cmd", 141 (testcase->opts.make_cmd != NULL) ? testcase->opts.make_cmd : "make"); 142 if (r == 0) 143 err(1, "prop_dictionary operation failed"); 144 145 r = prop_dictionary_set(testcase_dict, "opts", dict); 146 if (r == 0) 147 err(1, "prop_dictionary operation failed"); 148 149 return testcase_dict; 150 } 151 152 struct timeval * 153 testcase_get_timeout(prop_dictionary_t testcase) 154 { 155 static struct timeval tv; 156 int32_t val; 157 int r; 158 159 r = prop_dictionary_get_int32(prop_dictionary_get(testcase, "opts"), 160 "timeout_in_secs", &val); 161 if (r == 0) 162 err(1, "prop_dictionary operation failed"); 163 164 tv.tv_usec = 0; 165 tv.tv_sec = (long)val; 166 167 return &tv; 168 } 169 170 int 171 testcase_get_type(prop_dictionary_t testcase) 172 { 173 const char *type; 174 int r; 175 176 r = prop_dictionary_get_cstring_nocopy(testcase, "type", &type); 177 if (r == 0) 178 err(1, "prop_dictionary operation failed"); 179 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; 186 187 return 0; 188 } 189 190 const char * 191 testcase_get_type_desc(prop_dictionary_t testcase) 192 { 193 const char *str; 194 int r; 195 196 r = prop_dictionary_get_cstring_nocopy(testcase, "type", &str); 197 if (r == 0) 198 err(1, "prop_dictionary operation failed"); 199 200 return str; 201 } 202 203 const char * 204 testcase_get_name(prop_dictionary_t testcase) 205 { 206 const char *str; 207 int r; 208 209 r = prop_dictionary_get_cstring_nocopy(testcase, "name", &str); 210 if (r == 0) 211 err(1, "prop_dictionary operation failed"); 212 213 return str; 214 } 215 216 int 217 testcase_get_argc(prop_dictionary_t testcase) 218 { 219 int32_t argc; 220 int r; 221 222 r = prop_dictionary_get_int32(testcase, "argc", &argc); 223 if (r == 0) 224 err(1, "prop_dictionary operation failed for argc"); 225 226 return argc; 227 } 228 229 const char ** 230 testcase_get_args(prop_dictionary_t testcase) 231 { 232 /* Sane limit of 63 arguments... who wants more than that? */ 233 static const char *argv[64]; 234 unsigned int i, count; 235 prop_array_t a; 236 int r; 237 238 a = prop_dictionary_get(testcase, "args"); 239 if (a == NULL) 240 err(1, "testcase_get_args NULL array"); 241 242 count = prop_array_count(a); 243 244 for (i = 0; i < count; i++) { 245 r = prop_array_get_cstring_nocopy(a, i, &argv[i]); 246 if (r == 0) 247 err(1, "error building argv"); 248 } 249 250 argv[i] = NULL; 251 252 return argv; 253 } 254 255 uint32_t 256 testcase_get_flags(prop_dictionary_t testcase) 257 { 258 uint32_t flags; 259 int r; 260 261 r = prop_dictionary_get_uint32(prop_dictionary_get(testcase, "opts"), 262 "flags", &flags); 263 if (r == 0) 264 err(1, "prop_dictionary operation failed"); 265 266 return flags; 267 } 268 269 int 270 testcase_get_precmd_type(prop_dictionary_t testcase) 271 { 272 uint32_t flags = testcase_get_flags(testcase); 273 274 return (flags & (TESTCASE_INT_PRE | TESTCASE_CUSTOM_PRE)); 275 } 276 277 int 278 testcase_get_rc(prop_dictionary_t testcase) 279 { 280 int32_t rc; 281 int r; 282 283 r = prop_dictionary_get_int32(prop_dictionary_get(testcase, "opts"), 284 "rc", &rc); 285 if (r == 0) 286 err(1, "prop_dictionary operation failed for rc"); 287 288 return rc; 289 } 290 291 int 292 testcase_get_postcmd_type(prop_dictionary_t testcase) 293 { 294 uint32_t flags = testcase_get_flags(testcase); 295 296 return (flags & (TESTCASE_INT_POST | TESTCASE_CUSTOM_POST)); 297 } 298 299 int 300 testcase_needs_setuid(prop_dictionary_t testcase) 301 { 302 uint32_t flags = testcase_get_flags(testcase); 303 304 return (flags & TESTCASE_RUN_AS); 305 } 306 307 uid_t 308 testcase_get_runas_uid(prop_dictionary_t testcase) 309 { 310 uint32_t uid = 0; 311 int r; 312 313 r = prop_dictionary_get_uint32( 314 prop_dictionary_get(testcase, "opts"), "runas_uid", &uid); 315 if (r == 0) 316 err(1, "prop_dictionary operation failed"); 317 318 return (uid_t)uid; 319 } 320 321 const char * 322 testcase_get_custom_precmd(prop_dictionary_t testcase) 323 { 324 const char *str; 325 int r; 326 327 r = prop_dictionary_get_cstring_nocopy( 328 prop_dictionary_get(testcase, "opts"), "pre_cmd", &str); 329 if (r == 0) 330 err(1, "prop_dictionary operation failed"); 331 332 return str; 333 } 334 335 const char * 336 testcase_get_custom_postcmd(prop_dictionary_t testcase) 337 { 338 const char *str; 339 int r; 340 341 r = prop_dictionary_get_cstring_nocopy( 342 prop_dictionary_get(testcase, "opts"), "pre_cmd", &str); 343 if (r == 0) 344 err(1, "prop_dictionary operation failed"); 345 346 return str; 347 } 348 349 static const char * 350 _testcase_get_interpreter(prop_dictionary_t testcase, bool fatal) 351 { 352 const char *str; 353 int r; 354 355 r = prop_dictionary_get_cstring_nocopy( 356 prop_dictionary_get(testcase, "opts"), "interpreter", &str); 357 if (r == 0) { 358 if (fatal) 359 err(1, "prop_dictionary operation failed for interpreter"); 360 else 361 return NULL; 362 } 363 364 return str; 365 } 366 367 const char * 368 testcase_get_interpreter(prop_dictionary_t testcase) 369 { 370 return _testcase_get_interpreter(testcase, true); 371 } 372 373 const char * 374 testcase_get_interpreter_noexit(prop_dictionary_t testcase) 375 { 376 return _testcase_get_interpreter(testcase, false); 377 } 378 379 const char * 380 testcase_get_make_cmd(prop_dictionary_t testcase) 381 { 382 const char *str; 383 int r; 384 385 r = prop_dictionary_get_cstring_nocopy( 386 prop_dictionary_get(testcase, "opts"), "make_cmd", &str); 387 if (r == 0) 388 err(1, "prop_dictionary operation failed"); 389 390 return str; 391 } 392 393 prop_dictionary_t 394 testcase_get_result_dict(prop_dictionary_t testcase) 395 { 396 prop_dictionary_t result_dict; 397 int r; 398 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"); 404 405 r = prop_dictionary_set(testcase, "result", result_dict); 406 if (r == 0) 407 err(1, "prop_dictionary operation failed"); 408 } 409 410 return result_dict; 411 } 412 413 int 414 testcase_set_build_buf(prop_dictionary_t testcase, const char *buf) 415 { 416 prop_dictionary_t dict = testcase_get_result_dict(testcase); 417 418 return !prop_dictionary_set_cstring(dict, "build_buf", buf); 419 } 420 421 int 422 testcase_set_cleanup_buf(prop_dictionary_t testcase, const char *buf) 423 { 424 prop_dictionary_t dict = testcase_get_result_dict(testcase); 425 426 return !prop_dictionary_set_cstring(dict, "cleanup_buf", buf); 427 } 428 429 int 430 testcase_set_sys_buf(prop_dictionary_t testcase, const char *buf) 431 { 432 prop_dictionary_t dict = testcase_get_result_dict(testcase); 433 434 return !prop_dictionary_set_cstring(dict, "sys_buf", buf); 435 } 436 437 int 438 testcase_set_precmd_buf(prop_dictionary_t testcase, const char *buf) 439 { 440 prop_dictionary_t dict = testcase_get_result_dict(testcase); 441 442 return !prop_dictionary_set_cstring(dict, "precmd_buf", buf); 443 } 444 445 int 446 testcase_set_postcmd_buf(prop_dictionary_t testcase, const char *buf) 447 { 448 prop_dictionary_t dict = testcase_get_result_dict(testcase); 449 450 return !prop_dictionary_set_cstring(dict, "postcmd_buf", buf); 451 } 452 453 int 454 testcase_set_stdout_buf(prop_dictionary_t testcase, const char *buf) 455 { 456 prop_dictionary_t dict = testcase_get_result_dict(testcase); 457 458 return !prop_dictionary_set_cstring(dict, "stdout_buf", buf); 459 } 460 461 int 462 testcase_set_stderr_buf(prop_dictionary_t testcase, const char *buf) 463 { 464 prop_dictionary_t dict = testcase_get_result_dict(testcase); 465 466 return !prop_dictionary_set_cstring(dict, "stderr_buf", buf); 467 } 468 469 int 470 testcase_set_result(prop_dictionary_t testcase, int result) 471 { 472 prop_dictionary_t dict = testcase_get_result_dict(testcase); 473 474 return !prop_dictionary_set_int32(dict, "result", result); 475 } 476 477 int 478 testcase_set_exit_value(prop_dictionary_t testcase, int exitval) 479 { 480 prop_dictionary_t dict = testcase_get_result_dict(testcase); 481 482 return !prop_dictionary_set_int32(dict, "exit_value", exitval); 483 } 484 485 int 486 testcase_set_signal(prop_dictionary_t testcase, int sig) 487 { 488 prop_dictionary_t dict = testcase_get_result_dict(testcase); 489 490 return !prop_dictionary_set_int32(dict, "signal", sig); 491 } 492 493 const char * 494 testcase_get_build_buf(prop_dictionary_t testcase) 495 { 496 const char *str = ""; 497 498 prop_dictionary_t dict = testcase_get_result_dict(testcase); 499 prop_dictionary_get_cstring_nocopy(dict, "build_buf", &str); 500 501 return str; 502 } 503 504 const char * 505 testcase_get_cleanup_buf(prop_dictionary_t testcase) 506 { 507 const char *str = ""; 508 509 prop_dictionary_t dict = testcase_get_result_dict(testcase); 510 prop_dictionary_get_cstring_nocopy(dict, "cleanup_buf", &str); 511 512 return str; 513 } 514 515 const char * 516 testcase_get_sys_buf(prop_dictionary_t testcase) 517 { 518 const char *str = ""; 519 520 prop_dictionary_t dict = testcase_get_result_dict(testcase); 521 prop_dictionary_get_cstring_nocopy(dict, "sys_buf", &str); 522 523 return str; 524 } 525 526 const char * 527 testcase_get_precmd_buf(prop_dictionary_t testcase) 528 { 529 const char *str = ""; 530 531 prop_dictionary_t dict = testcase_get_result_dict(testcase); 532 prop_dictionary_get_cstring_nocopy(dict, "precmd_buf", &str); 533 534 return str; 535 } 536 537 const char * 538 testcase_get_postcmd_buf(prop_dictionary_t testcase) 539 { 540 const char *str = ""; 541 542 prop_dictionary_t dict = testcase_get_result_dict(testcase); 543 prop_dictionary_get_cstring_nocopy(dict, "postcmd_buf", &str); 544 545 return str; 546 } 547 548 const char * 549 testcase_get_stdout_buf(prop_dictionary_t testcase) 550 { 551 const char *str = ""; 552 553 prop_dictionary_t dict = testcase_get_result_dict(testcase); 554 prop_dictionary_get_cstring_nocopy(dict, "stdout_buf", &str); 555 556 return str; 557 } 558 559 const char * 560 testcase_get_stderr_buf(prop_dictionary_t testcase) 561 { 562 const char *str = ""; 563 564 prop_dictionary_t dict = testcase_get_result_dict(testcase); 565 prop_dictionary_get_cstring_nocopy(dict, "stderr_buf", &str); 566 567 return str; 568 } 569 570 int 571 testcase_get_result(prop_dictionary_t testcase) 572 { 573 int32_t result = RESULT_NOTRUN; 574 575 prop_dictionary_t dict = testcase_get_result_dict(testcase); 576 prop_dictionary_get_int32(dict, "result", &result); 577 578 return (int)result; 579 } 580 581 const char * 582 testcase_get_result_desc(prop_dictionary_t testcase) 583 { 584 int result = testcase_get_result(testcase); 585 586 switch(result) { 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"; 596 } 597 } 598 599 int 600 testcase_get_exit_value(prop_dictionary_t testcase) 601 { 602 int32_t exitval; 603 int r; 604 605 prop_dictionary_t dict = testcase_get_result_dict(testcase); 606 r = prop_dictionary_get_int32(dict, "exit_value", &exitval); 607 if (r == 0) 608 err(1, "prop_dictionary operation failed"); 609 610 return (int)exitval; 611 } 612 613 int 614 testcase_get_signal(prop_dictionary_t testcase) 615 { 616 int32_t sig; 617 int r; 618 619 prop_dictionary_t dict = testcase_get_result_dict(testcase); 620 r = prop_dictionary_get_int32(dict, "signal", &sig); 621 if (r == 0) 622 err(1, "prop_dictionary operation failed"); 623 624 return (int)sig; 625 } 626 627 int 628 parse_testcase_option(struct testcase_options *opts, char *option) 629 { 630 struct passwd *pwd; 631 char *parameter, *endptr; 632 long lval; 633 int noparam = 0; 634 635 parameter = strchr(option, '='); 636 noparam = (parameter == NULL); 637 if (!noparam) 638 { 639 *parameter = '\0'; 640 ++parameter; 641 } 642 643 if (strcmp(option, "timeout") == 0) { 644 if (noparam) 645 syntax_error("The option 'timeout' needs a parameter"); 646 /* NOTREACHED */ 647 648 lval = strtol(parameter, &endptr, 10); 649 if (*endptr != '\0') 650 syntax_error("The option 'timeout' expects an integer " 651 "parameter, not '%s'", parameter); 652 /* NOTREACHED */ 653 654 opts->timeout_in_secs = (long int)lval; 655 } else if (strcmp(option, "rc") == 0) { 656 if (noparam) 657 syntax_error("The option 'timeout' needs a parameter"); 658 /* NOTREACHED */ 659 660 lval = strtol(parameter, &endptr, 10); 661 if (*endptr != '\0') 662 syntax_error("The option 'timeout' expects an integer " 663 "parameter, not '%s'", parameter); 664 /* NOTREACHED */ 665 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) { 672 if (noparam) 673 syntax_error("The option 'pre' needs a parameter"); 674 /* NOTREACHED */ 675 676 opts->flags |= TESTCASE_CUSTOM_PRE; 677 opts->pre_cmd = strdup(parameter); 678 } else if (strcmp(option, "post") == 0) { 679 if (noparam) 680 syntax_error("The option 'post' needs a parameter"); 681 /* NOTREACHED */ 682 683 opts->flags |= TESTCASE_CUSTOM_POST; 684 opts->post_cmd = strdup(parameter); 685 } else if (strcmp(option, "runas") == 0) { 686 if (noparam) 687 syntax_error("The option 'runas' needs a parameter"); 688 /* NOTREACHED */ 689 690 if ((pwd = getpwnam(parameter))) { 691 opts->runas_uid = pwd->pw_uid; 692 opts->flags |= TESTCASE_RUN_AS; 693 } else { 694 syntax_error("invalid user name for 'runas': %s", 695 parameter); 696 } 697 } else if (strcmp(option, "nobuild") == 0) { 698 opts->flags |= TESTCASE_NOBUILD; 699 } else if (strcmp(option, "interpreter") == 0) { 700 if (noparam) 701 syntax_error("The option 'interpreter' needs a parameter"); 702 /* NOTREACHED */ 703 opts->interpreter = strdup(parameter); 704 } else if (strcmp(option, "make") == 0) { 705 if (noparam) 706 syntax_error("The option 'make' needs a parameter"); 707 /* NOTREACHED */ 708 709 opts->make_cmd = strdup(parameter); 710 } else if (strcmp(option, "defaults") == 0) { 711 /* Valid option, does nothing */ 712 } else { 713 syntax_error("Unknown option: %s", option); 714 /* NOTREACHED */ 715 } 716 717 return 0; 718 } 719 720 void 721 testcase_entry_parser(void *arg, char **tokens) 722 { 723 prop_array_t runlist; 724 prop_dictionary_t testcase_dict; 725 struct testcase *testcase; 726 char *options[256]; 727 int i, r, nopts; 728 729 runlist = (prop_array_t)arg; 730 731 testcase = malloc(sizeof(struct testcase)); 732 if (testcase == NULL) 733 err(1, "could not malloc testcase memory"); 734 735 bzero(testcase, sizeof(struct testcase)); 736 737 entry_check_num_args(tokens, 3); 738 739 testcase->argv = &tokens[3]; 740 for (testcase->argc = 0; testcase->argv[testcase->argc] != NULL; 741 testcase->argc++) 742 ; 743 744 nopts = parse_options(tokens[2], options); 745 746 testcase->name = tokens[0]; 747 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; 754 } else { 755 syntax_error("Unknown type: %s", tokens[1]); 756 /* NOTREACHED */ 757 } 758 759 testcase->type_str = tokens[1]; 760 761 config_get_defaults(&testcase->opts); 762 763 for (i = 0; i < nopts; i++) 764 parse_testcase_option(&testcase->opts, options[i]); 765 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'"); 770 771 if ((testcase->type == TESTCASE_TYPE_BUILDONLY) && 772 (testcase->opts.flags & TESTCASE_NOBUILD)) 773 syntax_error("'nobuild' option is incompatible with type " 774 "'buildonly'"); 775 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); 785 free(testcase); 786 787 r = prop_array_add(runlist, testcase_dict); 788 if (r == 0) 789 err(1, "prop_array_add failed"); 790 } 791