4 # The contents of this file are subject to the terms of the
5 # Common Development and Distribution License (the "License").
6 # You may not use this file except in compliance with the License.
8 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 # or http://www.opensolaris.org/os/licensing.
10 # See the License for the specific language governing permissions
11 # and limitations under the License.
13 # When distributing Covered Code, include this CDDL HEADER in each
14 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 # If applicable, add the following below this CDDL HEADER, with the
16 # fields enclosed by brackets "[]" replaced with your own identifying
17 # information: Portions Copyright [yyyy] [name of copyright owner]
23 # Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 # Use is subject to license terms.
26 # Copyright (c) 2012, 2020 by Delphix. All rights reserved.
29 . ${STF_TOOLS}/include/stf.shlib
37 _printline ASSERTION: "$@"
49 # Execute and print command with status where success equals non-zero result
51 # $@ - command to execute
53 # return 0 if command fails, otherwise return 1
57 log_neg_expect "" "$@"
61 # Execute a positive test and exit $STF_FAIL is test fails
63 # $@ - command to execute
68 (( $? != 0 )) && log_fail
71 # Execute a positive test (expecting no stderr) and exit $STF_FAIL
73 # $@ - command to execute
75 function log_must_nostderr
78 (( $? != 0 )) && log_fail
81 # Execute a positive test but retry the command on failure if the output
82 # matches an expected pattern. Otherwise behave like log_must and exit
83 # $STF_FAIL is test fails.
87 # $3-$@ - command to execute
89 function log_must_retry
92 typeset logfile="/tmp/log.$$"
99 while [[ -e $logfile ]]; do
100 logfile="$logfile.$$"
103 while (( $retry > 0 )); do
108 if (( $status == 0 )); then
109 $out | egrep -i "internal error|assertion failed" \
111 # internal error or assertion failed
112 if [[ $? -eq 0 ]]; then
114 _printerror "$@" "internal error or" \
115 " assertion failure exited $status"
118 [[ -n $LOGAPI_DEBUG ]] && cat $logfile
123 $out | grep -i "$expect" > /dev/null 2>&1
124 if (( $? == 0 )); then
126 _printerror "$@" "Retry in $delay seconds"
129 (( retry=retry - 1 ))
130 (( delay=delay * 2 ))
137 if (( $status != 0 )) ; then
139 _printerror "$@" "exited $status"
142 _recursive_output $logfile "false"
146 # Execute a positive test and exit $STF_FAIL is test fails after being
147 # retried up to 5 times when the command returns the keyword "busy".
149 # $@ - command to execute
150 function log_must_busy
152 log_must_retry "busy" 5 "$@"
153 (( $? != 0 )) && log_fail
156 # Execute a negative test and exit $STF_FAIL if test passes
158 # $@ - command to execute
163 (( $? != 0 )) && log_fail
166 # Execute a negative test with keyword expected, and exit
167 # $STF_FAIL if test passes
169 # $1 - keyword expected
170 # $2-$@ - command to execute
172 function log_mustnot_expect
175 (( $? != 0 )) && log_fail
178 # Signal numbers are platform-dependent
192 EXIT_SIGBUS=$((EXIT_SIGNAL + SIGBUS))
193 EXIT_SIGSEGV=$((EXIT_SIGNAL + SIGSEGV))
195 # Execute and print command with status where success equals non-zero result
196 # or output includes expected keyword
198 # $1 - keyword expected
199 # $2-$@ - command to execute
201 # return 0 if command fails, or the output contains the keyword expected,
204 function log_neg_expect
207 typeset logfile="/tmp/log.$$"
212 while [[ -e $logfile ]]; do
213 logfile="$logfile.$$"
221 if (( $status == EXIT_SUCCESS )); then
223 _printerror "$@" "unexpectedly exited $status"
225 elif (( $status == EXIT_NOTFOUND )); then
227 _printerror "$@" "unexpectedly exited $status (File not found)"
228 # bus error - core dump
229 elif (( $status == EXIT_SIGBUS )); then
231 _printerror "$@" "unexpectedly exited $status (Bus Error)"
232 # segmentation violation - core dump
233 elif (( $status == EXIT_SIGSEGV )); then
235 _printerror "$@" "unexpectedly exited $status (SEGV)"
237 $out | egrep -i "internal error|assertion failed" \
239 # internal error or assertion failed
240 if (( $? == 0 )); then
242 _printerror "$@" "internal error or assertion failure" \
244 elif [[ -n $expect ]] ; then
245 $out | grep -i "$expect" > /dev/null 2>&1
246 if (( $? == 0 )); then
250 _printerror "$@" "unexpectedly exited $status"
256 if (( $ret == 0 )); then
257 [[ -n $LOGAPI_DEBUG ]] && cat $logfile
258 _printsuccess "$@" "exited $status"
261 _recursive_output $logfile "false"
265 # Execute and print command with status where success equals zero result
267 # $@ command to execute
269 # return command exit status
274 typeset logfile="/tmp/log.$$"
276 while [[ -e $logfile ]]; do
277 logfile="$logfile.$$"
284 if (( $status != 0 )) ; then
286 _printerror "$@" "exited $status"
288 $out | egrep -i "internal error|assertion failed" \
290 # internal error or assertion failed
291 if [[ $? -eq 0 ]]; then
293 _printerror "$@" "internal error or assertion failure" \
297 [[ -n $LOGAPI_DEBUG ]] && cat $logfile
301 _recursive_output $logfile "false"
305 # Execute and print command with status where success equals zero result
306 # and no stderr output
308 # $@ command to execute
310 # return 0 if command succeeds and no stderr output
313 function log_pos_nostderr
316 typeset logfile="/tmp/log.$$"
318 while [[ -e $logfile ]]; do
319 logfile="$logfile.$$"
325 typeset out_msg=$($out)
327 if (( $status != 0 )) ; then
329 _printerror "$@" "exited $status"
331 if [[ ! -z "$out_msg" ]]; then
333 _printerror "$@" "message in stderr" \
337 [[ -n $LOGAPI_DEBUG ]] && cat $logfile
341 _recursive_output $logfile "false"
345 # Set an exit handler
347 # $@ - function(s) to perform on exit
354 # Push an exit handler on the cleanup stack
356 # $@ - function(s) to perform on exit
358 function log_onexit_push
363 # Pop an exit handler off the cleanup stack
365 function log_onexit_pop
367 _CLEANUP=("${_CLEANUP[@]:0:${#_CLEANUP[@]}-1}")
374 # Perform cleanup and exit $STF_PASS
380 _endlog $STF_PASS "$@"
383 # Perform cleanup and exit $STF_FAIL
389 _endlog $STF_FAIL "$@"
392 # Perform cleanup and exit $STF_UNRESOLVED
396 function log_unresolved
398 _endlog $STF_UNRESOLVED "$@"
401 # Perform cleanup and exit $STF_NOTINUSE
405 function log_notinuse
407 _endlog $STF_NOTINUSE "$@"
410 # Perform cleanup and exit $STF_UNSUPPORTED
414 function log_unsupported
416 _endlog $STF_UNSUPPORTED "$@"
419 # Perform cleanup and exit $STF_UNTESTED
423 function log_untested
425 _endlog $STF_UNTESTED "$@"
428 # Perform cleanup and exit $STF_UNINITIATED
432 function log_uninitiated
434 _endlog $STF_UNINITIATED "$@"
437 # Perform cleanup and exit $STF_NORESULT
441 function log_noresult
443 _endlog $STF_NORESULT "$@"
446 # Perform cleanup and exit $STF_WARNING
452 _endlog $STF_WARNING "$@"
455 # Perform cleanup and exit $STF_TIMED_OUT
459 function log_timed_out
461 _endlog $STF_TIMED_OUT "$@"
464 # Perform cleanup and exit $STF_OTHER
470 _endlog $STF_OTHER "$@"
473 function set_main_pid
482 # Execute custom callback scripts on test failure
484 # callback script paths are stored in TESTFAIL_CALLBACKS, delimited by ':'.
486 function _execute_testfail_callbacks
490 print "$TESTFAIL_CALLBACKS:" | while read -d ":" callback; do
491 if [[ -n "$callback" ]] ; then
492 log_note "Performing test-fail callback ($callback)"
498 # Perform cleanup and exit
501 # $2-$n - message text
505 typeset logfile="/tmp/log.$$"
506 _recursive_output $logfile
510 (( ${#@} > 0 )) && _printline "$@"
513 # If we're running in a subshell then just exit and let
514 # the parent handle the failures
516 if [[ -n "$_MAINPID" && $$ != "$_MAINPID" ]]; then
517 log_note "subshell exited: "$_MAINPID
521 if [[ $exitcode == $STF_FAIL ]] ; then
522 _execute_testfail_callbacks
525 typeset stack=("${_CLEANUP[@]}")
527 typeset i=${#stack[@]}
529 typeset cleanup="${stack[i]}"
530 log_note "Performing local cleanup via log_onexit ($cleanup)"
537 # Output a formatted line
546 # Output an error message
552 _printline ERROR: "$@"
555 # Output a success message
559 function _printsuccess
561 _printline SUCCESS: "$@"
564 # Output logfiles recursively
567 # $2 - indicate whether output the start file itself, default as yes.
569 function _recursive_output #logfile
573 while [[ -e $logfile ]]; do
574 if [[ -z $2 || $logfile != $1 ]]; then
578 logfile="$logfile.$$"