build: Fix autoconf warnings
[obnox/glusterfs.git] / run-tests.sh
1 #!/bin/bash
2 # Copyright (c) 2013-2014 Red Hat, Inc. <http://www.redhat.com>
3 #
4
5 export TZ=UTC
6 function check_dependencies()
7 {
8     ## Check all dependencies are present
9     MISSING=""
10
11     # Check for dbench
12     env dbench --usage > /dev/null 2>&1
13     if [ $? -ne 0 ]; then
14         MISSING="$MISSING dbench"
15     fi
16
17     # Check for git
18     env git --version > /dev/null 2>&1
19     if [ $? -ne 0 ]; then
20         MISSING="$MISSING git"
21     fi
22
23     # Check for nfs-utils (Linux-only: built-in NetBSD with different name)
24     if [ "x`uname -s`" = "xLinux" ] ; then
25       env mount.nfs -V > /dev/null 2>&1
26       if [ $? -ne 0 ]; then
27           MISSING="$MISSING nfs-utils"
28       fi
29     fi
30
31     # Check for the Perl Test Harness
32     env prove --version > /dev/null 2>&1
33     if [ $? -ne 0 ]; then
34         MISSING="$MISSING perl-Test-Harness"
35     fi
36
37     which json_verify > /dev/null
38     if [ $? -ne 0 ]; then
39         MISSING="$MISSING json_verify"
40     fi
41
42     # Check for XFS programs (Linux Only: NetBSD does without)
43     if [ "x`uname -s`" = "xLinux" ] ; then
44       env mkfs.xfs -V > /dev/null 2>&1
45       if [ $? -ne 0 ]; then
46           MISSING="$MISSING xfsprogs"
47       fi
48     fi
49
50     # Check for attr
51     env getfattr --version > /dev/null 2>&1
52     if [ $? -ne 0 ]; then
53         MISSING="$MISSING attr"
54     fi
55
56     # Check for pidof
57     pidof pidof > /dev/null 2>&1
58     if [ $? -ne 0 ]; then
59         MISSING="$MISSING pidof"
60     fi
61
62     # check for psutil python package
63     test `uname -s` == "Darwin" || test `uname -s` == "FreeBSD" && {
64         pip show psutil | grep -q psutil >/dev/null 2>&1
65         if [ $? -ne 0 ]; then
66             MISSING="$MISSING psutil"
67         fi
68     }
69
70     ## If dependencies are missing, warn the user and abort
71     if [ "x$MISSING" != "x" ]; then
72         test "x${force}" != "xyes" && echo "Aborting."
73         echo
74         echo "The following required tools are missing:"
75         echo
76         for pkg in $MISSING; do
77             echo "  * $pkg"
78         done
79         echo
80         test "x${force}" = "xyes" && return
81         echo "Please install them and try again."
82         echo
83         exit 2
84     fi
85 }
86
87 function check_location()
88 {
89     regression_testsdir=$(dirname $0);
90
91     if [ ! -f ${regression_testsdir}/tests/include.rc ]; then
92         echo "Aborting."
93         echo
94         echo "The tests/ subdirectory seems to be missing."
95         echo
96         echo "Please correct the problem and try again."
97         echo
98         exit 1
99     fi
100 }
101
102 function check_user()
103 {
104     # If we're not running as root, warn the user and abort
105     MYUID=`/usr/bin/id -u`
106     if [ 0${MYUID} -ne 0 ]; then
107         echo "Aborting."
108         echo
109         echo "The GlusterFS Test Framework must be run as root."
110         echo
111         echo "Please change to the root user and try again."
112         echo
113         exit 3
114     fi
115 }
116
117 function run_tests()
118 {
119     declare -A DONE
120     match()
121     {
122         # Patterns considered valid:
123         # 1. full or partial file/directory names
124         #   basic         matches tests/basic
125         #   basic/afr     matches tests/basic/afr
126         # 2. globs
127         #   basic/*       matches all files and directories in basic
128         #   basic/*/      matches subdirectories in basic (afr|ec)
129         # 3. numbered bug matching
130         #   884455        matches bugs/bug-884455.t
131         #   859927        matches bugs/859927, bugs/bug-859927.t
132         #   1015990       matches /bugs/bug-1015990-rep.t, bug-1015990.t
133         # ...lots of other cases accepted as well, since globbing is tricky.
134         local t=$1
135         local mt=$1
136         shift
137         local a
138         local match=1
139         if [ -d $t ] ; then
140             # Allow matching on globs like 'basic/*/'
141             mt=$t/
142         fi
143         for a in "$@" ; do
144             case "$mt" in
145                 *$a|*/bugs/$a/|*/bugs/$a.t|*/bugs/bug-$a.t|*/bugs/bug-$a-*.t)
146                     match=0
147                     ;;
148             esac
149         done
150         if [ "${DONE[$(dirname $t)]}" != "" ] ; then
151             # Parentdir is already matched
152             match=1
153             if [ -d $t ] ; then
154                 # Ignore subdirectory as well
155                 DONE[$t]=$t
156             fi
157        elif [ $match -eq 0 -a -d $t ] ; then
158             # Make sure children of this matched directory will be ignored
159             DONE[$t]=$t
160         elif [[ -f $t && ! $t =~ .*\.t ]] ; then
161             # Ignore files not ending in .t
162             match=1
163         fi
164         return $match
165     }
166     RES=0
167     for t in $(find ${regression_testsdir}/tests | LC_COLLATE=C sort) ; do
168         if match $t "$@" ; then
169             if [ -d $t ] ; then
170                 echo "Running tests in directory $t"
171                 prove -rf --timer $t
172             elif  [ -f $t ] ; then
173                 echo "Running tests in file $t"
174                 prove -f --timer $t
175             fi
176             TMP_RES=$?
177             if [ ${TMP_RES} -ne 0 ] ; then
178                 RES=${TMP_RES}
179                 FAILED="$FAILED $t"
180             fi
181         fi
182     done
183     if [ ${RES} -ne 0 ] ; then
184         FAILED=$( echo ${FAILED} | tr ' ' '\n' | sort -u )
185         echo "Failed tests ${FAILED}"
186     fi
187     return ${RES}
188 }
189
190 # If you're submitting a fix related to one of these tests and want its result
191 # to be considered, you'll need to remove it from the list as part of your
192 # patch.
193 function is_bad_test ()
194 {
195     local name=$1
196     for bt in ./tests/basic/quota-anon-fd-nfs.t \
197               ./tests/bugs/quota/bug-1235182.t \
198               ./tests/basic/mount-nfs-auth.t \
199               ./tests/basic/quota-nfs.t \
200               ./tests/basic/tier/tier_lookup_heal.t \
201               ./tests/basic/tier/bug-1214222-directories_missing_after_attach_tier.t \
202               ./tests/bugs/snapshot/bug-1109889.t \
203               ./tests/bugs/distribute/bug-1066798.t \
204               ./tests/bugs/glusterd/bug-1238706-daemons-stop-on-peer-cleanup.t \
205               ./tests/bugs/glusterd/bug-948686.t \
206               ./tests/geo-rep/georep-basic-dr-rsync.t \
207               ./tests/geo-rep/georep-basic-dr-tarssh.t \
208               ./tests/bugs/replicate/bug-1221481-allow-fops-on-dir-split-brain.t \
209               ./tests/basic/ec/ec-readdir.t \
210               ./tests/bugs/snapshot/bug-1275616.t \
211               ; do
212         [ x"$name" = x"$bt" ] && return 0 # bash: zero means true/success
213     done
214     return 1                              # bash: non-zero means false/failure
215 }
216
217 function run_all ()
218 {
219     find ${regression_testsdir}/tests -name '*.t' \
220     | LC_COLLATE=C sort \
221     | while read t; do
222         old_cores=$(ls /core.* 2> /dev/null | wc -l)
223         retval=0
224         prove -mf --timer $t
225         TMP_RES=$?
226         if [ ${TMP_RES} -ne 0 ] ; then
227             echo "$t: bad status $TMP_RES"
228             retval=$((retval+1))
229         fi
230         new_cores=$(ls /core.* 2> /dev/null | wc -l)
231         if [ x"$new_cores" != x"$old_cores" ]; then
232             core_diff=$((new_cores-old_cores))
233             echo "$t: $core_diff new core files"
234             retval=$((retval+2))
235         fi
236         if [ $retval -ne 0 ]; then
237             if is_bad_test $t; then
238                 echo  "Ignoring failure from known-bad test $t"
239                 retval=0
240             else
241                 echo
242                 echo "Running failed test $t in debug mode"
243                 echo "Just for debug data, does not change test result"
244                 echo
245                 bash -x $t
246                 echo
247                 return $retval
248             fi
249         fi
250     done
251 }
252
253 function main()
254 {
255     if [ $# -lt 1 ]; then
256         echo "Running all the regression test cases (new way)"
257         #prove -rf --timer ${regression_testsdir}/tests;
258         run_all
259     else
260         run_tests "$@"
261     fi
262 }
263
264 function main_and_retry()
265 {
266     RESFILE=`mktemp /tmp/${0##*/}.XXXXXX` || exit 1
267     main "$@" | tee ${RESFILE}
268     RET=$?
269
270     FAILED=$( awk '/Failed: /{print $1}' ${RESFILE} )
271     if [ "x${FAILED}" != "x" ] ; then
272        echo ""
273        echo "       *********************************"
274        echo "       *       REGRESSION FAILED       *"
275        echo "       * Retrying failed tests in case *"
276        echo "       * we got some spurous failures  *"
277        echo "       *********************************"
278        echo ""
279        main ${FAILED}
280        RET=$?
281     fi
282
283     rm -f ${RESFILE}
284     return ${RET}
285 }
286
287 echo
288 echo ... GlusterFS Test Framework ...
289 echo
290
291 force="no"
292 retry="no"
293 args=`getopt fr $*`
294 set -- $args
295 while [ $# -gt 0 ]; do
296     case "$1" in
297     -f)    force="yes" ;;
298     -r)    retry="yes" ;;
299     --)    shift; break;;
300     esac
301     shift
302 done
303
304 # Make sure we're running as the root user
305 check_user
306
307 # Make sure the needed programs are available
308 check_dependencies
309
310 # Check we're running from the right location
311 check_location
312
313 # Run the tests
314 if [ "x${retry}" = "xyes" ] ; then
315     main_and_retry $@
316 else
317     main "$@"
318 fi