diff options
Diffstat (limited to 'tests/zfs-tests/tests/functional/channel_program/channel_common.kshlib')
-rw-r--r-- | tests/zfs-tests/tests/functional/channel_program/channel_common.kshlib | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/tests/zfs-tests/tests/functional/channel_program/channel_common.kshlib b/tests/zfs-tests/tests/functional/channel_program/channel_common.kshlib new file mode 100644 index 000000000000..a828ba29065e --- /dev/null +++ b/tests/zfs-tests/tests/functional/channel_program/channel_common.kshlib @@ -0,0 +1,230 @@ +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2016, 2017 by Delphix. All rights reserved. +# + +. $STF_SUITE/include/libtest.shlib + +ZCP_ROOT=$STF_SUITE/tests/functional/channel_program + +# +# Note: In case of failure (log_fail) in this function +# we delete the file passed as <input file> so the +# test suite doesn't leak temp files on failures. So it +# is expected that <input file> is a temp file and not +# an installed file. +# +# <exitcode> <expected error string> <input file> <zfs program args> +# e.g. log_program 0 "" tmp.7a12V $POOL foo.zcp arg1 arg2 +function log_program +{ + typeset expectexit=$1 + shift + typeset expecterror=$1 + shift + typeset tmpin=$1 + shift + typeset cmdargs=$@ tmpout=$(mktemp) tmperr=$(mktemp) + + # Expected output/error filename is the same as the .zcp name + typeset basename + if [[ $2 != "-" ]]; then + basename=${2%.*} + fi + + log_note "running: zfs program $cmdargs:" + + zfs program $cmdargs >$tmpout 2>$tmperr + typeset ret=$? + + log_note "input:\n$(cat $tmpin)" + log_note "output:\n$(cat $tmpout)" + log_note "error:\n$(cat $tmperr)" + + # + # Verify correct return value + # + if [[ $ret -ne $expectexit ]]; then + rm $tmpout $tmperr $tmpin + log_fail "return mismatch: expected $expectexit, got $ret" + fi + + # + # Check the output or reported error for successful or error returns, + # respectively. + # + if [[ -f "$basename.out" ]] && [[ $expectexit -eq 0 ]]; then + + outdiff=$(diff "$basename.out" "$tmpout") + if [[ $? -ne 0 ]]; then + output=$(<$tmpout) + rm $tmpout $tmperr $tmpin + log_fail "Output mismatch. Expected:\n" \ + "$(<$basename.out)\nBut got:\n$output\n" \ + "Diff:\n$outdiff" + fi + + elif [[ -f "$basename.err" ]] && [[ $expectexit -ne 0 ]]; then + + outdiff=$(diff "$basename.err" "$tmperr") + if [[ $? -ne 0 ]]; then + outputerror=$(<$tmperr) + rm $tmpout $tmperr $tmpin + log_fail "Error mismatch. Expected:\n" \ + "$(<$basename.err)\nBut got:\n$outputerror\n" \ + "Diff:\n$outdiff" + fi + + elif [[ -n $expecterror ]] && [[ $expectexit -ne 0 ]]; then + + grep -q "$expecterror" $tmperr + if [[ $? -ne 0 ]]; then + outputerror=$(<$tmperr) + rm $tmpout $tmperr $tmpin + log_fail "Error mismatch. Expected to contain:\n" \ + "$expecterror\nBut got:\n$outputerror\n" + fi + + elif [[ $expectexit -ne 0 ]]; then + # + # If there's no expected output, error reporting is allowed to + # vary, but ensure that we didn't fail silently. + # + if [[ -z "$(<$tmperr)" ]]; then + rm $tmpout $tmperr $tmpin + log_fail "error with no stderr output" + fi + fi + + # + # Clean up all temp files except $tmpin which is + # reused for the second invocation of log_program. + # + rm $tmpout $tmperr +} + +# +# Even though the command's arguments are passed correctly +# to the log_must_program family of wrappers the majority +# of the time, zcp scripts passed as HERE documents can +# make things trickier (see comment within the function +# below) in the ordering of the commands arguments and how +# they are passed. Thus, with this function we reconstruct +# them to ensure that they are passed properly. +# +function log_program_construct_args +{ + typeset tmpin=$1 + shift + + args="" + i=0 + while getopts "nt:m:" opt; do + case $opt in + t) args="$args -t $OPTARG"; i=$(($i + 2)) ;; + m) args="$args -m $OPTARG"; i=$(($i + 2)) ;; + n) args="$args -n"; i=$(($i + 1)) ;; + esac + done + shift $i + + pool=$1 + shift + + infile=$1 + shift + + # + # Copy the contents of the original channel program to $tmpin. + # + # If $infile currently holds "-" (a dash) it means that we consume a + # HERE doc from stdin, otherwise $infile is a file path. + # + cat $infile > $tmpin + + lua_args=$@ + + echo "$args $pool $tmpin $lua_args" +} + +# +# Program should complete successfully +# when run in either context. +# +function log_must_program +{ + typeset tmpin=$(mktemp) + + program_args=$(log_program_construct_args $tmpin $@) + + log_program 0 "" $tmpin "-n $program_args" + log_program 0 "" $tmpin "$program_args" + + rm $tmpin +} +# +# Program should error as expected in +# the same way in both contexts. +# +function log_mustnot_checkerror_program +{ + typeset expecterror=$1 + shift + typeset tmpin=$(mktemp) + + program_args=$(log_program_construct_args $tmpin $@) + + log_program 1 "$expecterror" $tmpin "-n $program_args" + log_program 1 "$expecterror" $tmpin "$program_args" + + rm $tmpin +} + +# +# Program should fail when run in either +# context. +# +function log_mustnot_program +{ + log_mustnot_checkerror_program "" $@ +} + + +# +# Program should error as expected in +# open context but complete successfully +# in syncing context. +# +function log_mustnot_checkerror_program_open +{ + typeset expecterror=$1 + shift + typeset tmpin=$(mktemp) + + program_args=$(log_program_construct_args $tmpin $@) + + log_program 1 "$expecterror" $tmpin "-n $program_args" + log_program 0 "" $tmpin "$program_args" + + rm $tmpin +} + +# +# Program should complete successfully +# when run in syncing context but fail +# when attempted to run in open context. +# +function log_must_program_sync +{ + log_mustnot_checkerror_program_open "requires passing sync=TRUE" $@ +} |