mirror of
				https://git.proxmox.com/git/mirror_zfs
				synced 2025-11-04 01:24:57 +00:00 
			
		
		
		
	The commit replaces all findings of the link: http://www.opensolaris.org/os/licensing with this one: https://opensource.org/licenses/CDDL-1.0 Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Tino Reichardt <milky-zfs@mcmilk.de> Closes #13619
		
			
				
	
	
		
			505 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			505 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
#
 | 
						|
# CDDL HEADER START
 | 
						|
#
 | 
						|
# The contents of this file are subject to the terms of the
 | 
						|
# Common Development and Distribution License (the "License").
 | 
						|
# You may not use this file except in compliance with the License.
 | 
						|
#
 | 
						|
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 | 
						|
# or https://opensource.org/licenses/CDDL-1.0.
 | 
						|
# See the License for the specific language governing permissions
 | 
						|
# and limitations under the License.
 | 
						|
#
 | 
						|
# When distributing Covered Code, include this CDDL HEADER in each
 | 
						|
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 | 
						|
# If applicable, add the following below this CDDL HEADER, with the
 | 
						|
# fields enclosed by brackets "[]" replaced with your own identifying
 | 
						|
# information: Portions Copyright [yyyy] [name of copyright owner]
 | 
						|
#
 | 
						|
# CDDL HEADER END
 | 
						|
#
 | 
						|
 | 
						|
#
 | 
						|
# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 | 
						|
# Use is subject to license terms.
 | 
						|
#
 | 
						|
# Copyright (c) 2012, 2020 by Delphix. All rights reserved.
 | 
						|
#
 | 
						|
 | 
						|
STF_PASS=0
 | 
						|
STF_FAIL=1
 | 
						|
STF_UNRESOLVED=2
 | 
						|
STF_UNSUPPORTED=4
 | 
						|
STF_UNTESTED=5
 | 
						|
 | 
						|
# Output an assertion
 | 
						|
#
 | 
						|
# $@ - assertion text
 | 
						|
 | 
						|
function log_assert
 | 
						|
{
 | 
						|
	_printline ASSERTION: "$@"
 | 
						|
}
 | 
						|
 | 
						|
# Output a comment
 | 
						|
#
 | 
						|
# $@ - comment text
 | 
						|
 | 
						|
function log_note
 | 
						|
{
 | 
						|
	_printline NOTE: "$@"
 | 
						|
}
 | 
						|
 | 
						|
# Execute and print command with status where success equals non-zero result
 | 
						|
#
 | 
						|
# $@ - command to execute
 | 
						|
#
 | 
						|
# return 0 if command fails, otherwise return 1
 | 
						|
 | 
						|
function log_neg
 | 
						|
{
 | 
						|
	log_neg_expect "" "$@"
 | 
						|
}
 | 
						|
 | 
						|
# Execute a positive test and exit $STF_FAIL is test fails
 | 
						|
#
 | 
						|
# $@ - command to execute
 | 
						|
 | 
						|
function log_must
 | 
						|
{
 | 
						|
	log_pos "$@" || log_fail
 | 
						|
}
 | 
						|
 | 
						|
# Execute a positive test (expecting no stderr) and exit $STF_FAIL
 | 
						|
# if test fails
 | 
						|
# $@ - command to execute
 | 
						|
 | 
						|
function log_must_nostderr
 | 
						|
{
 | 
						|
	log_pos_nostderr "$@" || log_fail
 | 
						|
}
 | 
						|
 | 
						|
# Execute a positive test but retry the command on failure if the output
 | 
						|
# matches an expected pattern.  Otherwise behave like log_must and exit
 | 
						|
# $STF_FAIL is test fails.
 | 
						|
#
 | 
						|
# $1 - retry keyword
 | 
						|
# $2 - retry attempts
 | 
						|
# $3-$@ - command to execute
 | 
						|
#
 | 
						|
