fsstress: allow afsync on directories too
[xfstests-dev.git] / check
1 #!/bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3 # Copyright (c) 2000-2002,2006 Silicon Graphics, Inc.  All Rights Reserved.
4 #
5 # Control script for QA
6 #
7 tmp=/tmp/$$
8 status=0
9 needwrap=true
10 needsum=true
11 n_try=0
12 try=""
13 n_bad=0
14 sum_bad=0
15 bad=""
16 n_notrun=0
17 notrun=""
18 interrupt=true
19 diff="diff -u"
20 showme=false
21 have_test_arg=false
22 randomize=false
23 export here=`pwd`
24 xfile=""
25 subdir_xfile=""
26 brief_test_summary=false
27 do_report=false
28 DUMP_OUTPUT=false
29
30 # This is a global variable used to pass test failure text to reporting gunk
31 _err_msg=""
32
33 # start the initialisation work now
34 iam=check
35
36 export MSGVERB="text:action"
37 export QA_CHECK_FS=${QA_CHECK_FS:=true}
38
39 # number of diff lines from a failed test, 0 for whole output
40 export DIFF_LENGTH=${DIFF_LENGTH:=10}
41
42 # by default don't output timestamps
43 timestamp=${TIMESTAMP:=false}
44
45 rm -f $tmp.list $tmp.tmp $tmp.grep $here/$iam.out $tmp.xlist $tmp.report.*
46
47 SRC_GROUPS="generic shared"
48 export SRC_DIR="tests"
49
50 usage()
51 {
52     echo "Usage: $0 [options] [testlist]"'
53
54 check options
55     -nfs                test NFS
56     -glusterfs                test GlusterFS
57     -cifs               test CIFS
58     -9p                 test 9p
59     -overlay            test overlay
60     -pvfs2          test PVFS2
61     -tmpfs              test TMPFS
62     -ubifs              test ubifs
63     -l                  line mode diff
64     -udiff              show unified diff (default)
65     -n                  show me, do not run tests
66     -T                  output timestamps
67     -r                  randomize test order
68     -d                  dump test output to stdout
69     -b                  brief test summary
70     -R fmt[,fmt]        generate report in formats specified. Supported format: [xunit]
71     --large-fs          optimise scratch device for large filesystems
72     -s section          run only specified section from config file
73     -S section          exclude the specified section from the config file
74
75 testlist options
76     -g group[,group...] include tests from these groups
77     -x group[,group...] exclude tests from these groups
78     -X exclude_file     exclude individual tests
79     -E external_file    exclude individual tests
80     [testlist]          include tests matching names in testlist
81
82 testlist argument is a list of tests in the form of <test dir>/<test name>.
83
84 <test dir> is a directory under tests that contains a group file,
85 with a list of the names of the tests in that directory.
86
87 <test name> may be either a specific test file name (e.g. xfs/001) or
88 a test file name match pattern (e.g. xfs/*).
89
90 group argument is either a name of a tests group to collect from all
91 the test dirs (e.g. quick) or a name of a tests group to collect from
92 a specific tests dir in the form of <test dir>/<group name> (e.g. xfs/quick).
93 If you want to run all the tests in the test suite, use "-g all" to specify all
94 groups.
95
96 exclude_file argument refers to a name of a file inside each test directory.
97 for every test dir where this file is found, the listed test names are
98 excluded from the list of tests to run from that test dir.
99
100 external_file argument is a path to a single file containing a list of tests
101 to exclude in the form of <test dir>/<test name>.
102
103 examples:
104  check xfs/001
105  check -g quick
106  check -g xfs/quick
107  check -x stress xfs/*
108  check -X .exclude -g auto
109  check -E ~/.xfstests.exclude
110 '
111             exit 0
112 }
113
114 get_sub_group_list()
115 {
116         local d=$1
117         local grp=$2
118
119         test -s "$SRC_DIR/$d/group" || return 1
120
121         local grpl=$(sed -n < $SRC_DIR/$d/group \
122                 -e 's/#.*//' \
123                 -e 's/$/ /' \
124                 -e "s;^\($VALID_TEST_NAME\).* $grp .*;$SRC_DIR/$d/\1;p")
125         echo $grpl
126 }
127
128 get_group_list()
129 {
130         local grp=$1
131         local grpl=""
132         local sub=$(dirname $grp)
133
134         if [ -n "$sub" -a "$sub" != "." -a -d "$SRC_DIR/$sub" ]; then
135                 # group is given as <subdir>/<group> (e.g. xfs/quick)
136                 grp=$(basename $grp)
137                 get_sub_group_list $sub $grp
138                 return
139         fi
140
141         for d in $SRC_GROUPS $FSTYP; do
142                 if ! test -d "$SRC_DIR/$d" ; then
143                         continue
144                 fi
145                 grpl="$grpl $(get_sub_group_list $d $grp)"
146         done
147         echo $grpl
148 }
149
150 # Find all tests, excluding files that are test metadata such as group files.
151 # It matches test names against $VALID_TEST_NAME defined in common/rc
152 get_all_tests()
153 {
154         touch $tmp.list
155         for d in $SRC_GROUPS $FSTYP; do
156                 if ! test -d "$SRC_DIR/$d" ; then
157                         continue
158                 fi
159                 ls $SRC_DIR/$d/* | \
160                         grep -v "\..*" | \
161                         grep "^$SRC_DIR/$d/$VALID_TEST_NAME"| \
162                         grep -v "group\|Makefile" >> $tmp.list 2>/dev/null
163         done
164 }
165
166 # takes the list of tests to run in $tmp.list, and removes the tests passed to
167 # the function from that list.
168 trim_test_list()
169 {
170         test_list="$*"
171
172         rm -f $tmp.grep
173         numsed=0
174         for t in $test_list
175         do
176             if [ $numsed -gt 100 ]; then
177                 grep -v -f $tmp.grep <$tmp.list >$tmp.tmp
178                 mv $tmp.tmp $tmp.list
179                 numsed=0
180                 rm -f $tmp.grep
181             fi
182             echo "^$t\$" >>$tmp.grep
183             numsed=`expr $numsed + 1`
184         done
185         grep -v -f $tmp.grep <$tmp.list >$tmp.tmp
186         mv $tmp.tmp $tmp.list
187         rm -f $tmp.grep
188 }
189
190
191 _wallclock()
192 {
193     date "+%s"
194 }
195
196 _timestamp()
197 {
198     now=`date "+%T"`
199     echo -n " [$now]"
200 }
201
202 _prepare_test_list()
203 {
204         unset list
205         # Tests specified on the command line
206         if [ -s $tmp.arglist ]; then
207                 cat $tmp.arglist > $tmp.list
208         else
209                 touch $tmp.list
210         fi
211
212         # Specified groups to include
213         # Note that the CLI processing adds a leading space to the first group
214         # parameter, so we have to catch that here checking for "all"
215         if ! $have_test_arg && [ "$GROUP_LIST" == " all" ]; then
216                 # no test numbers, do everything
217                 get_all_tests
218         else
219                 for group in $GROUP_LIST; do
220                         list=$(get_group_list $group)
221                         if [ -z "$list" ]; then
222                                 echo "Group \"$group\" is empty or not defined?"
223                                 exit 1
224                         fi
225
226                         for t in $list; do
227                                 grep -s "^$t\$" $tmp.list >/dev/null || \
228                                                         echo "$t" >>$tmp.list
229                         done
230                 done
231         fi
232
233         # Specified groups to exclude
234         for xgroup in $XGROUP_LIST; do
235                 list=$(get_group_list $xgroup)
236                 if [ -z "$list" ]; then
237                         echo "Group \"$xgroup\" is empty or not defined?"
238                         exit 1
239                 fi
240
241                 trim_test_list $list
242         done
243
244         # sort the list of tests into numeric order
245         if $randomize; then
246                 if type shuf >& /dev/null; then
247                         sorter="shuf"
248                 else
249                         sorter="awk -v seed=$RANDOM -f randomize.awk"
250                 fi
251         else
252                 sorter="cat"
253         fi
254         list=`sort -n $tmp.list | uniq | $sorter`
255         rm -f $tmp.list
256 }
257
258 # Process command arguments first.
259 while [ $# -gt 0 ]; do
260         case "$1" in
261         -\? | -h | --help) usage ;;
262
263         -nfs)           FSTYP=nfs ;;
264         -glusterfs)     FSTYP=glusterfs ;;
265         -cifs)          FSTYP=cifs ;;
266         -9p)            FSTYP=9p ;;
267         -overlay)       FSTYP=overlay; export OVERLAY=true ;;
268         -pvfs2)         FSTYP=pvfs2 ;;
269         -tmpfs)         FSTYP=tmpfs ;;
270         -ubifs)         FSTYP=ubifs ;;
271
272         -g)     group=$2 ; shift ;
273                 GROUP_LIST="$GROUP_LIST ${group//,/ }"
274                 ;;
275
276         -x)     xgroup=$2 ; shift ;
277                 XGROUP_LIST="$XGROUP_LIST ${xgroup//,/ }"
278                 ;;
279
280         -X)     subdir_xfile=$2; shift ;
281                 ;;
282         -E)     xfile=$2; shift ;
283                 if [ -f $xfile ]; then
284                         sed "s/#.*$//" "$xfile" >> $tmp.xlist
285                 fi
286                 ;;
287         -s)     RUN_SECTION="$RUN_SECTION $2"; shift ;;
288         -S)     EXCLUDE_SECTION="$EXCLUDE_SECTION $2"; shift ;;
289         -l)     diff="diff" ;;
290         -udiff) diff="$diff -u" ;;
291
292         -n)     showme=true ;;
293         -r)     randomize=true ;;
294
295         -T)     timestamp=true ;;
296         -d)     DUMP_OUTPUT=true ;;
297         -b)     brief_test_summary=true;;
298         -R)     report_fmt=$2 ; shift ;
299                 REPORT_LIST="$REPORT_LIST ${report_fmt//,/ }"
300                 do_report=true
301                 ;;
302         --large-fs) export LARGE_SCRATCH_DEV=yes ;;
303         --extra-space=*) export SCRATCH_DEV_EMPTY_SPACE=${r#*=} ;;
304
305         -*)     usage ;;
306         *)      # not an argument, we've got tests now.
307                 have_test_arg=true ;;
308         esac
309
310         # if we've found a test specification, the break out of the processing
311         # loop before we shift the arguments so that this is the first argument
312         # that we process in the test arg loop below.
313         if $have_test_arg; then
314                 break;
315         fi
316
317         shift
318 done
319
320 # we need common/rc, that also sources common/config. We need to source it
321 # after processing args, overlay needs FSTYP set before sourcing common/config
322 if ! . ./common/rc; then
323         echo "check: failed to source common/rc"
324         exit 1
325 fi
326
327 if [ -n "$subdir_xfile" ]; then
328         for d in $SRC_GROUPS $FSTYP; do
329                 [ -f $SRC_DIR/$d/$subdir_xfile ] || continue
330                 for f in `sed "s/#.*$//" $SRC_DIR/$d/$subdir_xfile`; do
331                         echo $d/$f >> $tmp.xlist
332                 done
333         done
334 fi
335
336 # Process tests from command line now.
337 if $have_test_arg; then
338         while [ $# -gt 0 ]; do
339                 case "$1" in
340                 -*)     echo "Arguments before tests, please!"
341                         status=1
342                         exit $status
343                         ;;
344                 *)      # Expand test pattern (e.g. xfs/???, *fs/001)
345                         list=$(cd $SRC_DIR; echo $1)
346                         for t in $list; do
347                                 test_dir=`dirname $t`
348                                 test_dir=${test_dir#$SRC_DIR/*}
349                                 test_name=`basename $t`
350                                 group_file=$SRC_DIR/$test_dir/group
351
352                                 if egrep -q "^$test_name" $group_file; then
353                                         # in group file ... OK
354                                         echo $SRC_DIR/$test_dir/$test_name \
355                                                 >>$tmp.arglist
356                                 else
357                                         # oops
358                                         echo "$t - unknown test, ignored"
359                                 fi
360                         done
361                         ;;
362                 esac
363
364                 shift
365         done
366 elif [ -z "$GROUP_LIST" ]; then
367         # default group list is the auto group. If any other group or test is
368         # specified, we use that instead.
369         GROUP_LIST="auto"
370 fi
371
372 if [ `id -u` -ne 0 ]
373 then
374     echo "check: QA must be run as root"
375     exit 1
376 fi
377
378 _wipe_counters()
379 {
380         n_try="0"
381         n_bad="0"
382         n_notrun="0"
383         unset try notrun bad
384 }
385
386 _wrapup()
387 {
388         seq="check"
389         check="$RESULT_BASE/check"
390
391         if $showme; then
392                 if $needwrap; then
393                         if $do_report; then
394                                 _make_section_report
395                         fi
396                         needwrap=false
397                 fi
398         elif $needwrap; then
399                 if [ -f $check.time -a -f $tmp.time ]; then
400                         cat $check.time $tmp.time  \
401                                 | $AWK_PROG '
402                                 { t[$1] = $2 }
403                                 END {
404                                         if (NR > 0) {
405                                                 for (i in t) print i " " t[i]
406                                         }
407                                 }' \
408                                 | sort -n >$tmp.out
409                         mv $tmp.out $check.time
410                 fi
411
412                 echo "" >>$check.log
413                 date >>$check.log
414
415                 echo "SECTION       -- $section" >>$tmp.summary
416                 echo "=========================" >>$tmp.summary
417                 if [ ! -z "$n_try" -a $n_try != 0 ]; then
418                         if [ $brief_test_summary == "false" ]; then
419                                 echo "Ran:$try"
420                                 echo "Ran:$try" >>$tmp.summary
421                         fi
422                         echo "Ran:$try" >>$check.log
423                 fi
424
425                 $interrupt && echo "Interrupted!" | tee -a $check.log
426
427                 if [ ! -z "$notrun" ]; then
428                         if [ $brief_test_summary == "false" ]; then
429                                 echo "Not run:$notrun"
430                                 echo "Not run:$notrun" >>$tmp.summary
431                         fi
432                         echo "Not run:$notrun" >>$check.log
433                 fi
434
435                 if [ ! -z "$n_bad" -a $n_bad != 0 ]; then
436                         echo "Failures:$bad"
437                         echo "Failed $n_bad of $n_try tests"
438                         echo "Failures:$bad" >>$check.log
439                         echo "Failed $n_bad of $n_try tests" >>$check.log
440                         echo "Failures:$bad" >>$tmp.summary
441                         echo "Failed $n_bad of $n_try tests" >>$tmp.summary
442                 else
443                         echo "Passed all $n_try tests"
444                         echo "Passed all $n_try tests" >>$check.log
445                         echo "Passed all $n_try tests" >>$tmp.summary
446                 fi
447                 echo "" >>$tmp.summary
448                 if $do_report; then
449                         _make_section_report
450                 fi
451                 needwrap=false
452         fi
453
454         sum_bad=`expr $sum_bad + $n_bad`
455         _wipe_counters
456         rm -f /tmp/*.rawout /tmp/*.out /tmp/*.err /tmp/*.time
457         if ! $OPTIONS_HAVE_SECTIONS; then
458                 rm -f $tmp.*
459         fi
460 }
461
462 _summary()
463 {
464         _wrapup
465         if $showme; then
466                 :
467         elif $needsum; then
468                 count=`wc -L $tmp.summary | cut -f1 -d" "`
469                 cat $tmp.summary
470                 needsum=false
471         fi
472         rm -f $tmp.*
473 }
474
475 _check_filesystems()
476 {
477         if [ -f ${RESULT_DIR}/require_test ]; then
478                 _check_test_fs || err=true
479                 rm -f ${RESULT_DIR}/require_test*
480         else
481                 _test_unmount 2> /dev/null
482         fi
483         if [ -f ${RESULT_DIR}/require_scratch ]; then
484                 _check_scratch_fs || err=true
485                 rm -f ${RESULT_DIR}/require_scratch*
486         else
487                 _scratch_unmount 2> /dev/null
488         fi
489 }
490
491 _expunge_test()
492 {
493         local TEST_ID="$1"
494         if [ -s $tmp.xlist ]; then
495                 if grep -q $TEST_ID $tmp.xlist; then
496                         echo "       [expunged]"
497                         return 1
498                 fi
499         fi
500         return 0
501 }
502
503 _detect_kmemleak
504 _prepare_test_list
505
506 if $OPTIONS_HAVE_SECTIONS; then
507         trap "_summary; exit \$status" 0 1 2 3 15
508 else
509         trap "_wrapup; exit \$status" 0 1 2 3 15
510 fi
511
512 for section in $HOST_OPTIONS_SECTIONS; do
513         OLD_FSTYP=$FSTYP
514         OLD_TEST_FS_MOUNT_OPTS=$TEST_FS_MOUNT_OPTS
515         get_next_config $section
516
517         # Do we need to run only some sections ?
518         if [ ! -z "$RUN_SECTION" ]; then
519                 skip=true
520                 for s in $RUN_SECTION; do
521                         if [ $section == $s ]; then
522                                 skip=false
523                                 break;
524                         fi
525                 done
526                 if $skip; then
527                         continue
528                 fi
529         fi
530
531         # Did this section get excluded?
532         if [ ! -z "$EXCLUDE_SECTION" ]; then
533                 skip=false
534                 for s in $EXCLUDE_SECTION; do
535                         if [ $section == $s ]; then
536                                 skip=true
537                                 break;
538                         fi
539                 done
540                 if $skip; then
541                         continue
542                 fi
543         fi
544
545         mkdir -p $RESULT_BASE
546         if [ ! -d $RESULT_BASE ]; then
547                 echo "failed to create results directory $RESULT_BASE"
548                 status=1
549                 exit
550         fi
551
552         if $OPTIONS_HAVE_SECTIONS; then
553                 echo "SECTION       -- $section"
554         fi
555
556         sect_start=`_wallclock`
557         if $RECREATE_TEST_DEV || [ "$OLD_FSTYP" != "$FSTYP" ]; then
558                 echo "RECREATING    -- $FSTYP on $TEST_DEV"
559                 _test_unmount 2> /dev/null
560                 if ! _test_mkfs >$tmp.err 2>&1
561                 then
562                         echo "our local _test_mkfs routine ..."
563                         cat $tmp.err
564                         echo "check: failed to mkfs \$TEST_DEV using specified options"
565                         status=1
566                         exit
567                 fi
568                 if ! _test_mount
569                 then
570                         echo "check: failed to mount $TEST_DEV on $TEST_DIR"
571                         status=1
572                         exit
573                 fi
574                 _prepare_test_list
575         elif [ "$OLD_TEST_FS_MOUNT_OPTS" != "$TEST_FS_MOUNT_OPTS" ]; then
576                 _test_unmount 2> /dev/null
577                 if ! _test_mount
578                 then
579                         echo "check: failed to mount $TEST_DEV on $TEST_DIR"
580                         status=1
581                         exit
582                 fi
583         fi
584
585         init_rc
586
587         seq="check"
588         check="$RESULT_BASE/check"
589
590         # don't leave old full output behind on a clean run
591         rm -f $check.full
592
593         [ -f $check.time ] || touch $check.time
594
595         # print out our test configuration
596         echo "FSTYP         -- `_full_fstyp_details`"
597         echo "PLATFORM      -- `_full_platform_details`"
598         if [ ! -z "$SCRATCH_DEV" ]; then
599           echo "MKFS_OPTIONS  -- `_scratch_mkfs_options`"
600           echo "MOUNT_OPTIONS -- `_scratch_mount_options`"
601         fi
602         echo
603         needwrap=true
604
605         if [ ! -z "$SCRATCH_DEV" ]; then
606           _scratch_unmount 2> /dev/null
607           # call the overridden mkfs - make sure the FS is built
608           # the same as we'll create it later.
609
610           if ! _scratch_mkfs >$tmp.err 2>&1
611           then
612               echo "our local _scratch_mkfs routine ..."
613               cat $tmp.err
614               echo "check: failed to mkfs \$SCRATCH_DEV using specified options"
615               status=1
616               exit
617           fi
618
619           # call the overridden mount - make sure the FS mounts with
620           # the same options that we'll mount with later.
621           if ! _try_scratch_mount >$tmp.err 2>&1
622           then
623               echo "our local mount routine ..."
624               cat $tmp.err
625               echo "check: failed to mount \$SCRATCH_DEV using specified options"
626               status=1
627               exit
628           fi
629         fi
630
631         seqres="$check"
632         _check_test_fs
633
634         err=false
635         first_test=true
636         prev_seq=""
637         for seq in $list ; do
638                 # Run report for previous test!
639                 if $err ; then
640                         bad="$bad $seqnum"
641                         n_bad=`expr $n_bad + 1`
642                         tc_status="fail"
643                 fi
644                 if $do_report && ! $first_test ; then
645                         if [ $tc_status != "expunge" ] ; then
646                                 _make_testcase_report "$prev_seq" "$tc_status"
647                         fi
648                 fi
649                 first_test=false
650
651                 err=false
652                 prev_seq="$seq"
653                 if [ ! -f $seq ]; then
654                         # Try to get full name in case the user supplied only
655                         # seq id and the test has a name. A bit of hassle to
656                         # find really the test and not its sample output or
657                         # helping files.
658                         bname=$(basename $seq)
659                         full_seq=$(find $(dirname $seq) -name $bname* -executable |
660                                 awk '(NR == 1 || length < length(shortest)) { shortest = $0 }\
661                                      END { print shortest }')
662                         if [ -f $full_seq ] && \
663                            [ x$(echo $bname | grep -o "^$VALID_TEST_ID") != x ]; then
664                                 seq=$full_seq
665                         fi
666                 fi
667
668                 # the filename for the test and the name output are different.
669                 # we don't include the tests/ directory in the name output.
670                 export seqnum=`echo $seq | sed -e "s;$SRC_DIR/;;"`
671
672                 # Similarly, the result directory needs to replace the tests/
673                 # part of the test location.
674                 group=`dirname $seq`
675                 if $OPTIONS_HAVE_SECTIONS; then
676                         export RESULT_DIR=`echo $group | sed -e "s;$SRC_DIR;${RESULT_BASE}/$section;"`
677                         REPORT_DIR="$RESULT_BASE/$section"
678                 else
679                         export RESULT_DIR=`echo $group | sed -e "s;$SRC_DIR;$RESULT_BASE;"`
680                         REPORT_DIR="$RESULT_BASE"
681                 fi
682                 seqres="$REPORT_DIR/$seqnum"
683
684                 mkdir -p $RESULT_DIR
685                 echo -n "$seqnum"
686
687                 if $showme; then
688                         _expunge_test $seqnum
689                         if [ $? -eq 1 ]; then
690                             tc_status="expunge"
691                             continue
692                         fi
693                         echo
694                         start=0
695                         stop=0
696                         tc_status="list"
697                         n_notrun=`expr $n_notrun + 1`
698                         continue
699                 fi
700
701                 tc_status="pass"
702                 if [ ! -f $seq ]; then
703                         echo " - no such test?"
704                         continue
705                 fi
706
707                 # really going to try and run this one
708                 rm -f $seqres.out.bad
709
710                 # check if we really should run it
711                 _expunge_test $seqnum
712                 if [ $? -eq 1 ]; then
713                         tc_status="expunge"
714                         continue
715                 fi
716
717                 # record that we really tried to run this test.
718                 try="$try $seqnum"
719                 n_try=`expr $n_try + 1`
720
721                 # slashes now in names, sed barfs on them so use grep
722                 lasttime=`grep -w ^$seqnum $check.time | awk '// {print $2}'`
723                 if [ "X$lasttime" != X ]; then
724                         echo -n " ${lasttime}s ... "
725                 else
726                         echo -n "       " # prettier output with timestamps.
727                 fi
728                 rm -f core $seqres.notrun
729
730                 start=`_wallclock`
731                 $timestamp && echo -n " ["`date "+%T"`"]"
732                 [ ! -x $seq ] && chmod u+x $seq # ensure we can run it
733                 $LOGGER_PROG "run xfstest $seqnum"
734                 if [ -w /dev/kmsg ]; then
735                         export date_time=`date +"%F %T"`
736                         echo "run fstests $seqnum at $date_time" > /dev/kmsg
737                         # _check_dmesg depends on this log in dmesg
738                         touch ${RESULT_DIR}/check_dmesg
739                 fi
740                 if [ "$DUMP_OUTPUT" = true ]; then
741                         ./$seq 2>&1 | tee $tmp.out
742                         # Because $? would get tee's return code
743                         sts=${PIPESTATUS[0]}
744                 else
745                         ./$seq >$tmp.out 2>&1
746                         sts=$?
747                 fi
748
749                 if [ -f core ]; then
750                         _dump_err_cont "[dumped core]"
751                         mv core $RESULT_BASE/$seqnum.core
752                         err=true
753                 fi
754
755                 if [ -f $seqres.notrun ]; then
756                         $timestamp && _timestamp
757                         stop=`_wallclock`
758                         $timestamp || echo -n "[not run] "
759                         $timestamp && echo " [not run]" && \
760                                       echo -n " $seqnum -- "
761                         cat $seqres.notrun
762                         notrun="$notrun $seqnum"
763                         n_notrun=`expr $n_notrun + 1`
764                         tc_status="notrun"
765                         continue;
766                 fi
767
768                 if [ $sts -ne 0 ]; then
769                         _dump_err_cont "[failed, exit status $sts]"
770                         _test_unmount 2> /dev/null
771                         _scratch_unmount 2> /dev/null
772                         err=true
773                 else
774                         # the test apparently passed, so check for corruption
775                         # and log messages that shouldn't be there.
776                         _check_filesystems
777                         _check_dmesg || err=true
778                 fi
779
780                 # Scan for memory leaks after every test so that associating
781                 # a leak to a particular test will be as accurate as possible.
782                 _check_kmemleak || err=true
783
784                 # test ends after all checks are done.
785                 $timestamp && _timestamp
786                 stop=`_wallclock`
787
788                 if [ ! -f $seq.out ]; then
789                         _dump_err "no qualified output"
790                         err=true
791                         continue;
792                 fi
793
794                 # coreutils 8.16+ changed quote formats in error messages
795                 # from `foo' to 'foo'. Filter old versions to match the new
796                 # version.
797                 sed -i "s/\`/\'/g" $tmp.out
798                 if diff $seq.out $tmp.out >/dev/null 2>&1 ; then
799                         if ! $err ; then
800                                 echo "$seqnum `expr $stop - $start`" >>$tmp.time
801                                 echo -n " `expr $stop - $start`s"
802                         fi
803                         echo ""
804                 else
805                         _dump_err "- output mismatch (see $seqres.out.bad)"
806                         mv $tmp.out $seqres.out.bad
807                         $diff $seq.out $seqres.out.bad | {
808                         if test "$DIFF_LENGTH" -le 0; then
809                                 cat
810                         else
811                                 head -n "$DIFF_LENGTH"
812                                 echo "..."
813                                 echo "(Run '$diff $here/$seq.out $seqres.out.bad'" \
814                                         " to see the entire diff)"
815                         fi; } | sed -e 's/^\(.\)/    \1/'
816                         err=true
817                 fi
818         done
819
820         # make sure we record the status of the last test we ran.
821         if $err ; then
822                 bad="$bad $seqnum"
823                 n_bad=`expr $n_bad + 1`
824                 tc_status="fail"
825         fi
826         if $do_report && ! $first_test ; then
827                 if [ $tc_status != "expunge" ] ; then
828                         _make_testcase_report "$prev_seq" "$tc_status"
829                 fi
830         fi
831
832         sect_stop=`_wallclock`
833         interrupt=false
834         _wrapup
835         interrupt=true
836         echo
837
838         _test_unmount 2> /dev/null
839         _scratch_unmount 2> /dev/null
840 done
841
842 interrupt=false
843 status=`expr $sum_bad != 0`
844 exit