1# Simple test harness infrastructure 2# 3# Copyright 2005 by Rob Landley 4 5# This file defines two main functions, "testcmd" and "optional". The 6# first performs a test, the second enables/disables tests based on 7# configuration options. 8 9# The following environment variables enable optional behavior in "testing": 10# DEBUG - Show every command run by test script. 11# VERBOSE - Print the diff -u of each failed test case. 12# If equal to "fail", stop after first failed test. 13# 14# The "testcmd" function takes five arguments: 15# $1) Description to display when running command 16# $2) Command line arguments to command 17# $3) Expected result (on stdout) 18# $4) Data written to file "input" 19# $5) Data written to stdin 20# 21# The "testing" function is like testcmd but takes a complete command line 22# (I.E. you have to include the command name.) The variable $C is an absolute 23# path to the command being tested, which can bypass shell builtins. 24# 25# The exit value of testcmd is the exit value of the command it ran. 26# 27# The environment variable "FAILCOUNT" contains a cumulative total of the 28# number of failed tests. 29# 30# The "optional" function is used to skip certain tests (by setting the 31# environment variable SKIP), ala: 32# optional CFG_THINGY 33# 34# The "optional" function checks the environment variable "OPTIONFLAGS", 35# which is either empty (in which case it always clears SKIP) or 36# else contains a colon-separated list of features (in which case the function 37# clears SKIP if the flag was found, or sets it to 1 if the flag was not found). 38 39export FAILCOUNT=0 40export SKIP= 41 42# Helper functions 43 44# Check config to see if option is enabled, set SKIP if not. 45 46SHOWPASS=PASS 47SHOWFAIL=FAIL 48SHOWSKIP=SKIP 49 50if tty -s <&1 51then 52 SHOWPASS="$(echo -e "\033[1;32m${SHOWPASS}\033[0m")" 53 SHOWFAIL="$(echo -e "\033[1;31m${SHOWFAIL}\033[0m")" 54 SHOWSKIP="$(echo -e "\033[1;33m${SHOWSKIP}\033[0m")" 55fi 56 57optional() 58{ 59 option=`echo "$OPTIONFLAGS" | egrep "(^|:)$1(:|\$)"` 60 # Not set? 61 if [ -z "$1" ] || [ -z "$OPTIONFLAGS" ] || [ ${#option} -ne 0 ] 62 then 63 SKIP="" 64 return 65 fi 66 SKIP=1 67} 68 69wrong_args() 70{ 71 if [ $# -ne 5 ] 72 then 73 echo "Test $NAME has the wrong number of arguments ($# $*)" >&2 74 exit 75 fi 76} 77 78# The testing function 79 80testing() 81{ 82 wrong_args "$@" 83 84 NAME="$CMDNAME $1" 85 [ -z "$1" ] && NAME=$2 86 87 [ -n "$DEBUG" ] && set -x 88 89 if [ -n "$SKIP" ] || ( [ -n "$SKIP_HOST" ] && [ -n "$TEST_HOST" ]) 90 then 91 [ ! -z "$VERBOSE" ] && echo "$SHOWSKIP: $NAME" 92 return 0 93 fi 94 95 echo -ne "$3" > expected 96 echo -ne "$4" > input 97 echo -ne "$5" | ${EVAL:-eval} "$2" > actual 98 RETVAL=$? 99 100 # Catch segfaults 101 [ $RETVAL -gt 128 ] && [ $RETVAL -lt 255 ] && 102 echo "exited with signal (or returned $RETVAL)" >> actual 103 104 DIFF="$(diff -au${NOSPACE:+b} expected actual)" 105 if [ ! -z "$DIFF" ] 106 then 107 FAILCOUNT=$[$FAILCOUNT+1] 108 echo "$SHOWFAIL: $NAME" 109 if [ -n "$VERBOSE" ] 110 then 111 [ ! -z "$4" ] && echo "echo -ne \"$4\" > input" 112 echo "echo -ne '$5' |$EVAL $2" 113 echo "$DIFF" 114 [ "$VERBOSE" == fail ] && exit 1 115 fi 116 else 117 echo "$SHOWPASS: $NAME" 118 fi 119 rm -f input expected actual 120 121 [ -n "$DEBUG" ] && set +x 122 123 return 0 124} 125 126testcmd() 127{ 128 wrong_args "$@" 129 130 testing "$1" "$C $2" "$3" "$4" "$5" 131} 132 133# Recursively grab an executable and all the libraries needed to run it. 134# Source paths beginning with / will be copied into destpath, otherwise 135# the file is assumed to already be there and only its library dependencies 136# are copied. 137 138mkchroot() 139{ 140 [ $# -lt 2 ] && return 141 142 echo -n . 143 144 dest=$1 145 shift 146 for i in "$@" 147 do 148 [ "${i:0:1}" == "/" ] || i=$(which $i) 149 [ -f "$dest/$i" ] && continue 150 if [ -e "$i" ] 151 then 152 d=`echo "$i" | grep -o '.*/'` && 153 mkdir -p "$dest/$d" && 154 cat "$i" > "$dest/$i" && 155 chmod +x "$dest/$i" 156 else 157 echo "Not found: $i" 158 fi 159 mkchroot "$dest" $(ldd "$i" | egrep -o '/.* ') 160 done 161} 162 163# Set up a chroot environment and run commands within it. 164# Needed commands listed on command line 165# Script fed to stdin. 166 167dochroot() 168{ 169 mkdir tmpdir4chroot 170 mount -t ramfs tmpdir4chroot tmpdir4chroot 171 mkdir -p tmpdir4chroot/{etc,sys,proc,tmp,dev} 172 cp -L testing.sh tmpdir4chroot 173 174 # Copy utilities from command line arguments 175 176 echo -n "Setup chroot" 177 mkchroot tmpdir4chroot $* 178 echo 179 180 mknod tmpdir4chroot/dev/tty c 5 0 181 mknod tmpdir4chroot/dev/null c 1 3 182 mknod tmpdir4chroot/dev/zero c 1 5 183 184 # Copy script from stdin 185 186 cat > tmpdir4chroot/test.sh 187 chmod +x tmpdir4chroot/test.sh 188 chroot tmpdir4chroot /test.sh 189 umount -l tmpdir4chroot 190 rmdir tmpdir4chroot 191} 192 193