function log_must_retry
 | 
						|
{
 | 
						|
	typeset logfile="/tmp/log.$$"
 | 
						|
	typeset status=1
 | 
						|
	typeset expect=$1
 | 
						|
	typeset retry=$2
 | 
						|
	typeset delay=1
 | 
						|
	shift 2
 | 
						|
 | 
						|
	while [[ -e $logfile ]]; do
 | 
						|
		logfile="$logfile.$$"
 | 
						|
	done
 | 
						|
 | 
						|
	while (( $retry > 0 )); do
 | 
						|
		"$@" 2>$logfile
 | 
						|
		status=$?
 | 
						|
 | 
						|
		if (( $status == 0 )); then
 | 
						|
			if grep -qEi "internal error|assertion failed" $logfile; then
 | 
						|
				cat $logfile >&2
 | 
						|
				_printerror "$@" "internal error or" \
 | 
						|
					" assertion failure exited $status"
 | 
						|
				status=1
 | 
						|
			else
 | 
						|
				[[ -n $LOGAPI_DEBUG ]] && cat $logfile
 | 
						|
				_printsuccess "$@"
 | 
						|
			fi
 | 
						|
			break
 | 
						|
		else
 | 
						|
			if grep -qi "$expect" $logfile; then
 | 
						|
				cat $logfile >&2
 | 
						|
				_printerror "$@" "Retry in $delay seconds"
 | 
						|
				sleep $delay
 | 
						|
 | 
						|
				(( retry=retry - 1 ))
 | 
						|
				(( delay=delay * 2 ))
 | 
						|
			else
 | 
						|
				break;
 | 
						|
			fi
 | 
						|
		fi
 | 
						|
	done
 | 
						|
 | 
						|
	if (( $status != 0 )) ; then
 | 
						|
		cat $logfile >&2
 | 
						|
		_printerror "$@" "exited $status"
 | 
						|
	fi
 | 
						|
 | 
						|
	_recursive_output $logfile "false"
 | 
						|
	return $status
 | 
						|
}
 | 
						|
 | 
						|
# Execute a positive test and exit $STF_FAIL is test fails after being
 | 
						|
# retried up to 5 times when the command returns the keyword "busy".
 | 
						|
#
 | 
						|
# $@ - command to execute
 | 
						|
function log_must_busy
 | 
						|
{
 | 
						|
	log_must_retry "busy" 5 "$@" || log_fail
 | 
						|
}
 | 
						|
 | 
						|
# Execute a negative test and exit $STF_FAIL if test passes
 | 
						|
#
 | 
						|
# $@ - command to execute
 | 
						|
 | 
						|
function log_mustnot
 | 
						|
{
 | 
						|
	log_neg "$@" || log_fail
 | 
						|
}
 | 
						|
 | 
						|
# Execute a negative test with keyword expected, and exit
 | 
						|
# $STF_FAIL if test passes
 | 
						|
#
 | 
						|
# $1 - keyword expected
 | 
						|
# $2-$@ - command to execute
 | 
						|
 | 
						|
function log_mustnot_expect
 | 
						|
{
 | 
						|
	log_neg_expect "$@" || log_fail
 | 
						|
}
 | 
						|
 | 
						|
# Signal numbers are platform-dependent
 | 
						|
case $(uname) in
 | 
						|
Darwin|FreeBSD)
 | 
						|
	SIGBUS=10
 | 
						|
	SIGSEGV=11
 | 
						|
	;;
 | 
						|
illumos|Linux|*)
 | 
						|
	SIGBUS=7
 | 
						|
	SIGSEGV=11
 | 
						|
	;;
 | 
						|
esac
 | 
						|
EXIT_SUCCESS=0
 | 
						|
EXIT_NOTFOUND=127
 | 
						|
EXIT_SIGNAL=256
 | 
						|
EXIT_SIGBUS=$((EXIT_SIGNAL + SIGBUS))
 | 
						|
EXIT_SIGSEGV=$((EXIT_SIGNAL + SIGSEGV))
 | 
						|
 | 
						|
# Execute and print command with status where success equals non-zero result
 | 
						|
# or output includes expected keyword
 | 
						|
#
 | 
						|
# $1 - keyword expected
 | 
						|
# $2-$@ - command to execute
 | 
						|
#
 | 
						|
