3 # This file and its contents are supplied under the terms of the
4 # Common Development and Distribution License ("CDDL"), version 1.0.
5 # You may only use this file in accordance with the terms of version
8 # A full copy of the text of the CDDL should have accompanied this
9 # source. A copy of the CDDL is also available via the Internet at
10 # http://www.illumos.org/license/CDDL.
14 # Copyright (c) 2016, 2017 by Delphix. All rights reserved.
17 . $STF_SUITE/include/libtest.shlib
19 ZCP_ROOT=$STF_SUITE/tests/functional/channel_program
22 # Note: In case of failure (log_fail) in this function
23 # we delete the file passed as <input file> so the
24 # test suite doesn't leak temp files on failures. So it
25 # is expected that <input file> is a temp file and not
28 # <exitcode> <expected error string> <input file> <zfs program args>
29 # e.g. log_program 0 "" tmp.7a12V $POOL foo.zcp arg1 arg2
34 typeset expecterror=$1
38 typeset cmdargs=$@ tmpout=$(mktemp) tmperr=$(mktemp)
40 # Expected output/error filename is the same as the .zcp name
42 if [[ $2 != "-" ]]; then
46 log_note "running: zfs program $cmdargs:"
48 zfs program $cmdargs >$tmpout 2>$tmperr
51 log_note "input:\n$(cat $tmpin)"
52 log_note "output:\n$(cat $tmpout)"
53 log_note "error:\n$(cat $tmperr)"
56 # Verify correct return value
58 if [[ $ret -ne $expectexit ]]; then
59 rm $tmpout $tmperr $tmpin
60 log_fail "return mismatch: expected $expectexit, got $ret"
64 # Check the output or reported error for successful or error returns,
67 if [[ -f "$basename.out" ]] && [[ $expectexit -eq 0 ]]; then
69 outdiff=$(diff "$basename.out" "$tmpout")
70 if [[ $? -ne 0 ]]; then
72 rm $tmpout $tmperr $tmpin
73 log_fail "Output mismatch. Expected:\n" \
74 "$(cat $basename.out)\nBut got:\n$output\n" \
78 elif [[ -f "$basename.err" ]] && [[ $expectexit -ne 0 ]]; then
80 outdiff=$(diff "$basename.err" "$tmperr")
81 if [[ $? -ne 0 ]]; then
82 outputerror=$(cat $tmperr)
83 rm $tmpout $tmperr $tmpin
84 log_fail "Error mismatch. Expected:\n" \
85 "$(cat $basename.err)\nBut got:\n$outputerror\n" \
89 elif [[ -n $expecterror ]] && [[ $expectexit -ne 0 ]]; then
91 grep -q "$expecterror" $tmperr
92 if [[ $? -ne 0 ]]; then
93 outputerror=$(cat $tmperr)
94 rm $tmpout $tmperr $tmpin
95 log_fail "Error mismatch. Expected to contain:\n" \
96 "$expecterror\nBut got:\n$outputerror\n"
99 elif [[ $expectexit -ne 0 ]]; then
101 # If there's no expected output, error reporting is allowed to
102 # vary, but ensure that we didn't fail silently.
104 if [[ -z "$(cat $tmperr)" ]]; then
105 rm $tmpout $tmperr $tmpin
106 log_fail "error with no stderr output"
111 # Clean up all temp files except $tmpin which is
112 # reused for the second invocation of log_program.
118 # Even though the command's arguments are passed correctly
119 # to the log_must_program family of wrappers the majority
120 # of the time, zcp scripts passed as HERE documents can
121 # make things trickier (see comment within the function
122 # below) in the ordering of the commands arguments and how
123 # they are passed. Thus, with this function we reconstruct
124 # them to ensure that they are passed properly.
126 function log_program_construct_args
133 while getopts "nt:m:" opt; do
135 t) args="$args -t $OPTARG"; i=$(($i + 2)) ;;
136 m) args="$args -m $OPTARG"; i=$(($i + 2)) ;;
137 n) args="$args -n"; i=$(($i + 1)) ;;
146 # Catch HERE document if it exists and save it within our
147 # temp file. The reason we do this is that since the
148 # log_must_program wrapper calls zfs-program twice (once
149 # for open context and once for syncing) the HERE doc
150 # is consumed in the first invocation and the second one
151 # does not have a program to run.
153 test -s /dev/stdin && cat > $tmpin
156 # If $tmpin has contents it means that we consumed a HERE
157 # doc and $1 currently holds "-" (a dash). If there is no
158 # HERE doc and $tmpin is empty, then we copy the contents
159 # of the original channel program to $tmpin.
161 [[ -s $tmpin ]] || cp $1 $tmpin
166 echo "$args $pool $tmpin $lua_args"
170 # Program should complete successfully
171 # when run in either context.
173 function log_must_program
175 typeset tmpin=$(mktemp)
177 program_args=$(log_program_construct_args $tmpin $@)
179 log_program 0 "" $tmpin "-n $program_args"
180 log_program 0 "" $tmpin "$program_args"
185 # Program should error as expected in
186 # the same way in both contexts.
188 function log_mustnot_checkerror_program
190 typeset expecterror=$1
192 typeset tmpin=$(mktemp)
194 program_args=$(log_program_construct_args $tmpin $@)
196 log_program 1 "$expecterror" $tmpin "-n $program_args"
197 log_program 1 "$expecterror" $tmpin "$program_args"
203 # Program should fail when run in either
206 function log_mustnot_program
208 log_mustnot_checkerror_program "" $@
213 # Program should error as expected in
214 # open context but complete successfully
215 # in syncing context.
217 function log_mustnot_checkerror_program_open
219 typeset expecterror=$1
221 typeset tmpin=$(mktemp)
223 program_args=$(log_program_construct_args $tmpin $@)
225 log_program 1 "$expecterror" $tmpin "-n $program_args"
226 log_program 0 "" $tmpin "$program_args"
232 # Program should complete successfully
233 # when run in syncing context but fail
234 # when attempted to run in open context.
236 function log_must_program_sync
238 log_mustnot_checkerror_program_open "requires passing sync=TRUE" $@