aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Behlendorf <[email protected]>2016-06-20 14:28:51 -0700
committerBrian Behlendorf <[email protected]>2016-08-30 15:26:14 -0700
commite623aea2ec11b4e3da8ddec50634be6e0be14eaf (patch)
tree3f59aa864827437237ed808a653436c8424bc2d5
parent2158b165ed02178a58540b55eca828d32977147c (diff)
Add log_must_{retry,busy} helpers
Add helpers which automatically retry the provided command when the error message matches the provided keyword. This provides an easy way to handle the asynchronous nature of some ZFS commands. For example, the `zfs destroy` command may need to be retried in the case where the block device is unexpected busy. This can be accomplished as follows: log_must_busy $ZFS destroy ... Signed-off-by: Brian Behlendorf <[email protected]> Issue #5002
-rw-r--r--tests/test-runner/include/logapi.shlib75
1 files changed, 75 insertions, 0 deletions
diff --git a/tests/test-runner/include/logapi.shlib b/tests/test-runner/include/logapi.shlib
index 6fd4ab369..b970e4ecc 100644
--- a/tests/test-runner/include/logapi.shlib
+++ b/tests/test-runner/include/logapi.shlib
@@ -69,6 +69,81 @@ function log_must
(( $? != 0 )) && 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 out=""
+ 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=$?
+ out="$CAT $logfile"
+
+ if (( $status == 0 )); then
+ $out | $EGREP -i "internal error|assertion failed" \
+ > /dev/null 2>&1
+ # internal error or assertion failed
+ if [[ $? -eq 0 ]]; then
+ print -u2 $($out)
+ _printerror "$@" "internal error or" \
+ " assertion failure exited $status"
+ status=1
+ else
+ [[ -n $LOGAPI_DEBUG ]] && print $($out)
+ _printsuccess "$@"
+ fi
+ break
+ else
+ $out | $GREP -i "$expect" > /dev/null 2>&1
+ if (( $? == 0 )); then
+ print -u2 $($out)
+ _printerror "$@" "Retry in $delay seconds"
+ $SLEEP $delay
+
+ (( retry=retry - 1 ))
+ (( delay=delay * 2 ))
+ else
+ break;
+ fi
+ fi
+ done
+
+ if (( $status != 0 )) ; then
+ print -u2 $($out)
+ _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 "$@"
+ (( $? != 0 )) && log_fail
+}
+
# Execute a negative test and exit $STF_FAIL if test passes
#
# $@ - command to execute