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 69skipnot() 70{ 71 if [ -z "$VERBOSE" ] 72 then 73 eval "$@" 2>/dev/null 74 else 75 eval "$@" 76 fi 77 [ $? -eq 0 ] || SKIPNOT=1 78} 79 80wrong_args() 81{ 82 if [ $# -ne 5 ] 83 then 84 echo "Test $NAME has the wrong number of arguments ($# $*)" >&2 85 exit 86 fi 87} 88 89# The testing function 90 91testing() 92{ 93 NAME="$CMDNAME $1" 94 wrong_args "$@" 95 96 [ -z "$1" ] && NAME=$2 97 98 [ -n "$DEBUG" ] && set -x 99 100 if [ -n "$SKIP" -o -n "$SKIP_HOST" -a -n "$TEST_HOST" -o -n "$SKIPNOT" ] 101 then 102 [ ! -z "$VERBOSE" ] && echo "$SHOWSKIP: $NAME" 103 unset SKIPNOT 104 return 0 105 fi 106 107 echo -ne "$3" > expected 108 echo -ne "$4" > input 109 echo -ne "$5" | ${EVAL:-eval} -- "$2" > actual 110 RETVAL=$? 111 112 # Catch segfaults 113 [ $RETVAL -gt 128 ] && [ $RETVAL -lt 255 ] && 114 echo "exited with signal (or returned $RETVAL)" >> actual 115 116 DIFF="$(diff -au${NOSPACE:+b} expected actual)" 117 if [ ! -z "$DIFF" ] 118 then 119 FAILCOUNT=$[$FAILCOUNT+1] 120 echo "$SHOWFAIL: $NAME" 121 if [ -n "$VERBOSE" ] 122 then 123 [ ! -z "$4" ] && echo "echo -ne \"$4\" > input" 124 echo "echo -ne '$5' |$EVAL $2" 125 echo "$DIFF" 126 [ "$VERBOSE" == fail ] && exit 1 127 fi 128 else 129 echo "$SHOWPASS: $NAME" 130 fi 131 rm -f input expected actual 132 133 [ -n "$DEBUG" ] && set +x 134 135 return 0 136} 137 138testcmd() 139{ 140 wrong_args "$@" 141 142 X="$1" 143 [ -z "$X" ] && X="$CMDNAME $2" 144 testing "$X" "$C $2" "$3" "$4" "$5" 145} 146 147# Recursively grab an executable and all the libraries needed to run it. 148# Source paths beginning with / will be copied into destpath, otherwise 149# the file is assumed to already be there and only its library dependencies 150# are copied. 151 152mkchroot() 153{ 154 [ $# -lt 2 ] && return 155 156 echo -n . 157 158 dest=$1 159 shift 160 for i in "$@" 161 do 162 [ "${i:0:1}" == "/" ] || i=$(which $i) 163 [ -f "$dest/$i" ] && continue 164 if [ -e "$i" ] 165 then 166 d=`echo "$i" | grep -o '.*/'` && 167 mkdir -p "$dest/$d" && 168 cat "$i" > "$dest/$i" && 169 chmod +x "$dest/$i" 170 else 171 echo "Not found: $i" 172 fi 173 mkchroot "$dest" $(ldd "$i" | egrep -o '/.* ') 174 done 175} 176 177# Set up a chroot environment and run commands within it. 178# Needed commands listed on command line 179# Script fed to stdin. 180 181dochroot() 182{ 183 mkdir tmpdir4chroot 184 mount -t ramfs tmpdir4chroot tmpdir4chroot 185 mkdir -p tmpdir4chroot/{etc,sys,proc,tmp,dev} 186 cp -L testing.sh tmpdir4chroot 187 188 # Copy utilities from command line arguments 189 190 echo -n "Setup chroot" 191 mkchroot tmpdir4chroot $* 192 echo 193 194 mknod tmpdir4chroot/dev/tty c 5 0 195 mknod tmpdir4chroot/dev/null c 1 3 196 mknod tmpdir4chroot/dev/zero c 1 5 197 198 # Copy script from stdin 199 200 cat > tmpdir4chroot/test.sh 201 chmod +x tmpdir4chroot/test.sh 202 chroot tmpdir4chroot /test.sh 203 umount -l tmpdir4chroot 204 rmdir tmpdir4chroot 205} 206