# return 0 if command fails, or the output contains the keyword expected,
 | 
						|
# return 1 otherwise
 | 
						|
 | 
						|
function log_neg_expect
 | 
						|
{
 | 
						|
	typeset logfile="/tmp/log.$$"
 | 
						|
	typeset ret=1
 | 
						|
	typeset expect=$1
 | 
						|
	shift
 | 
						|
 | 
						|
	while [[ -e $logfile ]]; do
 | 
						|
		logfile="$logfile.$$"
 | 
						|
	done
 | 
						|
 | 
						|
	"$@" 2>$logfile
 | 
						|
	typeset status=$?
 | 
						|
 | 
						|
	# unexpected status
 | 
						|
	if (( $status == EXIT_SUCCESS )); then
 | 
						|
		 cat $logfile >&2
 | 
						|
		_printerror "$@" "unexpectedly exited $status"
 | 
						|
	# missing binary
 | 
						|
	elif (( $status == EXIT_NOTFOUND )); then
 | 
						|
		cat $logfile >&2
 | 
						|
		_printerror "$@" "unexpectedly exited $status (File not found)"
 | 
						|
	# bus error - core dump
 | 
						|
	elif (( $status == EXIT_SIGBUS )); then
 | 
						|
		cat $logfile >&2
 | 
						|
		_printerror "$@" "unexpectedly exited $status (Bus Error)"
 | 
						|
	# segmentation violation - core dump
 | 
						|
	elif (( $status == EXIT_SIGSEGV )); then
 | 
						|
		cat $logfile >&2
 | 
						|
		_printerror "$@" "unexpectedly exited $status (SEGV)"
 | 
						|
	else
 | 
						|
		if grep -qEi "internal error|assertion failed" $logfile; then
 | 
						|
			cat $logfile >&2
 | 
						|
			_printerror "$@" "internal error or assertion failure" \
 | 
						|
				" exited $status"
 | 
						|
		elif [[ -n $expect ]] ; then
 | 
						|
			if grep -qi "$expect" $logfile; then
 | 
						|
				ret=0
 | 
						|
			else
 | 
						|
				cat $logfile >&2
 | 
						|
				_printerror "$@" "unexpectedly exited $status"
 | 
						|
			fi
 | 
						|
		else
 | 
						|
			ret=0
 | 
						|
		fi
 | 
						|
 | 
						|
		if (( $ret == 0 )); then
 | 
						|
			[[ -n $LOGAPI_DEBUG ]] && cat $logfile
 | 
						|
			_printsuccess "$@" "exited $status"
 | 
						|
		fi
 | 
						|
	fi
 | 
						|
	_recursive_output $logfile "false"
 | 
						|
	return $ret
 | 
						|
}
 | 
						|
 | 
						|
# Execute and print command with status where success equals zero result
 | 
						|
#
 | 
						|
# $@ command to execute
 | 
						|
#
 | 
						|
# return command exit status
 | 
						|
 | 
						|
function log_pos
 | 
						|
{
 | 
						|
	typeset logfile="/tmp/log.$$"
 | 
						|
 | 
						|
	while [[ -e $logfile ]]; do
 | 
						|
		logfile="$logfile.$$"
 | 
						|
	done
 | 
						|
 | 
						|
	"$@" 2>$logfile
 | 
						|
	typeset status=$?
 | 
						|
 | 
						|
	if (( $status != 0 )) ; then
 | 
						|
		cat $logfile >&2
 | 
						|
		_printerror "$@" "exited $status"
 | 
						|
	else
 | 
						|
		if grep -qEi "internal error|assertion failed" $logfile; then
 | 
						|
			cat $logfile >&2
 | 
						|
			_printerror "$@" "internal error or assertion failure" \
 | 
						|
				" exited $status"
 | 
						|
			status=1
 | 
						|
		else
 | 
						|
			[[ -n $LOGAPI_DEBUG ]] && cat $logfile
 | 
						|
			_printsuccess "$@"
 | 
						|
		fi
 | 
						|
	fi
 | 
						|
	_recursive_output $logfile "false"
 | 
						|
	return $status
 | 
						|
}
 | 
						|
 | 
						|
