config: Fix setting FSTYP automatically
[xfstests-dev.git] / check
1 #!/bin/bash
2 #
3 # Control script for QA
4 #
5 # Copyright (c) 2000-2002,2006 Silicon Graphics, Inc.  All Rights Reserved.
6 #
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.
10 #
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.
15 #
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
19 #
20 #
21
22 tmp=/tmp/$$
23 status=0
24 needwrap=true
25 needsum=true
26 n_try=0
27 try=""
28 n_bad=0
29 sum_bad=0
30 bad=""
31 notrun=""
32 interrupt=true
33 diff="diff -u"
34 showme=false
35 have_test_arg=false
36 randomize=false
37 export here=`pwd`
38 xfile=""
39
40 # start the initialisation work now
41 iam=check
42
43 export MSGVERB="text:action"
44 export QA_CHECK_FS=${QA_CHECK_FS:=true}
45
46 # number of diff lines from a failed test, 0 for whole output
47 export DIFF_LENGTH=${DIFF_LENGTH:=10}
48
49 # by default don't output timestamps
50 timestamp=${TIMESTAMP:=false}
51
52 rm -f $tmp.list $tmp.tmp $tmp.grep $here/$iam.out $tmp.xlist
53
54 # we need common/config
55 if ! . ./common/config
56 then
57     echo "$iam: failed to source common/config"
58     exit 1
59 fi
60
61 SUPPORTED_TESTS="[0-9][0-9][0-9] [0-9][0-9][0-9][0-9]"
62 SRC_GROUPS="generic shared"
63 export SRC_DIR="tests"
64
65 usage()
66 {
67     echo "Usage: $0 [options] [testlist]"'
68
69 check options
70     -nfs                test NFS
71     -tmpfs              test TMPFS
72     -l                  line mode diff
73     -udiff              show unified diff (default)
74     -n                  show me, do not run tests
75     -T                  output timestamps
76     -r                  randomize test order
77     --large-fs          optimise scratch device for large filesystems
78
79 testlist options
80     -g group[,group...] include tests from these groups
81     -x group[,group...] exclude tests from these groups
82     -X file             exclude individual tests
83     [testlist]          include tests matching names in testlist
84 '
85             exit 0
86 }
87
88 get_group_list()
89 {
90         grp=$1
91
92         for d in $SRC_GROUPS $FSTYP; do
93                 l=$(sed -n < $SRC_DIR/$d/group \
94                         -e 's/#.*//' \
95                         -e 's/$/ /' \
96                         -e "s;\(^[0-9][0-9][0-9]\).* $grp .*;$SRC_DIR/$d/\1;p")
97                 grpl="$grpl $l"
98         done
99         echo $grpl
100 }
101
102 # find all tests, excluding files that are test metadata such as group files.
103 # This assumes that tests are defined purely by alphanumeric filenames with no
104 # ".xyz" extensions in the name.
105 get_all_tests()
106 {
107         touch $tmp.list
108         for d in $SRC_GROUPS $FSTYP; do
109                 ls $SRC_DIR/$d/* | \
110                         grep -v "\..*" | \
111                         grep -v "group\|Makefile" >> $tmp.list 2>/dev/null
112         done
113 }
114
115 # takes the list of tests to run in $tmp.list, and removes the tests passed to
116 # the function from that list.
117 trim_test_list()
118 {
119         test_list="$*"
120
121         rm -f $tmp.grep
122         numsed=0
123         for t in $test_list
124         do
125             if [ $numsed -gt 100 ]; then
126                 grep -v -f $tmp.grep <$tmp.list >$tmp.tmp
127                 mv $tmp.tmp $tmp.list
128                 numsed=0
129                 rm -f $tmp.grep
130             fi
131             echo "^$t\$" >>$tmp.grep
132             numsed=`expr $numsed + 1`
133         done
134         grep -v -f $tmp.grep <$tmp.list >$tmp.tmp
135         mv $tmp.tmp $tmp.list
136 }
137
138
139 _wallclock()
140 {
141     date "+%H %M %S" | $AWK_PROG '{ print $1*3600 + $2*60 + $3 }'
142 }
143
144 _timestamp()
145 {
146     now=`date "+%T"`
147     echo -n " [$now]"
148 }
149
150 _prepare_test_list()
151 {
152         unset list
153         # Tests specified on the command line
154         if [ -s $tmp.arglist ]; then
155                 cat $tmp.arglist > $tmp.list
156         else
157                 touch $tmp.list
158         fi
159
160         # Specified groups to include
161         for group in $GROUP_LIST; do
162                 list=$(get_group_list $group)
163                 if [ -z "$list" ]; then
164                         echo "Group \"$group\" is empty or not defined?"
165                         exit 1
166                 fi
167
168                 for t in $list; do
169                         grep -s "^$t\$" $tmp.list >/dev/null || \
170                                                         echo "$t" >>$tmp.list
171                 done
172         done
173
174         if ! $have_test_arg && [ -z "$GROUP_LIST" ]; then
175                 # no test numbers, do everything
176                 get_all_tests
177         fi
178
179         # Specified groups to exclude
180         for xgroup in $XGROUP_LIST; do
181                 list=$(get_group_list $xgroup)
182                 if [ -z "$list" ]; then
183                         echo "Group \"$xgroup\" is empty or not defined?"
184                         exit 1
185                 fi
186
187                 trim_test_list $list
188         done
189
190         # sort the list of tests into numeric order
191         list=`sort -n $tmp.list | uniq`
192         rm -f $tmp.list $tmp.tmp $tmp.grep
193
194         if $randomize
195         then
196                 list=`echo $list | awk -f randomize.awk`
197         fi
198 }
199
200 # Process command arguments first.
201 while [ $# -gt 0 ]; do
202         case "$1" in
203         -\? | -h | --help) usage ;;
204
205         -nfs)   FSTYP=nfs ;;
206         -tmpfs) FSTYP=tmpfs ;;
207
208         -g)     group=$2 ; shift ;
209                 GROUP_LIST="$GROUP_LIST $group"
210                 ;;
211
212         -x)     xgroup=$2 ; shift ;
213                 XGROUP_LIST="$XGROUP_LIST $xgroup"
214                 ;;
215
216         -X)     xfile=$2; shift ;
217                 for d in $SRC_GROUPS $FSTYP; do
218                         [ -f $SRC_DIR/$d/$xfile ] || continue
219                         for f in `cat $SRC_DIR/$d/$xfile`; do
220                                 echo $d/$f >> $tmp.xlist
221                         done
222                 done
223                 ;;
224
225         -l)     diff="diff" ;;
226         -udiff) diff="$diff -u" ;;
227
228         -n)     showme=true ;;
229         -r)     randomize=true ;;
230
231         -T)     timestamp=true ;;
232
233         --large-fs) export LARGE_SCRATCH_DEV=yes ;;
234         --extra-space=*) export SCRATCH_DEV_EMPTY_SPACE=${r#*=} ;;
235
236         -*)     usage ;;
237         *)      # not an argument, we've got tests now.
238                 have_test_arg=true ;;
239         esac
240
241         # if we've found a test specification, the break out of the processing
242         # loop before we shift the arguments so that this is the first argument
243         # that we process in the test arg loop below.
244         if $have_test_arg; then
245                 break;
246         fi
247
248         shift
249 done
250
251 # Process tests from command line now.
252 if $have_test_arg; then
253         while [ $# -gt 0 ]; do
254                 case "$1" in
255                 -*)     echo "Argments before tests, please!"
256                         status=1
257                         exit $status
258                         ;;
259                 *)      test_dir=`dirname $1`
260                         test_dir=${test_dir#$SRC_DIR/*}
261                         test_name=`basename $1`
262                         group_file=$SRC_DIR/$test_dir/group
263
264                         if egrep "^$test_name" $group_file >/dev/null ; then
265                                 # in group file ... OK
266                                 echo $SRC_DIR/$test_dir/$test_name >>$tmp.arglist
267                         else
268                                 # oops
269                                 echo "$1 - unknown test, ignored"
270                         fi
271                         ;;
272                 esac
273
274                 shift
275         done
276 fi
277
278 # we need common/rc
279 if ! . ./common/rc
280 then
281     echo "check: failed to source common/rc"
282     exit 1
283 fi
284
285 if [ `id -u` -ne 0 ]
286 then
287     echo "check: QA must be run as root"
288     exit 1
289 fi
290
291 _wipe_counters()
292 {
293         n_try="0"
294         n_bad="0"
295         unset try notrun bad
296 }
297
298 _wrapup()
299 {
300     seq="check"
301     check="$RESULT_BASE/check"
302
303     if $showme
304     then
305         :
306     elif $needwrap
307     then
308         if [ -f $check.time -a -f $tmp.time ]
309         then
310             cat $check.time $tmp.time \
311             | $AWK_PROG '
312         { t[$1] = $2 }
313 END     { if (NR > 0) {
314             for (i in t) print i " " t[i]
315           }
316         }' \
317             | sort -n >$tmp.out
318             mv $tmp.out $check.time
319         fi
320
321         echo "" >>$check.log
322         date >>$check.log
323         echo $list | fmt | sed -e 's/^/    /' -e "s;$SRC_DIR/;;g" >>$check.log
324         $interrupt && echo "Interrupted!" >>$check.log
325
326         echo "SECTION       -- $section" >>$tmp.summary
327         echo "=========================" >>$tmp.summary
328         if [ ! -z "$n_try" -a $n_try != 0 ]
329         then
330             echo "Ran:$try"
331             echo "Ran:$try" >>$tmp.summary
332         fi
333
334         if [ ! -z "$notrun" ]
335         then
336             echo "Not run:$notrun"
337             echo "Not run:$notrun" >>$check.log
338             echo "Not run:$notrun" >>$tmp.summary
339         fi
340
341         if [ ! -z "$n_bad" -a $n_bad != 0 ]
342         then
343             echo "Failures:$bad"
344             echo "Failed $n_bad of $n_try tests"
345             echo "Failures:$bad" | fmt >>$check.log
346             echo "Failed $n_bad of $n_try tests" >>$check.log
347             echo "Failures:$bad" >>$tmp.summary
348             echo "Failed $n_bad of $n_try tests" >>$tmp.summary
349         else
350             echo "Passed all $n_try tests"
351             echo "Passed all $n_try tests" >>$check.log
352             echo "Passed all $n_try tests" >>$tmp.summary
353         fi
354         echo "" >>$tmp.summary
355         needwrap=false
356     fi
357
358     sum_bad=`expr $sum_bad + $n_bad`
359     _wipe_counters
360     rm -f /tmp/*.rawout /tmp/*.out /tmp/*.err /tmp/*.time
361     if ! $OPTIONS_HAVE_SECTIONS; then
362         rm -f $tmp.*
363     fi
364 }
365
366 _summary()
367 {
368         _wrapup
369         if $showme; then
370                 :
371         elif $needsum; then
372                 count=`wc -L $tmp.summary | cut -f1 -d" "`
373                 cat $tmp.summary
374                 needsum=false
375         fi
376         rm -f $tmp.*
377 }
378
379 _prepare_test_list
380
381 if $OPTIONS_HAVE_SECTIONS; then
382         trap "_summary; exit \$status" 0 1 2 3 15
383 else
384         trap "_wrapup; exit \$status" 0 1 2 3 15
385 fi
386
387 for section in $HOST_OPTIONS_SECTIONS; do
388         OLD_FSTYP=$FSTYP
389         OLD_MOUNT_OPTIONS=$MOUNT_OPTIONS
390         get_next_config $section
391
392         mkdir -p $RESULT_BASE
393         if [ ! -d $RESULT_BASE ]; then
394                 echo "failed to create results directory $RESULT_BASE"
395                 exit 1;
396         fi
397
398         if $OPTIONS_HAVE_SECTIONS; then
399                 echo "SECTION       -- $section"
400         fi
401
402         if $RECREATE_TEST_DEV || [ "$OLD_FSTYP" != "$FSTYP" ]; then
403                 echo "RECREATING    -- $FSTYP on $TEST_DEV"
404                 umount $TEST_DEV 2> /dev/null
405                 if ! _test_mkfs >$tmp.err 2>&1
406                 then
407                         echo "our local _test_mkfs routine ..."
408                         cat $tmp.err
409                         echo "check: failed to mkfs \$TEST_DEV using specified options"
410                         exit 1
411                 fi
412                 out=`_mount_or_remount_rw "$MOUNT_OPTIONS" $TEST_DEV $TEST_DIR`
413                 if [ $? -ne 1 ]; then
414                         echo $out
415                         exit 1
416                 fi
417                 _prepare_test_list
418         elif [ "$OLD_MOUNT_OPTIONS" != "$MOUNT_OPTIONS" ]; then
419                 umount $TEST_DEV 2> /dev/null
420                 out=`_mount_or_remount_rw "$MOUNT_OPTIONS" $TEST_DEV $TEST_DIR`
421                 if [ $? -ne 1 ]; then
422                         echo $out
423                         exit 1
424                 fi
425         fi
426
427         init_rc
428
429         seq="check"
430         check="$RESULT_BASE/check"
431
432         # don't leave old full output behind on a clean run
433         rm -f $check.full
434
435         [ -f $check.time ] || touch $check.time
436
437         # print out our test configuration
438         echo "FSTYP         -- `_full_fstyp_details`"
439         echo "PLATFORM      -- `_full_platform_details`"
440         if [ ! -z "$SCRATCH_DEV" ]; then
441           echo "MKFS_OPTIONS  -- `_scratch_mkfs_options`"
442           echo "MOUNT_OPTIONS -- `_scratch_mount_options`"
443         fi
444         echo
445         needwrap=true
446
447         if [ ! -z "$SCRATCH_DEV" ]; then
448           umount $SCRATCH_DEV 2>/dev/null
449           # call the overridden mkfs - make sure the FS is built
450           # the same as we'll create it later.
451
452           if ! _scratch_mkfs $flag >$tmp.err 2>&1
453           then
454               echo "our local _scratch_mkfs routine ..."
455               cat $tmp.err
456               echo "check: failed to mkfs \$SCRATCH_DEV using specified options"
457               exit 1
458           fi
459
460           # call the overridden mount - make sure the FS mounts with
461           # the same options that we'll mount with later.
462           if ! _scratch_mount >$tmp.err 2>&1
463           then
464               echo "our local mount routine ..."
465               cat $tmp.err
466               echo "check: failed to mount \$SCRATCH_DEV using specified options"
467               exit 1
468           fi
469         fi
470
471         seqres="$check"
472         _check_test_fs
473
474         for seq in $list
475         do
476             err=false
477
478             # the filename for the test and the name output are different.
479             # we don't include the tests/ directory in the name output.
480             seqnum=`echo $seq | sed -e "s;$SRC_DIR/;;"`
481
482             # Similarly, the result directory needs to replace the tests/
483             # part of the test location.
484             group=`dirname $seq`
485             if $OPTIONS_HAVE_SECTIONS; then
486                 export RESULT_DIR=`echo $group | sed -e "s;$SRC_DIR;${RESULT_BASE}/$section;"`
487                 seqres="$RESULT_BASE/$section/$seqnum"
488             else
489                 export RESULT_DIR=`echo $group | sed -e "s;$SRC_DIR;$RESULT_BASE;"`
490                 seqres="$RESULT_BASE/$seqnum"
491             fi
492
493             mkdir -p $RESULT_DIR
494
495             echo -n "$seqnum"
496
497             if $showme
498             then
499                 echo
500                 continue
501             elif [ ! -f $seq ]
502             then
503                 echo " - no such test?"
504             else
505                 # really going to try and run this one
506                 #
507                 rm -f $seqres.out.bad
508
509                 # check if we really should run it
510                 if [ -s $tmp.xlist ]; then
511                         if grep $seqnum $tmp.xlist > /dev/null 2>&1 ; then
512                                 echo "       [expunged]"
513                                 continue
514                         fi
515                 fi
516
517                 # slashes now in names, sed barfs on them so use grep
518                 lasttime=`grep -w ^$seqnum $check.time | awk '// {print $2}'`
519                 if [ "X$lasttime" != X ]; then
520                         echo -n " ${lasttime}s ..."
521                 else
522                         echo -n "       "       # prettier output with timestamps.
523                 fi
524                 rm -f core $seqres.notrun
525
526                 start=`_wallclock`
527                 $timestamp && echo -n " ["`date "+%T"`"]"
528                 [ ! -x $seq ] && chmod u+x $seq # ensure we can run it
529                 $LOGGER_PROG "run xfstest $seqnum"
530                 ./$seq >$tmp.rawout 2>&1
531                 sts=$?
532                 $timestamp && _timestamp
533                 stop=`_wallclock`
534
535                 _fix_malloc <$tmp.rawout >$tmp.out
536                 rm -f $tmp.rawout
537
538                 if [ -f core ]
539                 then
540                     echo -n " [dumped core]"
541                     mv core $RESULT_BASE/$seqnum.core
542                     err=true
543                 fi
544
545                 if [ -f $seqres.notrun ]
546                 then
547                     $timestamp || echo -n " [not run] "
548                     $timestamp && echo " [not run]" && echo -n "        $seqnum -- "
549                     cat $seqres.notrun
550                     notrun="$notrun $seqnum"
551                 else
552                     if [ $sts -ne 0 ]
553                     then
554                         echo -n " [failed, exit status $sts]"
555                         err=true
556                     fi
557                     if [ ! -f $seq.out ]
558                     then
559                         echo " - no qualified output"
560                         err=true
561                     else
562
563                         # coreutils 8.16+ changed quote formats in error messages from
564                         # `foo' to 'foo'. Filter old versions to match the new version.
565                         sed -i "s/\`/\'/g" $tmp.out
566                         if diff $seq.out $tmp.out >/dev/null 2>&1
567                         then
568                             if $err
569                             then
570                                 :
571                             else
572                                 echo "$seqnum `expr $stop - $start`" >>$tmp.time
573                                 echo -n " `expr $stop - $start`s"
574                             fi
575                             echo ""
576                         else
577                             echo " - output mismatch (see $seqres.out.bad)"
578                             mv $tmp.out $seqres.out.bad
579                             $diff $seq.out $seqres.out.bad | {
580                                 if test "$DIFF_LENGTH" -le 0; then
581                                         cat
582                                 else
583                                         head -n "$DIFF_LENGTH"
584                                         echo "..."
585                                         echo "(Run '$diff $seq.out $seqres.out.bad'" \
586                                                 " to see the entire diff)"
587                                 fi; } | \
588                                 sed -e 's/^\(.\)/    \1/'
589                             err=true
590                         fi
591                     fi
592                 fi
593
594             fi
595
596             # come here for each test, except when $showme is true
597             #
598             if $err
599             then
600                 bad="$bad $seqnum"
601                 n_bad=`expr $n_bad + 1`
602                 quick=false
603             fi
604             if [ ! -f $seqres.notrun ]
605             then
606                 try="$try $seqnum"
607                 n_try=`expr $n_try + 1`
608                 _check_test_fs
609             fi
610
611             seq="after_$seqnum"
612         done
613         _wrapup
614         echo
615
616         umount $TEST_DEV 2> /dev/null
617         umount $SCRATCH_DEV 2> /dev/null
618 done
619
620 interrupt=false
621 status=`expr $sum_bad`
622 exit