1# 2# This file and its contents are supplied under the terms of the 3# Common Development and Distribution License ("CDDL"), version 1.0. 4# You may only use this file in accordance with the terms of version 5# 1.0 of the CDDL. 6# 7# A full copy of the text of the CDDL should have accompanied this 8# source. A copy of the CDDL is also available via the Internet at 9# http://www.illumos.org/license/CDDL. 10# 11 12# 13# Copyright (c) 2016, 2017 by Delphix. All rights reserved. 14# 15 16. $STF_SUITE/include/libtest.shlib 17 18ZCP_ROOT=$STF_SUITE/tests/functional/channel_program 19 20# 21# Note: In case of failure (log_fail) in this function 22# we delete the file passed as <input file> so the 23# test suite doesn't leak temp files on failures. So it 24# is expected that <input file> is a temp file and not 25# an installed file. 26# 27# <exitcode> <expected error string> <input file> <zfs program args> 28# e.g. log_program 0 "" tmp.7a12V $POOL foo.zcp arg1 arg2 29function log_program 30{ 31 typeset expectexit=$1 32 shift 33 typeset expecterror=$1 34 shift 35 typeset tmpin=$1 36 shift 37 typeset cmdargs=$@ tmpout=$(mktemp) tmperr=$(mktemp) 38 39 # Expected output/error filename is the same as the .zcp name 40 typeset basename 41 if [[ $2 != "-" ]]; then 42 basename=${2%.*} 43 fi 44 45 log_note "running: zfs program $cmdargs:" 46 47 zfs program $cmdargs >$tmpout 2>$tmperr 48 typeset ret=$? 49 50 log_note "input:\n$(cat $tmpin)" 51 log_note "output:\n$(cat $tmpout)" 52 log_note "error:\n$(cat $tmperr)" 53 54 # 55 # Verify correct return value 56 # 57 if [[ $ret -ne $expectexit ]]; then 58 rm $tmpout $tmperr $tmpin 59 log_fail "return mismatch: expected $expectexit, got $ret" 60 fi 61 62 # 63 # Check the output or reported error for successful or error returns, 64 # respectively. 65 # 66 if [[ -f "$basename.out" ]] && [[ $expectexit -eq 0 ]]; then 67 68 outdiff=$(diff "$basename.out" "$tmpout") 69 if [[ $? -ne 0 ]]; then 70 output=$(<$tmpout) 71 rm $tmpout $tmperr $tmpin 72 log_fail "Output mismatch. Expected:\n" \ 73 "$(<$basename.out)\nBut got:\n$output\n" \ 74 "Diff:\n$outdiff" 75 fi 76 77 elif [[ -f "$basename.err" ]] && [[ $expectexit -ne 0 ]]; then 78 79 outdiff=$(diff "$basename.err" "$tmperr") 80 if [[ $? -ne 0 ]]; then 81 outputerror=$(<$tmperr) 82 rm $tmpout $tmperr $tmpin 83 log_fail "Error mismatch. Expected:\n" \ 84 "$(<$basename.err)\nBut got:\n$outputerror\n" \ 85 "Diff:\n$outdiff" 86 fi 87 88 elif [[ -n $expecterror ]] && [[ $expectexit -ne 0 ]]; then 89 90 grep -q "$expecterror" $tmperr 91 if [[ $? -ne 0 ]]; then 92 outputerror=$(<$tmperr) 93 rm $tmpout $tmperr $tmpin 94 log_fail "Error mismatch. Expected to contain:\n" \ 95 "$expecterror\nBut got:\n$outputerror\n" 96 fi 97 98 elif [[ $expectexit -ne 0 ]]; then 99 # 100 # If there's no expected output, error reporting is allowed to 101 # vary, but ensure that we didn't fail silently. 102 # 103 if [[ -z "$(<$tmperr)" ]]; then 104 rm $tmpout $tmperr $tmpin 105 log_fail "error with no stderr output" 106 fi 107 fi 108 109 # 110 # Clean up all temp files except $tmpin which is 111 # reused for the second invocation of log_program. 112 # 113 rm $tmpout $tmperr 114} 115 116# 117# Even though the command's arguments are passed correctly 118# to the log_must_program family of wrappers the majority 119# of the time, zcp scripts passed as HERE documents can 120# make things trickier (see comment within the function 121# below) in the ordering of the commands arguments and how 122# they are passed. Thus, with this function we reconstruct 123# them to ensure that they are passed properly. 124# 125function log_program_construct_args 126{ 127 typeset tmpin=$1 128 shift 129 130 args="" 131 i=0 132 while getopts "nt:m:" opt; do 133 case $opt in 134 t) args="$args -t $OPTARG"; i=$(($i + 2)) ;; 135 m) args="$args -m $OPTARG"; i=$(($i + 2)) ;; 136 n) args="$args -n"; i=$(($i + 1)) ;; 137 esac 138 done 139 shift $i 140 141 pool=$1 142 shift 143 144 infile=$1 145 shift 146 147 # 148 # Copy the contents of the original channel program to $tmpin. 149 # 150 # If $infile currently holds "-" (a dash) it means that we consume a 151 # HERE doc from stdin, otherwise $infile is a file path. 152 # 153 cat $infile > $tmpin 154 155 lua_args=$@ 156 157 echo "$args $pool $tmpin $lua_args" 158} 159 160# 161# Program should complete successfully 162# when run in either context. 163# 164function log_must_program 165{ 166 typeset tmpin=$(mktemp) 167 168 program_args=$(log_program_construct_args $tmpin $@) 169 170 log_program 0 "" $tmpin "-n $program_args" 171 log_program 0 "" $tmpin "$program_args" 172 173 rm $tmpin 174} 175# 176# Program should error as expected in 177# the same way in both contexts. 178# 179function log_mustnot_checkerror_program 180{ 181 typeset expecterror=$1 182 shift 183 typeset tmpin=$(mktemp) 184 185 program_args=$(log_program_construct_args $tmpin $@) 186 187 log_program 1 "$expecterror" $tmpin "-n $program_args" 188 log_program 1 "$expecterror" $tmpin "$program_args" 189 190 rm $tmpin 191} 192 193# 194# Program should fail when run in either 195# context. 196# 197function log_mustnot_program 198{ 199 log_mustnot_checkerror_program "" $@ 200} 201 202 203# 204# Program should error as expected in 205# open context but complete successfully 206# in syncing context. 207# 208function log_mustnot_checkerror_program_open 209{ 210 typeset expecterror=$1 211 shift 212 typeset tmpin=$(mktemp) 213 214 program_args=$(log_program_construct_args $tmpin $@) 215 216 log_program 1 "$expecterror" $tmpin "-n $program_args" 217 log_program 0 "" $tmpin "$program_args" 218 219 rm $tmpin 220} 221 222# 223# Program should complete successfully 224# when run in syncing context but fail 225# when attempted to run in open context. 226# 227function log_must_program_sync 228{ 229 log_mustnot_checkerror_program_open "requires passing sync=TRUE" $@ 230} 231