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