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 but retry the command on failure if the output
72 # matches an expected pattern. Otherwise behave like log_must and exit
73 # $STF_FAIL is test fails.
77 # $3-$@ - command to execute
79 function log_must_retry
82 typeset logfile="/tmp/log.$$"
89 while [[ -e $logfile ]]; do
93 while (( $retry > 0 )); do
98 if (( $status == 0 )); then
99 $out | egrep -i "internal error|assertion failed" \
101 # internal error or assertion failed
102 if [[ $? -eq 0 ]]; then
104 _printerror "$@" "internal error or" \
105 " assertion failure exited $status"
108 [[ -n $LOGAPI_DEBUG ]] && print $($out)
113 $out | grep -i "$expect" > /dev/null 2>&1
114 if (( $? == 0 )); then
116 _printerror "$@" "Retry in $delay seconds"
119 (( retry=retry - 1 ))
120 (( delay=delay * 2 ))
127 if (( $status != 0 )) ; then
129 _printerror "$@" "exited $status"
132 _recursive_output $logfile "false"
136 # Execute a positive test and exit $STF_FAIL is test fails after being
137 # retried up to 5 times when the command returns the keyword "busy".
139 # $@ - command to execute
140 function log_must_busy
142 log_must_retry "busy" 5 "$@"
143 (( $? != 0 )) && log_fail
146 # Execute a negative test and exit $STF_FAIL if test passes
148 # $@ - command to execute
153 (( $? != 0 )) && log_fail
156 # Execute a negative test with keyword expected, and exit
157 # $STF_FAIL if test passes
159 # $1 - keyword expected
160 # $2-$@ - command to execute
162 function log_mustnot_expect
165 (( $? != 0 )) && log_fail
168 # Signal numbers are platform-dependent
182 EXIT_SIGBUS=$((EXIT_SIGNAL + SIGBUS))
183 EXIT_SIGSEGV=$((EXIT_SIGNAL + SIGSEGV))
185 # Execute and print command with status where success equals non-zero result
186 # or output includes expected keyword
188 # $1 - keyword expected
189 # $2-$@ - command to execute
191 # return 0 if command fails, or the output contains the keyword expected,
194 function log_neg_expect
197 typeset logfile="/tmp/log.$$"
202 while [[ -e $logfile ]]; do
203 logfile="$logfile.$$"
211 if (( $status == EXIT_SUCCESS )); then
213 _printerror "$@" "unexpectedly exited $status"
215 elif (( $status == EXIT_NOTFOUND )); then
217 _printerror "$@" "unexpectedly exited $status (File not found)"
218 # bus error - core dump
219 elif (( $status == EXIT_SIGBUS )); then
221 _printerror "$@" "unexpectedly exited $status (Bus Error)"
222 # segmentation violation - core dump
223 elif (( $status == EXIT_SIGSEGV )); then
225 _printerror "$@" "unexpectedly exited $status (SEGV)"
227 $out | egrep -i "internal error|assertion failed" \
229 # internal error or assertion failed
230 if (( $? == 0 )); then
232 _printerror "$@" "internal error or assertion failure" \
234 elif [[ -n $expect ]] ; then
235 $out | grep -i "$expect" > /dev/null 2>&1
236 if (( $? == 0 )); then
240 _printerror "$@" "unexpectedly exited $status"
246 if (( $ret == 0 )); then
247 [[ -n $LOGAPI_DEBUG ]] && print $($out)
248 _printsuccess "$@" "exited $status"
251 _recursive_output $logfile "false"
255 # Execute and print command with status where success equals zero result
257 # $@ command to execute
259 # return command exit status
264 typeset logfile="/tmp/log.$$"
266 while [[ -e $logfile ]]; do
267 logfile="$logfile.$$"
274 if (( $status != 0 )) ; then
276 _printerror "$@" "exited $status"
278 $out | egrep -i "internal error|assertion failed" \
280 # internal error or assertion failed
281 if [[ $? -eq 0 ]]; then
283 _printerror "$@" "internal error or assertion failure" \
287 [[ -n $LOGAPI_DEBUG ]] && print $($out)
291 _recursive_output $logfile "false"
295 # Set an exit handler
297 # $@ - function(s) to perform on exit
304 # Push an exit handler on the cleanup stack
306 # $@ - function(s) to perform on exit
308 function log_onexit_push
313 # Pop an exit handler off the cleanup stack
315 function log_onexit_pop
317 _CLEANUP=("${_CLEANUP[@]:0:${#_CLEANUP[@]}-1}")
324 # Perform cleanup and exit $STF_PASS
330 _endlog $STF_PASS "$@"
333 # Perform cleanup and exit $STF_FAIL
339 _endlog $STF_FAIL "$@"
342 # Perform cleanup and exit $STF_UNRESOLVED
346 function log_unresolved
348 _endlog $STF_UNRESOLVED "$@"
351 # Perform cleanup and exit $STF_NOTINUSE
355 function log_notinuse
357 _endlog $STF_NOTINUSE "$@"
360 # Perform cleanup and exit $STF_UNSUPPORTED
364 function log_unsupported
366 _endlog $STF_UNSUPPORTED "$@"
369 # Perform cleanup and exit $STF_UNTESTED
373 function log_untested
375 _endlog $STF_UNTESTED "$@"
378 # Perform cleanup and exit $STF_UNINITIATED
382 function log_uninitiated
384 _endlog $STF_UNINITIATED "$@"
387 # Perform cleanup and exit $STF_NORESULT
391 function log_noresult
393 _endlog $STF_NORESULT "$@"
396 # Perform cleanup and exit $STF_WARNING
402 _endlog $STF_WARNING "$@"
405 # Perform cleanup and exit $STF_TIMED_OUT
409 function log_timed_out
411 _endlog $STF_TIMED_OUT "$@"
414 # Perform cleanup and exit $STF_OTHER
420 _endlog $STF_OTHER "$@"
423 function set_main_pid
432 # Execute custom callback scripts on test failure
434 # callback script paths are stored in TESTFAIL_CALLBACKS, delimited by ':'.
436 function _execute_testfail_callbacks
440 print "$TESTFAIL_CALLBACKS:" | while read -d ":" callback; do
441 if [[ -n "$callback" ]] ; then
442 log_note "Performing test-fail callback ($callback)"
448 # Perform cleanup and exit
451 # $2-$n - message text
455 typeset logfile="/tmp/log.$$"
456 _recursive_output $logfile
460 (( ${#@} > 0 )) && _printline "$@"
463 # If we're running in a subshell then just exit and let
464 # the parent handle the failures
466 if [[ -n "$_MAINPID" && $$ != "$_MAINPID" ]]; then
467 log_note "subshell exited: "$_MAINPID
471 if [[ $exitcode == $STF_FAIL ]] ; then
472 _execute_testfail_callbacks
475 typeset stack=("${_CLEANUP[@]}")
477 typeset i=${#stack[@]}
479 typeset cleanup="${stack[i]}"
480 log_note "Performing local cleanup via log_onexit ($cleanup)"
487 # Output a formatted line
496 # Output an error message
502 _printline ERROR: "$@"
505 # Output a success message
509 function _printsuccess
511 _printline SUCCESS: "$@"
514 # Output logfiles recursively
517 # $2 - indicate whether output the start file itself, default as yes.
519 function _recursive_output #logfile
523 while [[ -e $logfile ]]; do
524 if [[ -z $2 || $logfile != $1 ]]; then
528 logfile="$logfile.$$"