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