# Execute and print command with status where success equals zero result
 | 
						|
# and no stderr output
 | 
						|
#
 | 
						|
# $@ command to execute
 | 
						|
#
 | 
						|
# return 0 if command succeeds and no stderr output
 | 
						|
# return 1 othersie
 | 
						|
 | 
						|
function log_pos_nostderr
 | 
						|
{
 | 
						|
	typeset logfile="/tmp/log.$$"
 | 
						|
 | 
						|
	while [[ -e $logfile ]]; do
 | 
						|
		logfile="$logfile.$$"
 | 
						|
	done
 | 
						|
 | 
						|
	"$@" 2>$logfile
 | 
						|
	typeset status=$?
 | 
						|
 | 
						|
	if (( $status != 0 )) ; then
 | 
						|
		cat $logfile >&2
 | 
						|
		_printerror "$@" "exited $status"
 | 
						|
	else
 | 
						|
		if [ -s "$logfile" ]; then
 | 
						|
			cat $logfile >&2
 | 
						|
			_printerror "$@" "message in stderr" \
 | 
						|
				" exited $status"
 | 
						|
			status=1
 | 
						|
		else
 | 
						|
			[[ -n $LOGAPI_DEBUG ]] && cat $logfile
 | 
						|
			_printsuccess "$@"
 | 
						|
		fi
 | 
						|
	fi
 | 
						|
	_recursive_output $logfile "false"
 | 
						|
	return $status
 | 
						|
}
 | 
						|
 | 
						|
# Set an exit handler
 | 
						|
#
 | 
						|
# $@ - function(s) to perform on exit
 | 
						|
 | 
						|
function log_onexit
 | 
						|
{
 | 
						|
	_CLEANUP=("$*")
 | 
						|
}
 | 
						|
 | 
						|
# Push an exit handler on the cleanup stack
 | 
						|
#
 | 
						|
# $@ - function(s) to perform on exit
 | 
						|
 | 
						|
function log_onexit_push
 | 
						|
{
 | 
						|
	_CLEANUP+=("$*")
 | 
						|
}
 | 
						|
 | 
						|
# Pop an exit handler off the cleanup stack
 | 
						|
 | 
						|
function log_onexit_pop
 | 
						|
{
 | 
						|
	_CLEANUP=("${_CLEANUP[@]:0:${#_CLEANUP[@]}-1}")
 | 
						|
}
 | 
						|
 | 
						|
#
 | 
						|
# Exit functions
 | 
						|
#
 | 
						|
 | 
						|
# Perform cleanup and exit $STF_PASS
 | 
						|
#
 | 
						|
# $@ - message text
 | 
						|
 | 
						|
function log_pass
 | 
						|
{
 | 
						|
	_endlog $STF_PASS "$@"
 | 
						|
}
 | 
						|
 | 
						|
# Perform cleanup and exit $STF_FAIL
 | 
						|
#
 | 
						|
# $@ - message text
 | 
						|
 | 
						|
function log_fail
 | 
						|
{
 | 
						|
	_endlog $STF_FAIL "$@"
 | 
						|
}
 | 
						|
 | 
						|
# Perform cleanup and exit $STF_UNRESOLVED
 | 
						|
#
 | 
						|
# $@ - message text
 | 
						|
 | 
						|
function log_unresolved
 | 
						|
{
 | 
						|
	_endlog $STF_UNRESOLVED "$@"
 | 
						|
}
 | 
						|
 | 
						|
# Perform cleanup and exit $STF_UNSUPPORTED
 | 
						|
#
 | 
						|
# $@ - message text
 | 
						|
 | 
						|
function log_unsupported
 | 
						|
{
 | 
						|
	_endlog $STF_UNSUPPORTED "$@"
 | 
						|
}
 | 
						|
 | 
						|
# Perform cleanup and exit $STF_UNTESTED
 | 
						|
#
 | 
						|
# $@ - message text
 | 
						|
 | 
						|
function log_untested
 | 
						|
{
 | 
						|
	_endlog $STF_UNTESTED "$@"
 | 
						|
}
 | 
						|
 | 
						|
