Files
apfstests/check
T
Dave Chinner 3345d2150e xfstests: clean up and simply check CLI option parsing
The options are parsed in a messy loop of option parsing and 
actions on secondary arguments. Turn it into something much neater
and easy to understand rather than a mess of temporary variables
and tortured logic...

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Phil White <pwhite@sgi.com>
[rjohnston@sgi.com fixed typos in commit message]
Signed-off-by: Rich Johnston <rjohnston@sgi.com>
2013-03-26 10:40:20 -05:00

529 lines
11 KiB
Bash
Executable File

#!/bin/bash
#
# Control script for QA
#
# Copyright (c) 2000-2002,2006 Silicon Graphics, Inc. All Rights Reserved.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it would be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
#
tmp=/tmp/$$
status=0
needwrap=true
n_try=0
try=""
n_bad=0
bad=""
notrun=""
interrupt=true
diff="diff -u"
showme=false
expunge=true
have_test_arg=false
randomize=false
here=`pwd`
FSTYP=xfs
SUPPORTED_TESTS="[0-9][0-9][0-9] [0-9][0-9][0-9][0-9]"
# generic initialization
iam=check
export QA_CHECK_FS=${QA_CHECK_FS:=true}
# by default don't output timestamps
timestamp=${TIMESTAMP:=false}
# number of diff lines from a failed test, 0 for whole output
export DIFF_LENGTH=${DIFF_LENGTH:=10}
# by default don't output timestamps
timestamp=${TIMESTAMP:=false}
usage()
{
echo "Usage: $0 [options] [testlist]"'
check options
-xfs test XFS (default)
-udf test UDF
-nfs test NFS
-l line mode diff
-udiff show unified diff (default)
-n show me, do not run tests
-T output timestamps
-r randomize test order
--large-fs optimise scratch device for large filesystems
testlist options
-g group[,group...] include tests from these groups
-x group[,group...] exclude tests from these groups
NNN include test NNN
NNN-NNN include test range (eg. 012-021)
'
exit 0
}
_setenvironment()
{
MSGVERB="text:action"
export MSGVERB
}
get_group_list()
{
grp=$1
grpl=$(sed -n < group \
-e 's/#.*//' \
-e 's/$/ /' \
-e "/^[0-9][0-9][0-9].* $grp /"'{ s/ .*//p }')
echo $grpl
}
expand_test_numbers()
{
# strip leading zeros, could be considered octal.
start=`echo $1 | sed 's/^0*//'`
end=`echo $2 | sed 's/^0*//'`
$AWK_PROG </dev/null '
BEGIN { for (t='$start'; t<='$end'; t++) printf "%03d\n",t }' \
| while read id
do
if grep -s "^$id " group >/dev/null ; then
# in group file ... OK
echo $id >>$tmp.list
elif [ -f expunged ] && $expunge && \
egrep "^$id([ ]|\$)" expunged >/dev/null ; then
# expunged ... will be reported, but not run, later
echo $id >>$tmp.list
else
# oops
echo "$id - unknown test, ignored"
fi
done
}
_wallclock()
{
date "+%H %M %S" | $AWK_PROG '{ print $1*3600 + $2*60 + $3 }'
}
_timestamp()
{
now=`date "+%T"`
echo -n " [$now]"
}
# start the initialisation work now
_setenvironment
rm -f $tmp.list $tmp.tmp $tmp.sed $here/$iam.out
# Autodetect fs type based on what's on $TEST_DEV
if [ "$HOSTOS" == "Linux" ]; then
FSTYP=`blkid -c /dev/null -s TYPE -o value $TEST_DEV`
fi
export FSTYP
# we need common.config
if ! . ./common.config
then
echo "$iam: failed to source common.config"
exit 1
fi
while [ $# -gt 0 ]; do
case "$1" in
-\? | -h | --help) usage ;;
-udf) FSTYP=udf ;;
-xfs) FSTYP=xfs ;;
-nfs) FSTYP=nfs ;;
-g) group=$2 ; shift ;
group_list=$(get_group_list $group)
if [ -z "$group_list" ]; then
echo "Group \"$group\" is empty or not defined?"
exit 1
fi
[ ! -s $tmp.list ] && touch $tmp.list
for t in $group_list; do
grep -s "^$t\$" $tmp.list >/dev/null || \
echo "$t" >>$tmp.list
done
;;
-x) xgroup=$2 ; shift ;
[ ! -s $tmp.list ] && ls $SUPPORTED_TESTS >$tmp.list 2>/dev/null
group_list=$(get_group_list $xgroup)
if [ -z "$group_list" ]; then
echo "Group \"$xgroup\" is empty or not defined?"
exit 1
fi
rm -f $tmp.sed
numsed=0
for t in $group_list
do
if [ $numsed -gt 100 ]; then
sed -f $tmp.sed <$tmp.list >$tmp.tmp
mv $tmp.tmp $tmp.list
numsed=0
rm -f $tmp.sed
fi
echo "/^$t\$/d" >>$tmp.sed
numsed=`expr $numsed + 1`
done
sed -f $tmp.sed <$tmp.list >$tmp.tmp
mv $tmp.tmp $tmp.list
;;
-l) diff="diff" ;;
-udiff) diff="$diff -u" ;;
-n) showme=true ;;
-r) randomize=true ;;
-T) timestamp=true ;;
"$SUPPORTED_TESTS")
echo "No tests?"
status=1
exit $status
;;
[0-9]*-[0-9]*)
eval `echo $1 | sed -e 's/^/start=/' -e 's/-/ end=/'`
expand_test_numbers $start $end
have_test_arg=true
;;
[0-9]*-)
eval `echo $1 | sed -e 's/^/start=/' -e 's/-//'`
end=`echo $SUPPORTED_TESTS | sed -e 's/\[0-9]//g' -e 's/ *$//' -e 's/.* //'`
if [ -z "$end" ]; then
echo "No tests in range \"$1\"?"
status=1
exit $status
fi
expand_test_numbers $start $end
have_test_arg=true
;;
--large-fs) export LARGE_SCRATCH_DEV=yes ;;
--extra-space=*) export SCRATCH_DEV_EMPTY_SPACE=${r#*=} ;;
-*) usage ;;
*) expand_test_numbers $1 $1 ;
have_test_arg=true
;;
esac
shift
done
if [ -s $tmp.list ]; then
# found some valid test numbers ... this is good
:
elif $have_test_arg; then
# had test numbers, but none in group file ... do nothing
touch $tmp.list
else
# no test numbers, do everything from group file
sed -n -e '/^[0-9][0-9][0-9]*/s/[ ].*//p' <group >$tmp.list
fi
# sort the list of tests into numeric order
list=`sort -n $tmp.list`
rm -f $tmp.list $tmp.tmp $tmp.sed
if $randomize
then
list=`echo $list | awk -f randomize.awk`
fi
# we need common.rc
if ! . ./common.rc
then
echo "check: failed to source common.rc"
exit 1
fi
if [ `id -u` -ne 0 ]
then
echo "check: QA must be run as root"
exit 1
fi
# Ok, time to start running...
_wrapup()
{
# for hangcheck ...
# remove files that were used by hangcheck
#
[ -f /tmp/check.pid ] && rm -rf /tmp/check.pid
[ -f /tmp/check.sts ] && rm -rf /tmp/check.sts
if $showme
then
:
elif $needwrap
then
if [ -f check.time -a -f $tmp.time ]
then
cat check.time $tmp.time \
| $AWK_PROG '
{ t[$1] = $2 }
END { if (NR > 0) {
for (i in t) print i " " t[i]
}
}' \
| sort -n >$tmp.out
mv $tmp.out check.time
fi
if [ -f $tmp.expunged ]
then
notrun=`wc -l <$tmp.expunged | sed -e 's/ *//g'`
n_try=`expr $n_try - $notrun`
list=`echo "$list" | sed -f $tmp.expunged`
fi
echo "" >>check.log
date >>check.log
echo $list | fmt | sed -e 's/^/ /' >>check.log
$interrupt && echo "Interrupted!" >>check.log
if [ ! -z "$n_try" -a $n_try != 0 ]
then
echo "Ran:$try"
fi
if [ ! -z "$notrun" ]
then
echo "Not run:$notrun"
echo "Not run:$notrun" >>check.log
fi
if [ ! -z "$n_bad" -a $n_bad != 0 ]
then
echo "Failures:$bad"
echo "Failed $n_bad of $n_try tests"
echo "Failures:$bad" | fmt >>check.log
echo "Failed $n_bad of $n_try tests" >>check.log
else
echo "Passed all $n_try tests"
echo "Passed all $n_try tests" >>check.log
fi
needwrap=false
fi
rm -f /tmp/*.rawout /tmp/*.out /tmp/*.err /tmp/*.time
rm -f /tmp/check.pid /tmp/check.sts
rm -f $tmp.*
}
trap "_wrapup; exit \$status" 0 1 2 3 15
# for hangcheck ...
# Save pid of check in a well known place, so that hangcheck can be sure it
# has the right pid (getting the pid from ps output is not reliable enough).
#
rm -rf /tmp/check.pid
echo $$ >/tmp/check.pid
# for hangcheck ...
# Save the status of check in a well known place, so that hangcheck can be
# sure to know where check is up to (getting test number from ps output is
# not reliable enough since the trace stuff has been introduced).
#
rm -rf /tmp/check.sts
echo "preamble" >/tmp/check.sts
# don't leave old full output behind on a clean run
rm -f check.full
[ -f check.time ] || touch check.time
# print out our test configuration
echo "FSTYP -- `_full_fstyp_details`"
echo "PLATFORM -- `_full_platform_details`"
if [ ! -z "$SCRATCH_DEV" ]; then
echo "MKFS_OPTIONS -- `_scratch_mkfs_options`"
echo "MOUNT_OPTIONS -- `_scratch_mount_options`"
fi
echo
if [ ! -z "$SCRATCH_DEV" ]; then
umount $SCRATCH_DEV 2>/dev/null
# call the overridden mkfs - make sure the FS is built
# the same as we'll create it later.
if ! _scratch_mkfs $flag >$tmp.err 2>&1
then
echo "our local _scratch_mkfs routine ..."
cat $tmp.err
echo "check: failed to mkfs \$SCRATCH_DEV using specified options"
exit 1
fi
# call the overridden mount - make sure the FS mounts with
# the same options that we'll mount with later.
if ! _scratch_mount >$tmp.err 2>&1
then
echo "our local mount routine ..."
cat $tmp.err
echo "check: failed to mount \$SCRATCH_DEV using specified options"
exit 1
fi
fi
seq="check"
_check_test_fs
[ -n "$TESTS_REMAINING_LOG" ] && echo $list > $TESTS_REMAINING_LOG
for seq in $list
do
err=false
echo -n "$seq"
if [ -n "$TESTS_REMAINING_LOG" ] ; then
sed -e "s/$seq//" -e 's/ / /' -e 's/^ *//' $TESTS_REMAINING_LOG > $TESTS_REMAINING_LOG.tmp
mv $TESTS_REMAINING_LOG.tmp $TESTS_REMAINING_LOG
sync
fi
if $showme
then
echo
continue
elif [ -f expunged ] && $expunge && egrep "^$seq([ ]|\$)" expunged >/dev/null
then
echo " - expunged"
rm -f $seq.out.bad
echo "/^$seq\$/d" >>$tmp.expunged
elif [ ! -f $seq ]
then
echo " - no such test?"
echo "/^$seq\$/d" >>$tmp.expunged
else
# really going to try and run this one
#
rm -f $seq.out.bad
lasttime=`sed -n -e "/^$seq /s/.* //p" <check.time`
if [ "X$lasttime" != X ]; then
echo -n " ${lasttime}s ..."
else
echo -n " " # prettier output with timestamps.
fi
rm -f core $seq.notrun
# for hangcheck ...
echo "$seq" >/tmp/check.sts
start=`_wallclock`
$timestamp && echo -n " ["`date "+%T"`"]"
[ ! -x $seq ] && chmod u+x $seq # ensure we can run it
$LOGGER_PROG "run xfstest $seq"
./$seq >$tmp.rawout 2>&1
sts=$?
$timestamp && _timestamp
stop=`_wallclock`
_fix_malloc <$tmp.rawout >$tmp.out
rm -f $tmp.rawout
if [ -f core ]
then
echo -n " [dumped core]"
mv core $seq.core
err=true
fi
if [ -f $seq.notrun ]
then
$timestamp || echo -n " [not run] "
$timestamp && echo " [not run]" && echo -n " $seq -- "
cat $seq.notrun
notrun="$notrun $seq"
else
if [ $sts -ne 0 ]
then
echo -n " [failed, exit status $sts]"
err=true
fi
if [ ! -f $seq.out ]
then
echo " - no qualified output"
err=true
else
if diff $seq.out $tmp.out >/dev/null 2>&1
then
if $err
then
:
else
echo "$seq `expr $stop - $start`" >>$tmp.time
echo -n " `expr $stop - $start`s"
fi
echo ""
else
echo " - output mismatch (see $seq.out.bad)"
mv $tmp.out $seq.out.bad
$diff $seq.out $seq.out.bad | {
if test "$DIFF_LENGTH" -le 0; then
cat
else
head -n "$DIFF_LENGTH"
fi; } | \
sed -e 's/^\(.\)/ \1/'
echo " ..."
echo " (Run '$diff $seq.out $seq.out.bad' to see the" \
"entire diff)"
err=true
fi
fi
fi
fi
# come here for each test, except when $showme is true
#
if $err
then
bad="$bad $seq"
n_bad=`expr $n_bad + 1`
quick=false
fi
if [ ! -f $seq.notrun ]
then
try="$try $seq"
n_try=`expr $n_try + 1`
_check_test_fs
fi
seq="after_$seq"
done
interrupt=false
status=`expr $n_bad`
exit