3 # Control script for QA
5 # Copyright (c) 2000-2002,2006 Silicon Graphics, Inc. All Rights Reserved.
7 # This program is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU General Public License as
9 # published by the Free Software Foundation.
11 # This program is distributed in the hope that it would be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write the Free Software Foundation,
18 # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
40 brief_test_summary=false
45 # start the initialisation work now
48 export MSGVERB="text:action"
49 export QA_CHECK_FS=${QA_CHECK_FS:=true}
51 # number of diff lines from a failed test, 0 for whole output
52 export DIFF_LENGTH=${DIFF_LENGTH:=10}
54 # by default don't output timestamps
55 timestamp=${TIMESTAMP:=false}
57 rm -f $tmp.list $tmp.tmp $tmp.grep $here/$iam.out $tmp.xlist $tmp.report.*
59 SRC_GROUPS="generic shared"
60 export SRC_DIR="tests"
64 echo "Usage: $0 [options] [testlist]"'
68 -glusterfs test GlusterFS
76 -udiff show unified diff (default)
77 -n show me, do not run tests
79 -r randomize test order
80 -d dump test output to stdout
82 -R fmt[,fmt] generate report in formats specified. Supported format: [xunit]
83 --large-fs optimise scratch device for large filesystems
84 -s section run only specified section from config file
85 -S section exclude the specified section from the config file
88 -g group[,group...] include tests from these groups
89 -x group[,group...] exclude tests from these groups
90 -X exclude_file exclude individual tests
91 -E external_file exclude individual tests
92 [testlist] include tests matching names in testlist
94 testlist argument is a list of tests in the form of <test dir>/<test name>.
96 <test dir> is a directory under tests that contains a group file,
97 with a list of the names of the tests in that directory.
99 <test name> may be either a specific test file name (e.g. xfs/001) or
100 a test file name match pattern (e.g. xfs/*).
102 group argument is either a name of a tests group to collect from all
103 the test dirs (e.g. quick) or a name of a tests group to collect from
104 a specific tests dir in the form of <test dir>/<group name> (e.g. xfs/quick).
105 If you want to run all the tests in the test suite, use "-g all" to specify all
108 exclude_file argument refers to a name of a file inside each test directory.
109 for every test dir where this file is found, the listed test names are
110 excluded from the list of tests to run from that test dir.
112 external_file argument is a path to a single file containing a list of tests
113 to exclude in the form of <test dir>/<test name>.
119 check -x stress xfs/*
120 check -X .exclude -g auto
121 check -E ~/.xfstests.exclude
131 test -s "$SRC_DIR/$d/group" || return 1
133 local grpl=$(sed -n < $SRC_DIR/$d/group \
136 -e "s;^\($VALID_TEST_NAME\).* $grp .*;$SRC_DIR/$d/\1;p")
144 local sub=$(dirname $grp)
146 if [ -n "$sub" -a "$sub" != "." -a -d "$SRC_DIR/$sub" ]; then
147 # group is given as <subdir>/<group> (e.g. xfs/quick)
149 get_sub_group_list $sub $grp
153 for d in $SRC_GROUPS $FSTYP; do
154 if ! test -d "$SRC_DIR/$d" ; then
157 grpl="$grpl $(get_sub_group_list $d $grp)"
162 # Find all tests, excluding files that are test metadata such as group files.
163 # It matches test names against $VALID_TEST_NAME defined in common/rc
167 for d in $SRC_GROUPS $FSTYP; do
168 if ! test -d "$SRC_DIR/$d" ; then
173 grep "^$SRC_DIR/$d/$VALID_TEST_NAME"| \
174 grep -v "group\|Makefile" >> $tmp.list 2>/dev/null
178 # takes the list of tests to run in $tmp.list, and removes the tests passed to
179 # the function from that list.
188 if [ $numsed -gt 100 ]; then
189 grep -v -f $tmp.grep <$tmp.list >$tmp.tmp
190 mv $tmp.tmp $tmp.list
194 echo "^$t\$" >>$tmp.grep
195 numsed=`expr $numsed + 1`
197 grep -v -f $tmp.grep <$tmp.list >$tmp.tmp
198 mv $tmp.tmp $tmp.list
217 # Tests specified on the command line
218 if [ -s $tmp.arglist ]; then
219 cat $tmp.arglist > $tmp.list
224 # Specified groups to include
225 # Note that the CLI processing adds a leading space to the first group
226 # parameter, so we have to catch that here checking for "all"
227 if ! $have_test_arg && [ "$GROUP_LIST" == " all" ]; then
228 # no test numbers, do everything
231 for group in $GROUP_LIST; do
232 list=$(get_group_list $group)
233 if [ -z "$list" ]; then
234 echo "Group \"$group\" is empty or not defined?"
239 grep -s "^$t\$" $tmp.list >/dev/null || \
240 echo "$t" >>$tmp.list
245 # Specified groups to exclude
246 for xgroup in $XGROUP_LIST; do
247 list=$(get_group_list $xgroup)
248 if [ -z "$list" ]; then
249 echo "Group \"$xgroup\" is empty or not defined?"
256 # sort the list of tests into numeric order
257 list=`sort -n $tmp.list | uniq`
262 list=`echo $list | awk -f randomize.awk`
266 # Process command arguments first.
267 while [ $# -gt 0 ]; do
269 -\? | -h | --help) usage ;;
272 -glusterfs) FSTYP=glusterfs ;;
275 -overlay) FSTYP=overlay; export OVERLAY=true ;;
276 -pvfs2) FSTYP=pvfs2 ;;
277 -tmpfs) FSTYP=tmpfs ;;
278 -ubifs) FSTYP=ubifs ;;
280 -g) group=$2 ; shift ;
281 GROUP_LIST="$GROUP_LIST ${group//,/ }"
284 -x) xgroup=$2 ; shift ;
285 XGROUP_LIST="$XGROUP_LIST ${xgroup//,/ }"
288 -X) xfile=$2; shift ;
289 for d in $SRC_GROUPS $FSTYP; do
290 [ -f $SRC_DIR/$d/$xfile ] || continue
291 for f in `sed "s/#.*$//" $SRC_DIR/$d/$xfile`; do
292 echo $d/$f >> $tmp.xlist
296 -E) xfile=$2; shift ;
297 if [ -f $xfile ]; then
298 sed "s/#.*$//" "$xfile" >> $tmp.xlist
301 -s) RUN_SECTION="$RUN_SECTION $2"; shift ;;
302 -S) EXCLUDE_SECTION="$EXCLUDE_SECTION $2"; shift ;;
304 -udiff) diff="$diff -u" ;;
307 -r) randomize=true ;;
309 -T) timestamp=true ;;
310 -d) DUMP_OUTPUT=true ;;
311 -b) brief_test_summary=true;;
312 -R) report_fmt=$2 ; shift ;
313 REPORT_LIST="$REPORT_LIST ${report_fmt//,/ }"
316 --large-fs) export LARGE_SCRATCH_DEV=yes ;;
317 --extra-space=*) export SCRATCH_DEV_EMPTY_SPACE=${r#*=} ;;
320 *) # not an argument, we've got tests now.
321 have_test_arg=true ;;
324 # if we've found a test specification, the break out of the processing
325 # loop before we shift the arguments so that this is the first argument
326 # that we process in the test arg loop below.
327 if $have_test_arg; then
334 # we need common/config, source it after processing args, overlay needs FSTYP
335 # set before sourcing common/config
336 if ! . ./common/config; then
337 echo "$iam: failed to source common/config"
341 # Process tests from command line now.
342 if $have_test_arg; then
343 while [ $# -gt 0 ]; do
345 -*) echo "Arguments before tests, please!"
349 *) # Expand test pattern (e.g. xfs/???, *fs/001)
350 list=$(cd $SRC_DIR; echo $1)
352 test_dir=`dirname $t`
353 test_dir=${test_dir#$SRC_DIR/*}
354 test_name=`basename $t`
355 group_file=$SRC_DIR/$test_dir/group
357 if egrep -q "^$test_name" $group_file; then
358 # in group file ... OK
359 echo $SRC_DIR/$test_dir/$test_name \
363 echo "$t - unknown test, ignored"
371 elif [ -z "$GROUP_LIST" ]; then
372 # default group list is the auto group. If any other group or test is
373 # specified, we use that instead.
380 echo "check: failed to source common/rc"
386 echo "check: QA must be run as root"
401 check="$RESULT_BASE/check"
411 if [ -f $check.time -a -f $tmp.time ]; then
412 cat $check.time $tmp.time \
417 for (i in t) print i " " t[i]
421 mv $tmp.out $check.time
427 echo "SECTION -- $section" >>$tmp.summary
428 echo "=========================" >>$tmp.summary
429 if [ ! -z "$n_try" -a $n_try != 0 ]; then
430 if [ $brief_test_summary == "false" ]; then
432 echo "Ran:$try" >>$tmp.summary
434 echo "Ran:$try" >>$check.log
437 $interrupt && echo "Interrupted!" | tee -a $check.log
439 if [ ! -z "$notrun" ]; then
440 if [ $brief_test_summary == "false" ]; then
441 echo "Not run:$notrun"
442 echo "Not run:$notrun" >>$tmp.summary
444 echo "Not run:$notrun" >>$check.log
447 if [ ! -z "$n_bad" -a $n_bad != 0 ]; then
449 echo "Failed $n_bad of $n_try tests"
450 echo "Failures:$bad" >>$check.log
451 echo "Failed $n_bad of $n_try tests" >>$check.log
452 echo "Failures:$bad" >>$tmp.summary
453 echo "Failed $n_bad of $n_try tests" >>$tmp.summary
455 echo "Passed all $n_try tests"
456 echo "Passed all $n_try tests" >>$check.log
457 echo "Passed all $n_try tests" >>$tmp.summary
459 echo "" >>$tmp.summary
466 sum_bad=`expr $sum_bad + $n_bad`
468 rm -f /tmp/*.rawout /tmp/*.out /tmp/*.err /tmp/*.time
469 if ! $OPTIONS_HAVE_SECTIONS; then
480 count=`wc -L $tmp.summary | cut -f1 -d" "`
489 if [ -f ${RESULT_DIR}/require_test ]; then
490 _check_test_fs || err=true
491 rm -f ${RESULT_DIR}/require_test*
493 if [ -f ${RESULT_DIR}/require_scratch ]; then
494 _check_scratch_fs || err=true
495 rm -f ${RESULT_DIR}/require_scratch*
502 if [ -s $tmp.xlist ]; then
503 if grep -q $TEST_ID $tmp.xlist; then
514 if $OPTIONS_HAVE_SECTIONS; then
515 trap "_summary; exit \$status" 0 1 2 3 15
517 trap "_wrapup; exit \$status" 0 1 2 3 15
520 for section in $HOST_OPTIONS_SECTIONS; do
522 OLD_TEST_FS_MOUNT_OPTS=$TEST_FS_MOUNT_OPTS
523 get_next_config $section
525 # Do we need to run only some sections ?
526 if [ ! -z "$RUN_SECTION" ]; then
528 for s in $RUN_SECTION; do
529 if [ $section == $s ]; then
539 # Did this section get excluded?
540 if [ ! -z "$EXCLUDE_SECTION" ]; then
542 for s in $EXCLUDE_SECTION; do
543 if [ $section == $s ]; then
553 mkdir -p $RESULT_BASE
554 if [ ! -d $RESULT_BASE ]; then
555 echo "failed to create results directory $RESULT_BASE"
560 if $OPTIONS_HAVE_SECTIONS; then
561 echo "SECTION -- $section"
564 sect_start=`_wallclock`
565 if $RECREATE_TEST_DEV || [ "$OLD_FSTYP" != "$FSTYP" ]; then
566 echo "RECREATING -- $FSTYP on $TEST_DEV"
567 _test_unmount 2> /dev/null
568 if ! _test_mkfs >$tmp.err 2>&1
570 echo "our local _test_mkfs routine ..."
572 echo "check: failed to mkfs \$TEST_DEV using specified options"
578 echo "check: failed to mount $TEST_DEV on $TEST_DIR"
583 elif [ "$OLD_TEST_FS_MOUNT_OPTS" != "$TEST_FS_MOUNT_OPTS" ]; then
584 _test_unmount 2> /dev/null
587 echo "check: failed to mount $TEST_DEV on $TEST_DIR"
596 check="$RESULT_BASE/check"
598 # don't leave old full output behind on a clean run
601 [ -f $check.time ] || touch $check.time
603 # print out our test configuration
604 echo "FSTYP -- `_full_fstyp_details`"
605 echo "PLATFORM -- `_full_platform_details`"
606 if [ ! -z "$SCRATCH_DEV" ]; then
607 echo "MKFS_OPTIONS -- `_scratch_mkfs_options`"
608 echo "MOUNT_OPTIONS -- `_scratch_mount_options`"
613 if [ ! -z "$SCRATCH_DEV" ]; then
614 _scratch_unmount 2> /dev/null
615 # call the overridden mkfs - make sure the FS is built
616 # the same as we'll create it later.
618 if ! _scratch_mkfs >$tmp.err 2>&1
620 echo "our local _scratch_mkfs routine ..."
622 echo "check: failed to mkfs \$SCRATCH_DEV using specified options"
627 # call the overridden mount - make sure the FS mounts with
628 # the same options that we'll mount with later.
629 if ! _scratch_mount >$tmp.err 2>&1
631 echo "our local mount routine ..."
633 echo "check: failed to mount \$SCRATCH_DEV using specified options"
646 if [ ! -f $seq ]; then
647 # Try to get full name in case the user supplied only seq id
648 # and the test has a name. A bit of hassle to find really
649 # the test and not its sample output or helping files.
650 bname=$(basename $seq)
651 full_seq=$(find $(dirname $seq) -name $bname* -executable |
652 awk '(NR == 1 || length < length(shortest)) { shortest = $0 }\
653 END { print shortest }')
654 if [ -f $full_seq ] \
655 && [ x$(echo $bname | grep -o "^$VALID_TEST_ID") != x ]; then
660 # the filename for the test and the name output are different.
661 # we don't include the tests/ directory in the name output.
662 export seqnum=`echo $seq | sed -e "s;$SRC_DIR/;;"`
664 # Similarly, the result directory needs to replace the tests/
665 # part of the test location.
667 if $OPTIONS_HAVE_SECTIONS; then
668 export RESULT_DIR=`echo $group | sed -e "s;$SRC_DIR;${RESULT_BASE}/$section;"`
669 REPORT_DIR="$RESULT_BASE/$section"
671 export RESULT_DIR=`echo $group | sed -e "s;$SRC_DIR;$RESULT_BASE;"`
672 REPORT_DIR="$RESULT_BASE"
674 seqres="$REPORT_DIR/$seqnum"
681 _expunge_test $seqnum
682 if [ $? -eq 1 ]; then
688 n_notrun=`expr $n_notrun + 1`
690 _make_testcase_report "list"
695 if [ ! -f $seq ]; then
696 echo " - no such test?"
698 # really going to try and run this one
700 rm -f $seqres.out.bad
702 # check if we really should run it
703 _expunge_test $seqnum
704 if [ $? -eq 1 ]; then
708 # slashes now in names, sed barfs on them so use grep
709 lasttime=`grep -w ^$seqnum $check.time | awk '// {print $2}'`
710 if [ "X$lasttime" != X ]; then
711 echo -n " ${lasttime}s ..."
713 echo -n " " # prettier output with timestamps.
715 rm -f core $seqres.notrun
718 $timestamp && echo -n " ["`date "+%T"`"]"
719 [ ! -x $seq ] && chmod u+x $seq # ensure we can run it
720 $LOGGER_PROG "run xfstest $seqnum"
721 if [ -w /dev/kmsg ]; then
722 export date_time=`date +"%F %T"`
723 echo "run fstests $seqnum at $date_time" > /dev/kmsg
724 # _check_dmesg depends on this log in dmesg
725 touch ${RESULT_DIR}/check_dmesg
727 if [ "$DUMP_OUTPUT" = true ]; then
728 ./$seq 2>&1 | tee $tmp.rawout
729 # Because $? would get tee's return code
732 ./$seq >$tmp.rawout 2>&1
735 $timestamp && _timestamp
738 _fix_malloc <$tmp.rawout >$tmp.out
743 _err_msg="[dumped core]"
745 mv core $RESULT_BASE/$seqnum.core
749 if [ -f $seqres.notrun ]
751 $timestamp || echo -n " [not run] "
752 $timestamp && echo " [not run]" && echo -n " $seqnum -- "
754 notrun="$notrun $seqnum"
755 n_notrun=`expr $n_notrun + 1`
760 _err_msg="[failed, exit status $sts]"
766 _dump_err "no qualified output"
770 # coreutils 8.16+ changed quote formats in error messages from
771 # `foo' to 'foo'. Filter old versions to match the new version.
772 sed -i "s/\`/\'/g" $tmp.out
773 if diff $seq.out $tmp.out >/dev/null 2>&1
779 echo "$seqnum `expr $stop - $start`" >>$tmp.time
780 echo -n " `expr $stop - $start`s"
784 echo " - output mismatch (see $seqres.out.bad)"
785 mv $tmp.out $seqres.out.bad
786 $diff $seq.out $seqres.out.bad | {
787 if test "$DIFF_LENGTH" -le 0; then
790 head -n "$DIFF_LENGTH"
792 echo "(Run '$diff $seq.out $seqres.out.bad'" \
793 " to see the entire diff)"
795 sed -e 's/^\(.\)/ \1/'
796 _err_msg="output mismatch (see $diff $seq.out $seqres.out.bad)"
801 n_try=`expr $n_try + 1`
803 _check_dmesg || err=true
804 _check_kmemleak || err=true
809 # come here for each test, except when $showme is true
814 n_bad=`expr $n_bad + 1`
818 _make_testcase_report "$tc_status"
822 sect_stop=`_wallclock`
828 _test_unmount 2> /dev/null
829 _scratch_unmount 2> /dev/null
833 status=`expr $sum_bad != 0`