dht: loc should store proper gfid
[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/quota-nfs.t \
199               ./tests/basic/tier/tier_lookup_heal.t \
200               ./tests/basic/tier/bug-1214222-directories_missing_after_attach_tier.t \
201               ./tests/basic/tier/record-metadata-heat.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               ; do
210         [ x"$name" = x"$bt" ] && return 0 # bash: zero means true/success
211     done
212     return 1                              # bash: non-zero means false/failure
213 }
214
215 function run_all ()
216 {
217     find ${regression_testsdir}/tests -name '*.t' \
218     | LC_COLLATE=C sort \
219     | while read t; do
220         old_cores=$(ls /core.* 2> /dev/null | wc -l)
221         retval=0
222         prove -mf --timer $t
223         TMP_RES=$?
224         if [ ${TMP_RES} -ne 0 ] ; then
225             echo "$t: bad status $TMP_RES"
226             retval=$((retval+1))
227         fi
228         new_cores=$(ls /core.* 2> /dev/null | wc -l)
229         if [ x"$new_cores" != x"$old_cores" ]; then
230             core_diff=$((new_cores-old_cores))
231             echo "$t: $core_diff new core files"
232             retval=$((retval+2))
233         fi
234         if [ $retval -ne 0 ]; then
235             if is_bad_test $t; then
236                 echo  "Ignoring failure from known-bad test $t"
237                 retval=0
238             else
239                 echo
240                 echo "Running failed test $t in debug mode"
241                 echo "Just for debug data, does not change test result"
242                 echo
243                 bash -x $t
244                 echo
245                 return $retval
246             fi
247         fi
248     done
249 }
250
251 function main()
252 {
253     if [ $# -lt 1 ]; then
254         echo "Running all the regression test cases (new way)"
255         #prove -rf --timer ${regression_testsdir}/tests;
256         run_all
257     else
258         run_tests "$@"
259     fi
260 }
261
262 function main_and_retry()
263 {
264     RESFILE=`mktemp /tmp/${0##*/}.XXXXXX` || exit 1
265     main "$@" | tee ${RESFILE}
266     RET=$?
267
268     FAILED=$( awk '/Failed: /{print $1}' ${RESFILE} )
269     if [ "x${FAILED}" != "x" ] ; then
270        echo ""
271        echo "       *********************************"
272        echo "       *       REGRESSION FAILED       *"
273        echo "       * Retrying failed tests in case *"
274        echo "       * we got some spurous failures  *"
275        echo "       *********************************"
276        echo ""
277        main ${FAILED}
278        RET=$?
279     fi
280
281     rm -f ${RESFILE}
282     return ${RET}
283 }
284
285 echo
286 echo ... GlusterFS Test Framework ...
287 echo
288
289 force="no"
290 retry="no"
291 args=`getopt fr $*`
292 set -- $args
293 while [ $# -gt 0 ]; do
294     case "$1" in
295     -f)    force="yes" ;;
296     -r)    retry="yes" ;;
297     --)    shift; break;;
298     esac
299     shift
300 done
301
302 # Make sure we're running as the root user
303 check_user
304
305 # Make sure the needed programs are available
306 check_dependencies
307
308 # Check we're running from the right location
309 check_location
310
311 # Run the tests
312 if [ "x${retry}" = "xyes" ] ; then
313     main_and_retry $@
314 else
315     main "$@"
316 fi