1######################################################################## 2# # 3# This software is part of the ast package # 4# Copyright (c) 1994-2012 AT&T Intellectual Property # 5# and is licensed under the # 6# Eclipse Public License, Version 1.0 # 7# by AT&T Intellectual Property # 8# # 9# A copy of the License is available at # 10# http://www.eclipse.org/org/documents/epl-v10.html # 11# (with md5 checksum b35adb5213ca9657e911e9befb180842) # 12# # 13# Information and Software Systems Research # 14# AT&T Research # 15# Florham Park NJ # 16# # 17# Glenn Fowler <gsf@research.att.com> # 18# # 19######################################################################## 20: regress - run regression tests in command.tst 21 22command=regress 23case $(getopts '[-][123:xyz]' opt --xyz 2>/dev/null; echo 0$opt) in 240123) USAGE=$' 25[-? 26@(#)$Id: regress (AT&T Research) 2012-02-02 $ 27] 28'$USAGE_LICENSE$' 29[+NAME?regress - run regression tests] 30[+DESCRIPTION?\bregress\b runs the tests in \aunit\a, or 31 \aunit\a\b.tst\b if \aunit\a does not exist. If \acommand\a is omitted 32 then it is assumed to be the base name of \aunit\a. All testing is done 33 in the temporary directory \aunit\a\b.tmp\b.] 34[+?Default test output lists the \anumber\a and \adescription\a for 35 each active \bTEST\b group and the \anumber\a:\aline\a for each 36 individual \bEXEC\b test. Each test that fails results in a diagnostic 37 that contains the word \bFAILED\b; no other diagnostics contain this 38 word.] 39[b:ignore-space?Ignore space differences when comparing expected 40 output.] 41[i:pipe-input?Repeat each test with the standard input redirected through a 42 pipe.] 43[k:keep?Enable \bcore\b dumps, exit after the first test that fails, 44 and do not remove the temporary directory \aunit\a\b.tmp\b.] 45[l:local-fs?Force \aunit\a\b.tmp\b to be in a local filesystem.] 46[o:pipe-output?Repeat each test with the standard output redirected through 47 a pipe.] 48[p:pipe-io?Repeat each test with the standard input and standard output 49 redirected through pipes.] 50[q:quiet?Output information on \bFAILED\b tests only.] 51[r!:regular?Run each test with the standard input and standard output 52 redirected through regular files.] 53[t:test?Run only tests matching \apattern\a. Tests are numbered and 54 consist of at least two digits (0 filled if necessary.) Tests matching 55 \b+(0)\b are always run.]:[pattern] 56[x:trace?Enable debug tracing.] 57[v:verbose?List differences between actual (<) and expected (>) output, 58 errors and exit codes. Also disable long output line truncation.] 59 60unit [ command [ arg ... ] ] 61 62[+INPUT FILES?The regression test file \aunit\a\b.tst\b is a \bksh\b(1) 63 script that is executed in an environment with the following functions 64 defined:] 65 { 66 [+BODY \b{ ... }?Defines the test body; used for complex tests.] 67 [+CD \b\adirectory\a?Create and change to working directory for 68 one test.] 69 [+CLEANUP \b\astatus\a?Called at exit time to remove the 70 temporary directory \aunit\a\b.tmp\b, list the tests totals via 71 \bTALLY\b, and exit with status \astatus\a.] 72 [+COMMAND \b\aarg\a ...?Runs the current command under test with 73 \aarg\a ... appended to the default args.] 74 [+CONTINUE?The background job must be running.] 75 [+COPY \b\afrom to\a?Copy file \afrom\a to \ato\a. \afrom\a may 76 be a regular file or \bINPUT\b, \bOUTPUT\b or \bERROR\b. Post 77 test comparisons are still done for \afrom\a.] 78 [+DIAGNOSTICS \b[ \b1\b | \b0\b | \apattern\a ]]?No argument or an 79 argument of \b1\b declares that diagnostics are to expected for 80 the remainder of the current \bTEST\b; \b0\b reverts to the default 81 state that diagnostics are not expected; otherwise the argument 82 is a \bksh\b(1) pattern that must match the non-empty contents 83 of the standard error.] 84 [+DO \b\astatement\a?Defines additional statements to be executed 85 for the current test. \astatement\a may be a { ... } group.] 86 [+EMPTY \bINPUT|OUTPUT|ERROR|SAME?The corresponding file is 87 expected to be empty.] 88 [+ERROR \b[ \b-e\b \afilter\a ]] [ \b-n\b ]] \afile\a | - \adata\a ...?The 89 standard error is expected to match either the contents 90 of \afile\a or the line \adata\a. \bERROR -n\b does not 91 append a newline to \adata\a. \afilter\a is a shell command 92 or pipeline that reads standard input and writes standard 93 output that is applied to ERROR before comparison with the 94 expected contents.] 95 [+EXEC \b[ \aarg\a ... ]]?Runs the command under test with 96 optional arguments. \bINPUT\b, \bOUTPUT\b, \bERROR\b, \bEXIT\b 97 and \bSAME\b calls following this \bEXEC\b up until the next 98 \bEXEC\b or the end of the script provide details for the 99 expected results. If no arguments are specified then the 100 arguments from the previious \bEXEC\b in the current \bTEST\b 101 group are used, or no arguments if this is the first \bEXEC\b 102 in the group.] 103 [+EXIT \b\astatus\a?The command exit status is expected to match 104 the pattern \astatus\a.] 105 [+EXITED?The background job must have exited.] 106 [+EXPORT \b[-]] \aname\a=\avalue\a ...?Export environment 107 variables for one test.] 108 [+FATAL \b\amessage\a ...?\amessage\a is printed on the standard 109 error and \bregress\b exits with status \b1\b.] 110 [+FIFO \bINPUT|OUTPUT|ERROR\b [ \b-n\b ]] \afile\a | - \adata\a ...?The 111 \bIO\B file is a fifo.] 112 [+IF \b\acommand\a [\anote\a]]?If the \bsh\b(1) \acommand\a exits 113 0 then tests until the next \bELIF\b, \bELSE\b or \bFI\b are 114 enabled. Otherwise those tests are skipped. \bIF\b ... \bFI\b 115 may be nested, but must not cross \bTEST\b boundaries. \anote\a 116 is listed on the standard error if the correspoding test block 117 is enabled; \bIF\b, \bELIF\b, \bELSE\b may nave a \anote\a 118 operand.] 119 [+IGNORE \b\afile\a ...?\afile\a is ignored for subsequent result 120 comparisons. \afile\a may be \bOUTPUT\b or \bERROR\b.] 121 [+IGNORESPACE?Ignore space differences when comparing expected 122 output.] 123 [+INCLUDE \b\afile\a ...?One or more \afile\a operands are read 124 via the \bksh\b(1) \b.\b(1) command. \bVIEW\b is used to locate 125 the files.] 126 [+INFO \b\adescription\a?\adescription\a is printed on the 127 standard error.] 128 [+INITIALIZE?Called by \bregress\b to initialize a each 129 \bTEST\b group.] 130 [+INPUT \b[ \b-e\b \afilter\a ]] [ \b-n\b ]] \afile\a | - \adata\a ...?The 131 standard input is set to either the contents of \afile\a 132 or the line \adata\a. \bINPUT -n\b does not append a newline 133 to \adata\a. \afilter\a is a shell command or pipeline that 134 reads standard input and writes standard output that is 135 applied to OUTPUT before comparison with the expected contents.] 136 [+INTRO?Called by \bregress\b to introduce all \bTEST\b 137 groups.] 138 [+IO \b[ \bFIFO\b | \bPIPE\b ]] \bINPUT|OUTPUT|ERROR\b [ \b-e\b \afilter\a ]] [ \b-n\b ]] \afile\a | - \adata\a ...?Internal 139 support for the \bINPUT\b, \bOUTPUT\b and \bERROR\b functions.] 140 [+JOB \b\aop\a [ ... ]]?Like \bEXEC\b except the command is run 141 as a background job for the duration of the group or until it 142 is killed via \bKILL\b.] 143 [+KEEP \b\apattern\a ...?The temporary directory is cleared for 144 each test. Files matching \apattern\a are retained between 145 tests.] 146 [+KILL \b[ \asignal\a ]]?Kill the background job with \asignal\a 147 [ \bSIGKILL\b ]].] 148 [+MOVE \b\afrom to\a?Rename file \afrom\a to \ato\a. \afrom\a may 149 be a regular file or \bINPUT\b, \bOUTPUT\b or \bERROR\b. Post 150 test comparisons are ignored for \afrom\a.] 151 [+NOTE \b\acomment\a?\acomment\a is added to the current test 152 trace output.] 153 [+OUTPUT \b[ \b-e\b \afilter\a ]] [ \b-n\b ]] \afile\a | - \adata\a ...?The 154 standard output is expected to match either the contents 155 of \afile\a or the line \adata\a. \bOUTPUT -n\b does not 156 append a newline to \adata\a. \afilter\a is a shell command 157 or pipeline that reads standard input and writes standard 158 output that is applied to ERROR before comparison with the 159 expected contents.] 160 [+PIPE \bINPUT|OUTPUT|ERROR\b [ \b-n\b ]] \afile\a | - \adata\a ...?The 161 \bIO\B file is a pipe.] 162 [+PROG \b\acommand\a [ \aarg\a ... ]]?\acommand\a is run with 163 optional arguments.] 164 [+REMOVE \b\afile\a ...?\afile\a ... are removed after the 165 current test is done.] 166 [+RUN?Called by \bregress\b to run the current test.] 167 [+SAME \b\anew old\a?\anew\a is expected to be the same as 168 \aold\a after the current test completes.] 169 [+SET \b[\bno\b]]\aname\a[=\avalue\a]]?Set the command line 170 option --\aname\a. The setting is in effect for all tests until 171 the next explicit \bSET\b.] 172 [+TALLY?Called by \bregress\b display the \bTEST\b results.] 173 [+TEST \b\anumber\a [ \adescription\a ... ]]?Define a new test 174 group labelled \anumber\a with optional \adescripion\a.] 175 [+TITLE \b[+]] \atext\a?Set the \bTEST\b output title to 176 \atext\a. If \b+\b is specified then \atext\a is appended to 177 the default title. The default title is the test file base 178 name, and, if different from the test file base name, the test 179 unit base name.] 180 [+TWD \b[ \adir\a ... ]]?Set the temporary test dir to \adir\a. 181 The default is \aunit\a\b.tmp\b, where \aunit\a is the test 182 input file sans directory and suffix. If \adir\a matches \b/*\b 183 then it is the directory name; if \adir\a is non-null then the 184 prefix \b${TMPDIR:-/tmp}\b is added; otherwise if \adir\a is 185 omitted then 186 \b${TMPDIR:-/tmp}/tst-\b\aunit\a-$$-$RANDOM.\b\aunit\a is 187 used.] 188 [+UMASK \b[ \amask\a ]]?Run subsequent tests with \bumask\b(1) 189 \amask\a. If \amask\a is omitted then the original \bumask\b is 190 used.] 191 [+UNIT \b\acommand\a [ \aarg\a ... ]]?Define the command and 192 optional default arguments to be tested. \bUNIT\b explicitly 193 overrides the default command name derived from the test script 194 file name. A \acommand\a operand with optional arguments 195 overrides the \bUNIT\b \acommand\a and arguments, with the 196 exception that if the \bUNIT\b \acommand\a is \b-\b or \b+\b 197 the \bUNIT\b arguments are appended to the operand or default 198 unit command and arguments.] 199 [+VIEW \b\avar\a [ \afile\a ]]?\avar\a is set to the full 200 pathname of \avar\a [ \afile\a ]] in the current \b$VPATH\b 201 view if defined.] 202 } 203[+SEE ALSO?\bnmake\b(1), \bksh\b(1)] 204' 205 ;; 206*) USAGE='ko:[[no]name[=value]]t:[test]v unit [path [arg ...]]' 207 ;; 208esac 209 210function FATAL # message 211{ 212 print -r -u2 "$command: $*" 213 GROUP=FINI 214 exit 1 215} 216 217function EMPTY 218{ 219 typeset i 220 typeset -n ARRAY=$1 221 for i in ${!ARRAY[@]} 222 do unset ARRAY[$i] 223 done 224} 225 226function INITIALIZE # void 227{ 228 typeset i j 229 cd "$TWD" 230 case $KEEP in 231 "") RM * 232 ;; 233 *) for i in * 234 do case $i in 235 !($KEEP)) j="$j $i" ;; 236 esac 237 done 238 case $j in 239 ?*) RM $j ;; 240 esac 241 ;; 242 esac 243 : >INPUT >OUTPUT.ex >ERROR.ex 244 BODY="" 245 COPY="" 246 DIAGNOSTICS="" 247 DONE="" 248 ERROR="" 249 EXIT=0 250 IGNORE="" 251 INIT="" 252 INPUT="" 253 MOVE="" 254 OUTPUT="" 255 EMPTY FILE 256 EMPTY FILTER 257 EMPTY SAME 258 EMPTY TYPE 259} 260 261function INTRO 262{ 263 typeset base command 264 265 if [[ ! $TEST_quiet ]] 266 then base=${REGRESS##*/} 267 base=${base%.tst} 268 command=${COMMAND##*/} 269 command=${command%' '*} 270 set -- $TITLE 271 TITLE= 272 case $1 in 273 ''|+) if [[ $command == $base ]] 274 then TITLE=$COMMAND 275 else TITLE="$COMMAND, $base" 276 fi 277 if (( $# )) 278 then shift 279 fi 280 ;; 281 esac 282 while (( $# )) 283 do if [[ $TITLE ]] 284 then TITLE="$TITLE, $1" 285 else TITLE="$1" 286 fi 287 shift 288 done 289 print -u2 "TEST $TITLE" 290 fi 291} 292 293function TALLY # extra message text 294{ 295 typeset msg 296 case $GROUP in 297 INIT) ;; 298 *) msg="TEST $TITLE, $TESTS test" 299 case $TESTS in 300 1) ;; 301 *) msg=${msg}s ;; 302 esac 303 msg="$msg, $ERRORS error" 304 case $ERRORS in 305 1) ;; 306 *) msg=${msg}s ;; 307 esac 308 if (( $# )) 309 then msg="$msg, $*" 310 fi 311 print -u2 "$msg" 312 GROUP=INIT 313 TESTS=0 314 ERRORS=0 315 ;; 316 esac 317} 318 319function TITLE # text 320{ 321 TITLE=$@ 322} 323 324function UNWIND 325{ 326 while (( COND > 1 )) 327 do print -r -u2 "$command: line $LINE: no matching FI for IF on line ${COND_LINE[COND]}" 328 (( COND-- )) 329 done 330 if (( COND > 0 )) 331 then (( COND = 0 )) 332 FATAL "line $LINE: no matching FI for IF on line ${COND_LINE[COND+1]}" 333 fi 334 if [[ $JOBPID ]] 335 then if [[ $JOBPID != 0 ]] 336 then kill -KILL $JOBPID 2>/dev/null 337 wait 338 fi 339 JOBPID= 340 fi 341 JOBSTATUS= 342 JOBOP= 343 wait 344} 345 346function CLEANUP # status 347{ 348 typeset note 349 350 if [[ $GROUP != INIT ]] 351 then if [[ ! $TEST_keep ]] 352 then cd $SOURCE 353 if [[ $TEST_local ]] 354 then RM ${TEST_local} 355 fi 356 RM "$TWD" 357 fi 358 if (( $1 )) && [[ $GROUP != FINI ]] 359 then note=terminated 360 fi 361 fi 362 TALLY $note 363 [[ $TEST_keep ]] || UNWIND 364 exit $1 365} 366 367function RUN # [ op ] 368{ 369 typeset i r=1 370 [[ $UMASK != $UMASK_ORIG ]] && umask $UMASK_ORIG 371#print -u2 AHA#$LINENO $0 GROUP=$GROUP ITEM=$ITEM FLUSHED=$FLUSHED JOBOP=$JOBOP 372 case $GROUP in 373 INIT) RM "$TWD" 374 if [[ $TEST_local ]] 375 then TEST_local=${TMPDIR:-/tmp}/rt-$$/${TWD##*/} 376 mkdir -p "$TEST_local" && ln -s "$TEST_local" "$TWD" || FATAL "$TWD": cannot create directory 377 TEST_local=${TEST_local%/*} 378 else mkdir "$TWD" || FATAL "$TWD": cannot create directory 379 fi 380 cd "$TWD" 381 TWD=$PWD 382 : > rmu 383 if rm -u rmu >/dev/null 2>&1 384 then TEST_rmu=-u 385 else rm rmu 386 fi 387 if [[ $UNIT ]] 388 then set -- "${ARGV[@]}" 389 case $1 in 390 ""|[-+]*) 391 UNIT $UNIT "${ARGV[@]}" 392 ;; 393 *) UNIT "${ARGV[@]}" 394 ;; 395 esac 396 fi 397 INTRO 398 ;; 399 FINI) ;; 400 $TEST_select) 401 if [[ $ITEM == $FLUSHED ]] 402 then return 0 403 fi 404 FLUSHED=$ITEM 405 if (( COND_SKIP[COND] )) 406 then return 1 407 fi 408 ((COUNT++)) 409 if (( $ITEM <= $LASTITEM )) 410 then LABEL=$TEST#$COUNT 411 else LASTITEM=$ITEM 412 LABEL=$TEST:$ITEM 413 fi 414 TEST_file="" 415 exec >/dev/null 416 for i in $INPUT 417 do case " $OUTPUT " in 418 *" $i "*) 419 if [[ -f $i.sav ]] 420 then cp $i.sav $i 421 COMPARE="$COMPARE $i" 422 elif [[ -f $i ]] 423 then cp $i $i.sav 424 COMPARE="$COMPARE $i" 425 fi 426 ;; 427 esac 428 done 429 for i in $OUTPUT 430 do case " $COMPARE " in 431 *" $i "*) 432 ;; 433 *) COMPARE="$COMPARE $i" 434 ;; 435 esac 436 done 437 for i in $INIT 438 do $i $TEST INIT 439 done 440#print -u2 AHA#$LINENO $0 GROUP=$GROUP ITEM=$ITEM JOBOP=$JOBOP JOBPID=$JOBPID JOBSTATUS=$JOBSTATUS 441 if [[ $JOBPID != 0 && ( $JOBPID || $JOBSTATUS ) ]] 442 then if [[ ! $TEST_quiet ]] 443 then print -nu2 "$LABEL" 444 fi 445 RESULTS 446 elif [[ $BODY ]] 447 then SHOW=$NOTE 448 if [[ ! $TEST_quiet ]] 449 then print -r -u2 " $SHOW" 450 fi 451 for i in $BODY 452 do $i $TEST BODY 453 done 454 else SHOW= 455 if [[ ${TYPE[INPUT]} == PIPE ]] 456 then if [[ ${TYPE[OUTPUT]} == PIPE ]] 457 then if [[ ! $TEST_quiet ]] 458 then print -nu2 "$LABEL" 459 fi 460 cat <$TWD/INPUT | COMMAND "${ARGS[@]}" | cat >$TWD/OUTPUT 461 RESULTS 'pipe input' 462 else if [[ ! $TEST_quiet ]] 463 then print -nu2 "$LABEL" 464 fi 465 cat <$TWD/INPUT | COMMAND "${ARGS[@]}" >$TWD/OUTPUT 466 RESULTS 'pipe io' 467 fi 468 elif [[ ${TYPE[OUTPUT]} == PIPE ]] 469 then if [[ ! $TEST_quiet ]] 470 then print -nu2 "$LABEL" 471 fi 472 COMMAND "${ARGS[@]}" <$TWD/INPUT | cat >$TWD/OUTPUT 473 RESULTS 'pipe output' 474 else if [[ $TEST_regular ]] 475 then if [[ ! $TEST_quiet ]] 476 then print -nu2 "$LABEL" 477 fi 478 if [[ ${TYPE[INPUT]} == FIFO ]] 479 then COMMAND "${ARGS[@]}" >$TWD/OUTPUT 480 else COMMAND "${ARGS[@]}" <$TWD/INPUT >$TWD/OUTPUT 481 fi 482 RESULTS 483 fi 484 if [[ $TEST_pipe_input ]] 485 then if [[ ! $TEST_quiet ]] 486 then print -nu2 "$LABEL" 487 fi 488 (trap '' PIPE; cat <$TWD/INPUT 2>/dev/null; exit 0) | COMMAND "${ARGS[@]}" >$TWD/OUTPUT 489 STATUS=$? 490 RESULTS 'pipe input' 491 fi 492 if [[ $TEST_pipe_output ]] 493 then if [[ ! $TEST_quiet ]] 494 then print -nu2 "$LABEL" 495 fi 496 COMMAND "${ARGS[@]}" <$TWD/INPUT | cat >$TWD/OUTPUT 497 STATUS=$? 498 RESULTS 'pipe output' 499 fi 500 if [[ $TEST_pipe_io ]] 501 then if [[ ! $TEST_quiet ]] 502 then print -nu2 "$LABEL" 503 fi 504 (trap '' PIPE; cat <$TWD/INPUT 2>/dev/null; exit 0) | COMMAND "${ARGS[@]}" | cat >$TWD/OUTPUT 505 STATUS=$? 506 RESULTS 'pipe io' 507 fi 508 fi 509 set -- $COPY 510 COPY="" 511 while : 512 do case $# in 513 0|1) break ;; 514 *) cp $1 $2 ;; 515 esac 516 shift 2 517 done 518 set -- $MOVE 519 MOVE="" 520 while (( $# > 1 )) 521 do mv $1 $2 522 shift 2 523 done 524 fi 525 for i in $DONE 526 do $i $TEST DONE $STATUS 527 done 528 COMPARE="" 529 r=0 530 ;; 531 esac 532 if [[ $COMMAND_ORIG ]] 533 then COMMAND=$COMMAND_ORIG 534 COMMAND_ORIG= 535 ARGS=(${ARGS_ORIG[@]}) 536 fi 537 return $r 538} 539 540function DO # cmd ... 541{ 542 [[ $GROUP == $TEST_select ]] || return 1 543 (( COND_SKIP[COND] )) && return 1 544 [[ $UMASK != $UMASK_ORIG ]] && umask $UMASK 545 return 0 546} 547 548function UNIT # cmd arg ... 549{ 550 typeset cmd=$1 551 case $cmd in 552 [-+]) shift 553 if (( UNIT_READONLY )) 554 then COMMAND="$COMMAND $*" 555 else #BUG# ARGV=("${ARGV[@]}" "$@") 556 set -- "${ARGV[@]}" "$@" 557 ARGV=("$@") 558 fi 559 return 560 ;; 561 esac 562 (( UNIT_READONLY )) && return 563 if [[ $UNIT ]] && (( $# <= 1 )) 564 then set -- "${ARGV[@]}" 565 case $1 in 566 "") set -- "$cmd" ;; 567 [-+]*) set -- "$cmd" "${ARGV[@]}" ;; 568 *) cmd=$1 ;; 569 esac 570 fi 571 UNIT= 572 COMMAND=$cmd 573 shift 574 typeset cmd=$(whence $COMMAND) 575 if [[ ! $cmd ]] 576 then FATAL $COMMAND: not found 577 elif [[ ! $cmd ]] 578 then FATAL $cmd: not found 579 fi 580 case $# in 581 0) ;; 582 *) COMMAND="$COMMAND $*" ;; 583 esac 584} 585 586function TWD # [ dir ] 587{ 588 case $1 in 589 '') TWD=${TWD##*/}; TWD=${TMPDIR:-/tmp}/tst-${TWD%.*}-$$-$RANDOM ;; 590 /*) TWD=$1 ;; 591 *) TWD=${TMPDIR:-/tmp}/$1 ;; 592 esac 593} 594 595function TEST # number description arg ... 596{ 597 RUN 598 LINE=$TESTLINE 599 UNWIND 600 COUNT=0 601 LASTITEM=0 602 case $1 in 603 -) ((LAST++)); TEST=$LAST ;; 604 +([0123456789])) LAST=$1 TEST=$1 ;; 605 *) LAST=0${1/[!0123456789]/} TEST=$1 ;; 606 esac 607 NOTE= 608 if [[ ! $TEST_quiet && $TEST == $TEST_select ]] && (( ! COND_SKIP[COND] )) 609 then print -r -u2 "$TEST $2" 610 fi 611 unset ARGS 612 unset EXPORT 613 EXPORTS=0 614 TEST_file="" 615 if [[ $TEST != ${GROUP}* ]] 616 then GROUP=${TEST%%+([abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ])} 617 if [[ $GROUP == $TEST_select ]] && (( ! COND_SKIP[COND] )) 618 then INITIALIZE 619 fi 620 fi 621 ((SUBTESTS=0)) 622 [[ $TEST == $TEST_select ]] && (( ! COND_SKIP[COND] )) 623} 624 625function EXEC # arg ... 626{ 627 if [[ $GROUP != $TEST_select ]] || (( COND_SKIP[COND] )) 628 then return 629 fi 630 if ((SUBTESTS++)) 631 then RUN 632 fi 633 case $# in 634 0) set -- "${ARGS[@]}" ;; 635 esac 636 ITEM=$LINE 637 NOTE="$(print -r -f '%q ' -- $COMMAND_ORIG "$@")${JOBPID:+&}" 638 ARGS=("$@") 639} 640 641function JOB # arg ... 642{ 643 JOBPID=0 644 EXEC "$@" 645} 646 647function CONTINUE 648{ 649 RUN || return 650 JOBOP=CONTINUE 651 ITEM=$LINE 652 NOTE="$(print -r -f '%q ' -- $JOBOP)" 653#print -u2 AHA#$LINENO JOBOP=$JOBOP ITEM=$ITEM NOTE=$NOTE 654} 655 656function EXITED 657{ 658 RUN || return 659 JOBOP=EXITED 660 ITEM=$LINE 661 NOTE="$(print -r -f '%q ' -- $JOBOP)" 662#print -u2 AHA#$LINENO JOBOP=$JOBOP ITEM=$ITEM NOTE=$NOTE 663} 664 665function KILL # [ signal ] 666{ 667 RUN || return 668 JOBOP=$2 669 [[ $JOBOP ]] || JOBOP=KILL 670 ITEM=$LINE 671 NOTE="$(print -r -f '%q ' -- $JOBOP)" 672} 673 674function CD 675{ 676 RUN 677 if [[ $GROUP == $TEST_select ]] && (( ! COND_SKIP[COND] )) 678 then mkdir -p "$@" && cd "$@" || FATAL cannot initialize working directory "$@" 679 fi 680} 681 682function EXPORT 683{ 684 typeset x n v 685 if [[ $GROUP == INIT ]] 686 then for x 687 do n=${x%%=*} 688 v=${x#*=} 689 ENVIRON[ENVIRONS++]=$n="'$v'" 690 done 691 else RUN 692 if [[ $GROUP != $TEST_select ]] || (( COND_SKIP[COND] )) 693 then return 694 fi 695 for x 696 do n=${x%%=*} 697 v=${x#*=} 698 EXPORT[EXPORTS++]=$n="'$v'" 699 done 700 fi 701} 702 703function FLUSH 704{ 705 if [[ $GROUP != $TEST_select ]] || (( COND_SKIP[COND] )) 706 then return 707 fi 708 if ((SUBTESTS++)) 709 then RUN 710 fi 711} 712 713function PROG # cmd arg ... 714{ 715 typeset command args 716 if [[ $GROUP != $TEST_select ]] || (( COND_SKIP[COND] )) 717 then return 718 fi 719 ITEM=$LINE 720 NOTE="$(print -r -f '%q ' -- "$@")" 721 COMMAND_ORIG=$COMMAND 722 COMMAND=$1 723 shift 724 ARGS_ORIG=(${ARGS[@]}) 725 ARGS=("$@") 726} 727 728function NOTE # description 729{ 730 NOTE=$* 731} 732 733function IO # [ PIPE ] INPUT|OUTPUT|ERROR [-f*|-n] file|- data ... 734{ 735 typeset op i v f file type x 736 if [[ $GROUP != $TEST_select ]] || (( COND_SKIP[COND] )) 737 then return 738 fi 739 [[ $UMASK != $UMASK_ORIG ]] && umask $UMASK_ORIG 740 while : 741 do case $1 in 742 FIFO|PIPE) type=$1; shift ;; 743 *) break ;; 744 esac 745 done 746 op=$1 747 shift 748 [[ $type ]] && TYPE[$op]=$type 749 FILTER[$op]= 750 file=$TWD/$op 751 while : 752 do case $1 in 753 -x) x=1 754 shift 755 ;; 756 -e) (( $# > 1 )) && shift 757 FILTER[$op]=$1 758 shift 759 ;; 760 -e*) FILTER[$op]=${1#-e} 761 shift 762 ;; 763 -f*|-n) f=$1 764 shift 765 ;; 766 *) break 767 ;; 768 esac 769 done 770 case $# in 771 0) ;; 772 *) case $1 in 773 -) ;; 774 *) file=$1 775 eval i='$'$op 776 case " $i " in 777 *" $file "*) 778 ;; 779 *) eval $op='"$'$op' $file"' 780 ;; 781 esac 782 ;; 783 esac 784 shift 785 ;; 786 esac 787 case " $IGNORE " in 788 *" $file "*) 789 for i in $IGNORE 790 do case $i in 791 $file) ;; 792 *) v="$v $i" ;; 793 esac 794 done 795 IGNORE=$v 796 ;; 797 esac 798 FILE[$op]=$file 799 case $op in 800 OUTPUT|ERROR) 801 file=$file.ex 802 if [[ $file != /* ]] 803 then file=$TWD/$file 804 fi 805 ;; 806 esac 807 #unset SAME[$op] 808 SAME[$op]= 809 if [[ $file == /* ]] 810 then RM $file.sav 811 else RM $TWD/$file.sav 812 fi 813 if [[ $file == */* ]] 814 then mkdir -p ${file%/*} 815 fi 816 if [[ $file != */ ]] 817 then if [[ $type == FIFO ]] 818 then rm -f $file 819 mkfifo $file 820 fi 821 if [[ ${TYPE[$op]} != FIFO ]] 822 then if [[ $JOBOP ]] 823 then case $#:$f in 824 0:) ;; 825 *:-f) printf -- "$@" ;; 826 *:-f*) printf -- "${f#-f}""$@" ;; 827 *) print $f -r -- "$@" ;; 828 esac >> $file 829 else case $#:$f in 830 0:) ;; 831 *:-f) printf -- "$@" ;; 832 *:-f*) printf -- "${f#-f}""$@" ;; 833 *) print $f -r -- "$@" ;; 834 esac > $file 835 fi 836 elif [[ $#:$f != 0: ]] 837 then case $#:$f in 838 *:-f) printf -- "$@" ;; 839 *:-f*) printf -- "${f#-f}""$@" ;; 840 *) print $f -r -- "$@" ;; 841 esac >> $file & 842 fi 843 if [[ $x ]] 844 then chmod +x $file 845 fi 846 fi 847} 848 849function INPUT # file|- data ... 850{ 851 IO $0 "$@" 852} 853 854function COPY # from to 855{ 856 if [[ $GROUP != $TEST_select ]] || (( COND_SKIP[COND] )) 857 then return 858 fi 859 COPY="$COPY $@" 860} 861 862function MOVE # from to 863{ 864 typeset f 865 if [[ $GROUP != $TEST_select ]] || (( COND_SKIP[COND] )) 866 then return 867 fi 868 for f 869 do case $f in 870 INPUT|OUTPUT|ERROR) 871 f=$TWD/$f 872 ;; 873 /*) ;; 874 *) f=$PWD/$f 875 ;; 876 esac 877 MOVE="$MOVE $f" 878 done 879} 880 881function SAME # new old 882{ 883 typeset i file v 884 if [[ $GROUP != $TEST_select ]] || (( COND_SKIP[COND] )) 885 then return 886 fi 887 case $# in 888 2) case $1 in 889 INPUT) cat $2 > $1; return ;; 890 esac 891 SAME[$1]=$2 892 file=$1 893 COMPARE="$COMPARE $1" 894 ;; 895 3) SAME[$2]=$3 896 file=$2 897 eval i='$'$1 898 case " $i " in 899 *" $2 "*) 900 ;; 901 *) eval $1='"$'$1' $2"' 902 ;; 903 esac 904 COMPARE="$COMPARE $2" 905 ;; 906 esac 907 case " $IGNORE " in 908 *" $file "*) 909 for i in $IGNORE 910 do case $i in 911 $file) ;; 912 *) v="$v $i" ;; 913 esac 914 done 915 IGNORE=$v 916 ;; 917 esac 918} 919 920function OUTPUT # file|- data ... 921{ 922 IO $0 "$@" 923} 924 925function ERROR # file|- data ... 926{ 927 IO $0 "$@" 928} 929 930function RM # rm(1) args 931{ 932 if [[ ! $TEST_rmu ]] 933 then chmod -R u+rwx "$@" >/dev/null 2>&1 934 fi 935 rm $TEST_rmu $TEST_rmflags "$@" 936} 937 938function REMOVE # file ... 939{ 940 typeset i 941 for i 942 do RM $i $i.sav 943 done 944} 945 946function IGNORE # file ... 947{ 948 typeset i 949 for i 950 do case $i in 951 INPUT|OUTPUT|ERROR) 952 i=$TWD/$i 953 ;; 954 esac 955 case " $IGNORE " in 956 *" $i "*) 957 ;; 958 *) IGNORE="$IGNORE $i" 959 ;; 960 esac 961 done 962} 963 964function KEEP # pattern ... 965{ 966 typeset i 967 for i 968 do case $KEEP in 969 "") KEEP="$i" ;; 970 *) KEEP="$KEEP|$i" ;; 971 esac 972 done 973} 974 975function DIAGNOSTICS # [ 1 | 0 ] 976{ 977 case $#:$1 in 978 0:|1:1) DIAGNOSTICS=1 979 EXIT='*' 980 ;; 981 1:|1:0) DIAGNOSTICS="" 982 EXIT=0 983 ;; 984 *) DIAGNOSTICS=$1 985 EXIT='*' 986 ;; 987 esac 988} 989 990function IGNORESPACE 991{ 992 : ${IGNORESPACE=-b} 993} 994 995function EXIT # status 996{ 997 EXIT=$1 998} 999 1000function INFO # info description 1001{ 1002 typeset -R15 info=$1 1003 if [[ ! $1 ]] 1004 then info=no 1005 fi 1006 shift 1007 if [[ ! $TEST_quiet ]] 1008 then print -r -u2 "$info " "$@" 1009 fi 1010} 1011 1012function COMMAND # arg ... 1013{ 1014 typeset input 1015 ((TESTS++)) 1016 case " ${ENVIRON[*]} ${EXPORT[*]}" in 1017 *' 'LC_ALL=*) 1018 ;; 1019 *' 'LC_+([A-Z])=*) 1020 EXPORT[EXPORTS++]="LC_ALL=" 1021 ;; 1022 esac 1023 if [[ $TEST_keep ]] 1024 then ( 1025 PS4='' 1026 set -x 1027 print -r -- "${ENVIRON[@]}" "${EXPORT[@]}" "PATH=$PATH" $COMMAND "$@" 1028 ) 2>&1 >/dev/null | 1029 sed -e 's,^print -r -- ,,' -e 's,$, "$@",' >$TWD/COMMAND 1030 chmod +x $TWD/COMMAND 1031 fi 1032 if [[ $UMASK != $UMASK_ORIG ]] 1033 then : >$TWD/ERROR 1034 umask $UMASK 1035 fi 1036 if [[ ${TYPE[INPUT]} == FIFO && ${FILE[INPUT]} == */INPUT ]] 1037 then input="< ${FILE[INPUT]}" 1038 fi 1039 if [[ $TEST_trace ]] 1040 then set +x 1041 eval print -u2 "$PS4" "${ENVIRON[@]}" "${EXPORT[@]}" PATH='$PATH' '$'COMMAND '"$@"' '$input' '"2>$TWD/ERROR"' '"${JOBPID:+&}"' 1042 fi 1043 eval "${ENVIRON[@]}" "${EXPORT[@]}" PATH='$PATH' '$'COMMAND '"$@"' $input "2>$TWD/ERROR" "${JOBPID:+&}" 1044 STATUS=$? 1045 [[ $TEST_trace ]] && set -x 1046 if [[ $JOBPID ]] 1047 then JOBPID=$! 1048 fi 1049 [[ $UMASK != $UMASK_ORIG ]] && umask $UMASK_ORIG 1050 return $STATUS 1051} 1052 1053function RESULTS # pipe* 1054{ 1055 typeset i j k s failed ignore io op 1056 if [[ $1 ]] 1057 then io="$1 " 1058 fi 1059 [[ $JOBOP || $JOBPID || $JOBSTATUS ]] && sleep 1 1060 for i in $COMPARE $TWD/OUTPUT $TWD/ERROR 1061 do case " $IGNORE $ignore $MOVE " in 1062 *" $i "*) continue ;; 1063 esac 1064 ignore="$ignore $i" 1065 op=${i##*/} 1066 if [[ ${FILTER[$op]} ]] 1067 then eval "{ ${FILTER[$op]} ;} < $i > $i.fi" 1068 mv $i.fi $i 1069 fi 1070 j=${SAME[$op]} 1071 if [[ ! $j ]] 1072 then if [[ $i == /* ]] 1073 then k=$i 1074 else k=$TWD/$i 1075 fi 1076 for s in ex sav err 1077 do [[ -f $k.$s ]] && break 1078 done 1079 j=$k.$s 1080 fi 1081 if [[ "$DIAGNOSTICS" && $i == */ERROR ]] 1082 then if [[ $STATUS == 0 && ! -s $TWD/ERROR || $DIAGNOSTICS != 1 && $(<$i) != $DIAGNOSTICS ]] 1083 then failed=$failed${failed:+,}DIAGNOSTICS 1084 if [[ $TEST_verbose && $DIAGNOSTICS != 1 ]] 1085 then print -u2 " ===" "diagnostic pattern '$DIAGNOSTICS' did not match" ${i#$TWD/} "===" 1086 cat $i >&2 1087 fi 1088 fi 1089 continue 1090 fi 1091 diff $IGNORESPACE $i $j >$i.diff 2>&1 1092 if [[ -s $i.diff ]] 1093 then failed=$failed${failed:+,}${i#$TWD/} 1094 if [[ $TEST_verbose ]] 1095 then print -u2 " ===" diff $IGNORESPACE ${i#$TWD/} "<actual >expected ===" 1096 cat $i.diff >&2 1097 fi 1098 fi 1099 done 1100 if [[ $JOBOP ]] 1101 then if [[ $JOBPID ]] && ! kill -0 $JOBPID 2>/dev/null 1102 then wait $JOBPID 1103 JOBSTATUS=$? 1104 JOBPID= 1105 fi 1106#print -u2 AHA#$LINENO JOBOP=$JOBOP JOBPID=$JOBPID JOBSTATUS=$JOBSTATUS 1107 case $JOBOP in 1108 CONTINUE) 1109 if [[ ! $JOBPID ]] 1110 then failed=$failed${failed:+,}EXITED 1111 fi 1112 ;; 1113 EXITED) if [[ $JOBPID ]] 1114 then failed=$failed${failed:+,}RUNNING 1115 fi 1116 ;; 1117 *) if [[ ! $JOBPID ]] 1118 then failed=$failed${failed:+,}EXITED 1119 fi 1120 if ! kill -$JOBOP $JOBPID 2>/dev/null 1121 then failed=$failed${failed:+,}KILL-$JOBOP 1122 fi 1123 ;; 1124 esac 1125 JOBOP= 1126 fi 1127 if [[ ! $failed && $STATUS != $EXIT ]] 1128 then failed="exit code $EXIT expected -- got $STATUS" 1129 fi 1130 if [[ $failed ]] 1131 then ((ERRORS++)) 1132 if [[ ! $TEST_quiet ]] 1133 then SHOW="FAILED ${io}[ $failed ] $NOTE" 1134 print -r -u2 " $SHOW" 1135 fi 1136 if [[ $TEST_keep ]] 1137 then GROUP=FINI 1138 exit 1139 fi 1140 elif [[ ! $TEST_quiet ]] 1141 then SHOW=$NOTE 1142 print -r -u2 " $SHOW" 1143 fi 1144} 1145 1146function SET # [no]name[=value] 1147{ 1148 typeset i r 1149 if [[ $TEST ]] 1150 then RUN 1151 fi 1152 for i 1153 do if [[ $i == - ]] 1154 then r=1 1155 elif [[ $i == + ]] 1156 then r= 1157 else if [[ $i == no?* ]] 1158 then i=${i#no} 1159 v= 1160 elif [[ $i == *=* ]] 1161 then v=${i#*=} 1162 if [[ $v == 0 ]] 1163 then v= 1164 fi 1165 i=${i%%=*} 1166 else v=1 1167 fi 1168 i=${i//-/_} 1169 if [[ $r ]] 1170 then READONLY[$i]=1 1171 elif [[ ${READONLY[$i]} ]] 1172 then continue 1173 fi 1174 eval TEST_$i=$v 1175 fi 1176 done 1177} 1178 1179function VIEW # var [ file ] 1180{ 1181 nameref var=$1 1182 typeset i bwd file pwd view root offset 1183 if [[ $var ]] 1184 then return 0 1185 fi 1186 case $# in 1187 1) file=$1 ;; 1188 *) file=$2 ;; 1189 esac 1190 pwd=${TWD%/*} 1191 bwd=${PMP%/*} 1192 if [[ -r $file ]] 1193 then if [[ ! -d $file ]] 1194 then var=$PWD/$file 1195 return 0 1196 fi 1197 for i in $file/* 1198 do if [[ -r $i ]] 1199 then var=$PWD/$file 1200 return 0 1201 fi 1202 break 1203 done 1204 fi 1205 for view in ${VIEWS[@]} 1206 do case $view in 1207 /*) ;; 1208 *) view=$pwd/$view ;; 1209 esac 1210 case $offset in 1211 '') case $pwd in 1212 $view/*) offset=${pwd#$view} ;; 1213 *) offset=${bwd#$view} ;; 1214 esac 1215 ;; 1216 esac 1217 if [[ -r $view$offset/$file ]] 1218 then if [[ ! -d $view$offset/$file ]] 1219 then var=$view$offset/$file 1220 return 0 1221 fi 1222 for i in $view$offset/$file/* 1223 do if [[ -f $i ]] 1224 then var=$view$offset/$file 1225 return 0 1226 fi 1227 break 1228 done 1229 fi 1230 done 1231 var= 1232 return 1 1233} 1234 1235function INCLUDE # file ... 1236{ 1237 typeset f v x 1238 for f 1239 do if VIEW v $f || [[ $PREFIX && $f != /* ]] && VIEW v $PREFIX$f 1240 then x=$x$'\n'". $v" 1241 else FATAL $f: not found 1242 fi 1243 done 1244 [[ $x ]] && trap "$x" 0 1245} 1246 1247function UMASK # [ mask ] 1248{ 1249 if (( $# )) 1250 then UMASK=$1 1251 else UMASK=$UMASK_ORIG 1252 fi 1253} 1254 1255function PIPE # INPUT|OUTPUT|ERROR file|- data ... 1256{ 1257 IO $0 "$@" 1258} 1259 1260function FIFO # INPUT|OUTPUT|ERROR file|- data ... 1261{ 1262 IO $0 "$@" 1263} 1264 1265function IF # command(s) [note] 1266{ 1267 [[ $GROUP == $TEST_select ]] || return 1268 RUN 1269 (( COND++ )) 1270 COND_LINE[COND]=$LINE 1271 if (( COND > 1 && COND_SKIP[COND-1] )) 1272 then (( COND_KEPT[COND] = 1 )) 1273 (( COND_SKIP[COND] = 1 )) 1274 elif eval "{ $1 ;} >/dev/null 2>&1" 1275 then (( COND_KEPT[COND] = 1 )) 1276 (( COND_SKIP[COND] = 0 )) 1277 [[ $2 && ! $TEST_quiet ]] && print -u2 "NOTE $2" 1278 else (( COND_KEPT[COND] = 0 )) 1279 (( COND_SKIP[COND] = 1 )) 1280 fi 1281} 1282 1283function ELIF # command(s) [note] 1284{ 1285 [[ $GROUP == $TEST_select ]] || return 1286 RUN 1287 if (( COND <= 0 )) 1288 then FATAL line $LINE: no matching IF for ELIF 1289 fi 1290 if (( COND_KEPT[COND] )) 1291 then (( COND_SKIP[COND] = 0 )) 1292 elif eval "$* > /dev/null 2>&1" 1293 then (( COND_KEPT[COND] = 1 )) 1294 (( COND_SKIP[COND] = 0 )) 1295 [[ $2 && ! $TEST_quiet ]] && print -u2 "NOTE $2" 1296 else (( COND_SKIP[COND] = 1 )) 1297 fi 1298} 1299 1300function ELSE # [note] 1301{ 1302 [[ $GROUP == $TEST_select ]] || return 1303 RUN 1304 if (( COND <= 0 )) 1305 then FATAL line $LINE: no matching IF for ELSE 1306 fi 1307 if (( COND_KEPT[COND] )) 1308 then (( COND_SKIP[COND] = 1 )) 1309 else (( COND_KEPT[COND] = 1 )) 1310 (( COND_SKIP[COND] = 0 )) 1311 [[ $1 && ! $TEST_quiet ]] && print -u2 "NOTE $1" 1312 fi 1313} 1314 1315function FI 1316{ 1317 [[ $GROUP == $TEST_select ]] || return 1318 RUN 1319 if (( COND <= 0 )) 1320 then FATAL line $LINE: no matching IF for FI on line $LINE 1321 fi 1322 (( ! COND_KEPT[COND] )) && [[ $1 && ! $TEST_quiet ]] && print -u2 "NOTE $1" 1323 (( COND-- )) 1324} 1325 1326# main 1327 1328integer ERRORS=0 ENVIRONS=0 EXPORTS=0 TESTS=0 SUBTESTS=0 LINE=0 TESTLINE=0 1329integer ITEM=0 LASTITEM=0 COND=0 UNIT_READONLY=0 COUNT 1330typeset ARGS COMMAND COPY DIAGNOSTICS ERROR EXEC FLUSHED=0 GROUP=INIT 1331typeset IGNORE INPUT KEEP OUTPUT TEST SOURCE MOVE NOTE UMASK UMASK_ORIG 1332typeset ARGS_ORIG COMMAND_ORIG TITLE UNIT ARGV PREFIX OFFSET IGNORESPACE 1333typeset COMPARE MAIN JOBPID='' JOBSTATUS='' 1334typeset TEST_file TEST_keep TEST_pipe_input TEST_pipe_io TEST_pipe_output TEST_local 1335typeset TEST_quiet TEST_regular=1 TEST_rmflags='-rf --' TEST_rmu TEST_select 1336 1337typeset -A SAME VIEWS FILE TYPE READONLY FILTER 1338typeset -a COND_LINE COND_SKIP COND_KEPT ENVIRON EXPORT 1339typeset -Z LAST=00 1340 1341unset FIGNORE 1342 1343while getopts -a $command "$USAGE" OPT 1344do case $OPT in 1345 b) (( $OPTARG )) && IGNORESPACE=-b 1346 ;; 1347 i) SET - pipe-input=$OPTARG 1348 ;; 1349 k) SET - keep=$OPTARG 1350 ;; 1351 l) SET - local 1352 ;; 1353 o) SET - pipe-output=$OPTARG 1354 ;; 1355 p) SET - pipe-io=$OPTARG 1356 ;; 1357 q) SET - quiet=$OPTARG 1358 ;; 1359 r) SET - regular=$OPTARG 1360 ;; 1361 t) if [[ $TEST_select ]] 1362 then TEST_select="$TEST_select|${OPTARG//,/\|}" 1363 else TEST_select="${OPTARG//,/\|}" 1364 fi 1365 ;; 1366 x) SET - trace=$OPTARG 1367 ;; 1368 v) SET - verbose=$OPTARG 1369 ;; 1370 *) GROUP=FINI 1371 exit 2 1372 ;; 1373 esac 1374done 1375shift $OPTIND-1 1376case $# in 13770) FATAL test unit name omitted ;; 1378esac 1379export COLUMNS=80 1380SOURCE=$PWD 1381PATH=$SOURCE:${PATH#?(.):} 1382PATH=${PATH%%:?(.)}:/bin:/usr/bin 1383UNIT=$1 1384shift 1385if [[ -f $UNIT && ! -x $UNIT ]] 1386then REGRESS=$UNIT 1387else REGRESS=${UNIT%.tst} 1388 REGRESS=$REGRESS.tst 1389 [[ -f $REGRESS ]] || FATAL $REGRESS: regression tests not found 1390fi 1391UNIT=${UNIT##*/} 1392UNIT=${UNIT%.tst} 1393MAIN=$UNIT 1394if [[ $VPATH ]] 1395then set -A VIEWS ${VPATH//:/' '} 1396 OFFSET=${SOURCE#${VIEWS[0]}} 1397 if [[ $OFFSET ]] 1398 then OFFSET=${OFFSET#/}/ 1399 fi 1400fi 1401if [[ $REGRESS == */* ]] 1402then PREFIX=${REGRESS%/*} 1403 if [[ ${#VIEWS[@]} ]] 1404 then for i in ${VIEWS[@]} 1405 do PREFIX=${PREFIX#$i/} 1406 done 1407 fi 1408 PREFIX=${PREFIX#$OFFSET} 1409 if [[ $PREFIX ]] 1410 then PREFIX=$PREFIX/ 1411 fi 1412fi 1413TWD=$PWD/$UNIT.tmp 1414PMP=$(pwd -P)/$UNIT.tmp 1415UMASK_ORIG=$(umask) 1416UMASK=$UMASK_ORIG 1417ARGV=("$@") 1418if [[ ${ARGV[0]} && ${ARGV[0]} != [-+]* ]] 1419then UNIT "${ARGV[@]}" 1420 UNIT_READONLY=1 1421fi 1422trap 'code=$?; CLEANUP $code' EXIT 1423if [[ ! $TEST_select ]] 1424then TEST_select="[0123456789]*" 1425fi 1426TEST_select="@($TEST_select|+(0))" 1427if [[ $TEST_trace ]] 1428then export PS4=':$LINENO: ' 1429 typeset -ft $(typeset +f) 1430 set -x 1431fi 1432if [[ $TEST_verbose ]] 1433then typeset SHOW 1434else typeset -L70 SHOW 1435fi 1436if [[ ! $TEST_keep ]] && (ulimit -c 0) >/dev/null 2>&1 1437then ulimit -c 0 1438fi 1439set --pipefail 1440 1441# some last minute shenanigans 1442 1443alias BODY='BODY=BODY; function BODY' 1444alias CONTINUE='LINE=$LINENO; CONTINUE' 1445alias DO='(( $ITEM != $FLUSHED )) && RUN DO; DO &&' 1446alias DONE='DONE=DONE; function DONE' 1447alias EXEC='LINE=$LINENO; EXEC' 1448alias EXITED='LINE=$LINENO; EXITED' 1449alias INIT='INIT=INIT; function INIT' 1450alias JOB='LINE=$LINENO; JOB' 1451alias KILL='LINE=$LINENO; KILL' 1452alias PROG='LINE=$LINENO; FLUSH; PROG' 1453alias TEST='TESTLINE=$LINENO; TEST' 1454alias IF='LINE=$LINENO; FLUSH; IF' 1455alias ELIF='LINE=$LINENO; FLUSH; ELIF' 1456alias ELSE='LINE=$LINENO; FLUSH; ELSE' 1457alias FI='LINE=$LINENO; FLUSH; FI' 1458 1459# do the tests 1460 1461. $REGRESS 1462RUN 1463GROUP=FINI 1464