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