function set_main_pid
 | 
						|
{
 | 
						|
	_MAINPID=$1
 | 
						|
}
 | 
						|
 | 
						|
#
 | 
						|
# Internal functions
 | 
						|
#
 | 
						|
 | 
						|
# Execute custom callback scripts on test failure
 | 
						|
#
 | 
						|
# callback script paths are stored in TESTFAIL_CALLBACKS, delimited by ':'.
 | 
						|
 | 
						|
function _execute_testfail_callbacks
 | 
						|
{
 | 
						|
	typeset callback
 | 
						|
 | 
						|
	while read -d ":" callback; do
 | 
						|
		if [[ -n "$callback" ]] ; then
 | 
						|
			log_note "Performing test-fail callback ($callback)"
 | 
						|
			$callback
 | 
						|
		fi
 | 
						|
	done <<<"$TESTFAIL_CALLBACKS:"
 | 
						|
}
 | 
						|
 | 
						|
# Perform cleanup and exit
 | 
						|
#
 | 
						|
# $1 - stf exit code
 | 
						|
# $2-$n - message text
 | 
						|
 | 
						|
function _endlog
 | 
						|
{
 | 
						|
	typeset logfile="/tmp/log.$$"
 | 
						|
	_recursive_output $logfile
 | 
						|
 | 
						|
	typeset exitcode=$1
 | 
						|
	shift
 | 
						|
	(( ${#@} > 0 )) && _printline "$@"
 | 
						|
 | 
						|
	#
 | 
						|
	# If we're running in a subshell then just exit and let
 | 
						|
	# the parent handle the failures
 | 
						|
	#
 | 
						|
	if [[ -n "$_MAINPID" && $$ != "$_MAINPID" ]]; then
 | 
						|
		log_note "subshell exited: "$_MAINPID
 | 
						|
		exit $exitcode
 | 
						|
	fi
 | 
						|
 | 
						|
	if [[ $exitcode == $STF_FAIL ]] ; then
 | 
						|
		_execute_testfail_callbacks
 | 
						|
	fi
 | 
						|
 | 
						|
	typeset stack=("${_CLEANUP[@]}")
 | 
						|
	log_onexit ""
 | 
						|
	typeset i=${#stack[@]}
 | 
						|
	while (( i-- )); do
 | 
						|
		typeset cleanup="${stack[i]}"
 | 
						|
		log_note "Performing local cleanup via log_onexit ($cleanup)"
 | 
						|
		$cleanup
 | 
						|
	done
 | 
						|
 | 
						|
	exit $exitcode
 | 
						|
}
 | 
						|
 | 
						|
# Output a formatted line
 | 
						|
#
 | 
						|
# $@ - message text
 | 
						|
 | 
						|
function _printline
 | 
						|
{
 | 
						|
	echo "$@"
 | 
						|
}
 | 
						|
 | 
						|
# Output an error message
 | 
						|
#
 | 
						|
# $@ - message text
 | 
						|
 | 
						|
function _printerror
 | 
						|
{
 | 
						|
	_printline ERROR: "$@"
 | 
						|
}
 | 
						|
 | 
						|
# Output a success message
 | 
						|
#
 | 
						|
# $@ - message text
 | 
						|
 | 
						|
function _printsuccess
 | 
						|
{
 | 
						|
	_printline SUCCESS: "$@"
 | 
						|
}
 | 
						|
 | 
						|
# Output logfiles recursively
 | 
						|
#
 | 
						|
# $1 - start file
 | 
						|
# $2 - indicate whether output the start file itself, default as yes.
 | 
						|
 | 
						|
function _recursive_output #logfile
 | 
						|
{
 | 
						|
	typeset logfile=$1
 | 
						|
 | 
						|
	while [[ -e $logfile ]]; do
 | 
						|
		if [[ -z $2 || $logfile != $1 ]]; then
 | 
						|
			cat $logfile
 | 
						|
		fi
 | 
						|
		rm -f $logfile
 | 
						|
		logfile="$logfile.$$"
 | 
						|
	done
 | 
						|
}
 |