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