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