2013-08-21 00:50:41 -07:00
#!/bin/bash
2014-03-06 16:53:50 +00:00
# Copyright (c) 2013-2014 Red Hat, Inc. <http://www.redhat.com>
2013-08-21 00:50:41 -07:00
#
2014-05-20 19:18:31 +05:30
export TZ = UTC
2016-02-01 12:29:40 +05:30
force = "no"
2016-03-10 10:50:59 -05:00
head = "yes"
2016-12-08 16:24:15 -05:00
retry = "yes"
2016-02-01 12:29:40 +05:30
tests = ""
2016-02-04 14:32:12 +05:30
exit_on_failure = "yes"
2016-02-08 12:13:54 +05:30
skip_bad_tests = "yes"
skip_known_bugs = "yes"
section_separator = "========================================"
2018-01-18 23:24:04 +05:30
run_timeout = 200
kill_after_time = 5
2016-02-01 12:29:40 +05:30
2016-02-28 16:34:50 +05:30
OSTYPE = $( uname -s)
2014-03-06 16:53:50 +00:00
function check_dependencies( )
{
## Check all dependencies are present
MISSING = ""
# Check for dbench
2014-08-08 01:56:23 -07:00
env dbench --usage > /dev/null 2>& 1
if [ $? -ne 0 ] ; then
2014-03-06 16:53:50 +00:00
MISSING = " $MISSING dbench "
fi
# Check for git
env git --version > /dev/null 2>& 1
if [ $? -ne 0 ] ; then
MISSING = " $MISSING git "
fi
2014-10-09 09:08:57 +02:00
# Check for nfs-utils (Linux-only: built-in NetBSD with different name)
if [ "x`uname -s`" = "xLinux" ] ; then
env mount.nfs -V > /dev/null 2>& 1
if [ $? -ne 0 ] ; then
MISSING = " $MISSING nfs-utils "
fi
2014-03-06 16:53:50 +00:00
fi
# Check for the Perl Test Harness
env prove --version > /dev/null 2>& 1
if [ $? -ne 0 ] ; then
MISSING = " $MISSING perl-Test-Harness "
fi
2014-08-08 01:56:23 -07:00
which json_verify > /dev/null
if [ $? -ne 0 ] ; then
MISSING = " $MISSING json_verify "
2014-06-13 03:33:51 +01:00
fi
2014-10-09 09:08:57 +02:00
# Check for XFS programs (Linux Only: NetBSD does without)
if [ "x`uname -s`" = "xLinux" ] ; then
env mkfs.xfs -V > /dev/null 2>& 1
if [ $? -ne 0 ] ; then
MISSING = " $MISSING xfsprogs "
fi
2014-03-06 16:53:50 +00:00
fi
# Check for attr
env getfattr --version > /dev/null 2>& 1
if [ $? -ne 0 ] ; then
MISSING = " $MISSING attr "
fi
2014-07-29 02:32:14 +02:00
# Check for pidof
2014-09-04 19:30:48 +05:30
pidof pidof > /dev/null 2>& 1
2014-07-29 02:32:14 +02:00
if [ $? -ne 0 ] ; then
MISSING = " $MISSING pidof "
fi
2014-08-19 16:14:03 -07:00
# check for psutil python package
test ` uname -s` = = "Darwin" || test ` uname -s` = = "FreeBSD" && {
pip show psutil | grep -q psutil >/dev/null 2>& 1
if [ $? -ne 0 ] ; then
MISSING = " $MISSING psutil "
fi
}
2014-03-06 16:53:50 +00:00
## If dependencies are missing, warn the user and abort
if [ " x $MISSING " != "x" ] ; then
2014-07-29 02:32:14 +02:00
test " x ${ force } " != "xyes" && echo "Aborting."
2014-03-06 16:53:50 +00:00
echo
echo "The following required tools are missing:"
echo
for pkg in $MISSING ; do
echo " * $pkg "
done
echo
2014-07-29 02:32:14 +02:00
test " x ${ force } " = "xyes" && return
2014-03-06 16:53:50 +00:00
echo "Please install them and try again."
echo
exit 2
fi
}
function check_location( )
2013-08-21 00:50:41 -07:00
{
2013-09-15 19:56:25 -07:00
regression_testsdir = $( dirname $0 ) ;
2013-08-21 00:50:41 -07:00
if [ ! -f ${ regression_testsdir } /tests/include.rc ] ; then
2014-03-06 16:53:50 +00:00
echo "Aborting."
echo
echo "The tests/ subdirectory seems to be missing."
echo
echo "Please correct the problem and try again."
echo
2013-08-21 00:50:41 -07:00
exit 1
fi
}
2014-03-06 16:53:50 +00:00
function check_user( )
{
# If we're not running as root, warn the user and abort
MYUID = ` /usr/bin/id -u`
if [ 0${ MYUID } -ne 0 ] ; then
echo "Aborting."
echo
echo "The GlusterFS Test Framework must be run as root."
echo
echo "Please change to the root user and try again."
echo
exit 3
fi
}
2016-02-02 18:14:24 +05:30
function match( )
2014-07-10 20:17:25 +02:00
{
# Patterns considered valid:
2016-02-02 18:14:24 +05:30
# 0. Empty means everything
# "" matches ** i.e all
2014-07-10 20:17:25 +02:00
# 1. full or partial file/directory names
# basic matches tests/basic
# basic/afr matches tests/basic/afr
# 2. globs
# basic/* matches all files and directories in basic
# basic/*/ matches subdirectories in basic (afr|ec)
# 3. numbered bug matching
# 884455 matches bugs/bug-884455.t
# 859927 matches bugs/859927, bugs/bug-859927.t
# 1015990 matches /bugs/bug-1015990-rep.t, bug-1015990.t
# ...lots of other cases accepted as well, since globbing is tricky.
local t = $1
shift
local a
local match = 1
2016-02-02 18:14:24 +05:30
if [ -z " $@ " ] ; then
match = 0
return $match
2014-07-10 20:17:25 +02:00
fi
2016-02-02 18:14:24 +05:30
for a in $@ ; do
case " $t " in
*$a *)
2014-07-10 20:17:25 +02:00
match = 0
; ;
esac
done
return $match
2016-02-02 18:14:24 +05:30
}
2016-02-08 12:13:54 +05:30
# Tests can have comment lines with some comma separated values within them.
# Key names used to determine test status are
# G_TESTDEF_TEST_STATUS_CENTOS6
# G_TESTDEF_TEST_STATUS_NETBSD7
# Some examples:
# G_TESTDEF_TEST_STATUS_CENTOS6=BAD_TEST,BUG=123456
# G_TESTDEF_TEST_STATUS_NETBSD7=KNOWN_ISSUE,BUG=4444444
# G_TESTDEF_TEST_STATUS_CENTOS6=BAD_TEST,BUG=123456;555555
# You can change status of test to enabled or delete the line only if all the
# bugs are closed or modified or if the patch fixes it.
function get_test_status ( )
2015-04-07 15:32:18 -04:00
{
2016-02-08 12:13:54 +05:30
local test_name = $1
local host_os = ""
local result = ""
host_os = $( uname -s)
case " $host_os " in
# Leaving out the logic to determine the particular distro and version
# for later. Why does the key have the distro and version then?
# Because changing the key in all test files would be very big process
# updating just this function with a better logic much simpler.
Linux)
result = $( grep -e "^#G_TESTDEF_TEST_STATUS_CENTOS6" $test_name | \
awk -F"," { 'print $1' } | awk -F"=" { 'print $2' } ) ; ;
NetBSD)
result = $( grep -e "^#G_TESTDEF_TEST_STATUS_NETBSD7" $test_name | \
awk -F"," { 'print $1' } | awk -F"=" { 'print $2' } ) ; ;
*)
result = "ENABLED" ; ;
esac
echo " $result "
2016-02-28 16:34:50 +05:30
}
2016-02-08 12:13:54 +05:30
function get_bug_list_for_disabled_test ( )
2016-02-28 16:34:50 +05:30
{
2016-02-08 12:13:54 +05:30
local test_name = $1
local host_os = ""
local result = ""
host_os = $( uname -s)
case " $host_os " in
# Leaving out the logic to determine the particular distro and version
# for later. Why does the key have the distro and version then?
# Because changing the key in all test files would be very big process
# updating just this function with a better logic much simpler.
Linux)
result = $( grep -e "^#G_TESTDEF_TEST_STATUS_CENTOS6" $test_name | \
awk -F"," { 'print $2' } | awk -F"=" { 'print $2' } ) ; ;
NetBSD)
result = $( grep -e "^#G_TESTDEF_TEST_STATUS_NETBSD7" $test_name | \
awk -F"," { 'print $2' } | awk -F"=" { 'print $2' } ) ; ;
*)
result = "0000000" ; ;
esac
echo " $result "
2016-02-28 16:34:50 +05:30
2015-04-15 22:58:59 -04:00
}
2015-04-07 15:32:18 -04:00
2016-02-02 19:12:41 +05:30
function run_tests( )
2015-04-15 22:58:59 -04:00
{
2016-02-02 19:12:41 +05:30
RES = 0
FAILED = ''
2018-01-18 23:24:04 +05:30
TESTS_NEEDED_RETRY = ''
2016-02-02 19:12:41 +05:30
GENERATED_CORE = ''
2016-02-08 12:13:54 +05:30
total_tests = 0
selected_tests = 0
skipped_bad_tests = 0
skipped_known_issue_tests = 0
total_run_tests = 0
2016-02-02 19:12:41 +05:30
2016-02-11 18:54:41 +05:30
# key = path of .t file; value = time taken to run the .t file
declare -A ELAPSEDTIMEMAP
2018-01-18 23:24:04 +05:30
# Test if -k is supported for timeout command
# This is not supported on centos6, but spuported on centos7
# The flags is required for running the command in both flavors
timeout_cmd_exists = "yes"
timeout -k 1 10 echo "testing 'timeout' command"
if [ $? -ne 0 ] ; then
timeout_cmd_exists = "no"
fi
2016-02-02 19:12:41 +05:30
for t in $( find ${ regression_testsdir } /tests -name '*.t' \
| LC_COLLATE = C sort) ; do
2016-04-06 15:47:46 -04:00
old_cores = $( ls /*-*.core 2> /dev/null | wc -l)
2016-02-08 12:13:54 +05:30
total_tests = $(( total_tests+1))
2016-02-02 19:12:41 +05:30
if match $t " $@ " ; then
2016-02-08 12:13:54 +05:30
selected_tests = $(( selected_tests+1))
2016-02-04 18:18:15 +05:30
echo
2016-02-08 12:13:54 +05:30
echo $section_separator $section_separator
if [ [ $( get_test_status $t ) = = "BAD_TEST" ] ] && \
[ [ $skip_bad_tests = = "yes" ] ]
then
skipped_bad_tests = $(( skipped_bad_tests+1))
2016-02-02 19:12:41 +05:30
echo " Skipping bad test file $t "
2016-02-08 12:13:54 +05:30
echo "Reason: bug(s):" $( get_bug_list_for_disabled_test $t )
echo $section_separator $section_separator
2016-02-04 18:18:15 +05:30
echo
2016-02-02 19:12:41 +05:30
continue
fi
2016-02-08 12:13:54 +05:30
if [ [ $( get_test_status $t ) = = "KNOWN_ISSUE" ] ] && \
[ [ $skip_known_bugs = = "yes" ] ]
then
skipped_known_issue_tests = $(( skipped_known_issue_tests+1))
echo " Skipping test file $t due to known issue "
echo "Reason: bug(s):" $( get_bug_list_for_disabled_test $t )
echo $section_separator $section_separator
2016-02-28 16:34:50 +05:30
echo
continue
fi
2016-02-08 12:13:54 +05:30
total_run_tests = $(( total_run_tests+1))
echo " [ $( date +%H:%M:%S) ] Running tests in file $t "
2016-02-11 18:54:41 +05:30
starttime = " $( date +%s) "
2018-01-18 23:24:04 +05:30
local cmd_timeout = $run_timeout ;
if [ ${ timeout_cmd_exists } = = "yes" ] ; then
if [ $( grep -c "SCRIPT_TIMEOUT=" ${ t } ) = = 1 ] ; then
cmd_timeout = $( grep "SCRIPT_TIMEOUT=" ${ t } | cut -f2 -d'=' ) ;
echo " Timeout set is ${ cmd_timeout } , default ${ run_timeout } "
fi
timeout -k ${ kill_after_time } ${ cmd_timeout } prove -vmfe '/bin/bash' ${ t }
else
prove -vmfe '/bin/bash' ${ t }
fi
2016-02-02 19:12:41 +05:30
TMP_RES = $?
2016-02-11 18:54:41 +05:30
ELAPSEDTIMEMAP[ $t ] = ` expr $( date +%s) - $starttime `
2018-01-18 23:24:04 +05:30
# timeout always return 124 if it is actually a timeout.
if ( ( ${ TMP_RES } = = 124) ) ; then
echo " ${ t } timed out after ${ cmd_timeout } seconds "
fi
2017-12-06 20:16:09 +05:30
if [ ${ TMP_RES } -ne 0 ] && [ " x ${ retry } " = "xyes" ] ; then
echo " $t : bad status $TMP_RES "
echo ""
echo " *********************************"
echo " * REGRESSION FAILED *"
echo " * Retrying failed tests in case *"
echo " * we got some spurious failures *"
echo " *********************************"
echo ""
2018-01-18 23:24:04 +05:30
if [ ${ timeout_cmd_exists } = = "yes" ] ; then
timeout -k ${ kill_after_time } ${ cmd_timeout } prove -vmfe '/bin/bash' ${ t }
else
prove -vmfe '/bin/bash' ${ t }
fi
2017-12-06 20:16:09 +05:30
TMP_RES = $?
2018-01-18 23:24:04 +05:30
if ( ( ${ TMP_RES } = = 124) ) ; then
echo " ${ t } timed out after ${ cmd_timeout } seconds "
fi
TESTS_NEEDED_RETRY = " ${ TESTS_NEEDED_RETRY } ${ t } "
2017-12-06 20:16:09 +05:30
fi
2016-02-02 19:12:41 +05:30
if [ ${ TMP_RES } -ne 0 ] ; then
RES = ${ TMP_RES }
FAILED = " ${ FAILED } ${ t } "
fi
2018-01-18 23:24:04 +05:30
2016-04-06 15:47:46 -04:00
new_cores = $( ls /*-*.core 2> /dev/null | wc -l)
2016-02-02 19:12:41 +05:30
if [ x" $new_cores " != x" $old_cores " ] ; then
core_diff = $(( new_cores-old_cores))
echo " $t : $core_diff new core files "
RES = 1
GENERATED_CORE = " ${ GENERATED_CORE } ${ t } "
fi
2016-02-04 18:18:15 +05:30
echo " End of test $t "
2016-02-08 12:13:54 +05:30
echo $section_separator $section_separator
2016-02-04 18:18:15 +05:30
echo
2016-02-04 14:32:12 +05:30
if [ $RES -ne 0 ] && [ x" $exit_on_failure " = "xyes" ] ; then
break;
fi
2015-04-07 15:32:18 -04:00
fi
done
2016-02-04 18:18:15 +05:30
echo
echo "Run complete"
2016-02-08 12:13:54 +05:30
echo $section_separator $section_separator
echo " Number of tests found: $total_tests "
echo " Number of tests selected for run based on pattern: $selected_tests "
echo " Number of tests skipped as they were marked bad: $skipped_bad_tests "
echo " Number of tests skipped because of known_issues: $skipped_known_issue_tests "
echo " Number of tests that were run: $total_run_tests "
2016-02-11 18:54:41 +05:30
2016-02-08 12:13:54 +05:30
echo
echo "Tests ordered by time taken, slowest to fastest: "
echo $section_separator $section_separator
2016-02-11 18:54:41 +05:30
for key in " ${ !ELAPSEDTIMEMAP[@] } "
do
2016-02-08 12:13:54 +05:30
echo " $key - ${ ELAPSEDTIMEMAP [ " $key " ] } second "
done | sort -rn -k3
2016-02-11 18:54:41 +05:30
2017-07-18 15:47:13 +05:30
if [ ${ RES } -ne 0 ] ; then
FAILED = $( echo ${ FAILED } | tr ' ' '\n' | sort -u )
FAILED_COUNT = $( echo -n " ${ FAILED } " | grep -c '^' )
echo -e " \n $FAILED_COUNT test(s) failed \n ${ FAILED } "
GENERATED_CORE = $( echo ${ GENERATED_CORE } | tr ' ' '\n' | sort -u )
GENERATED_CORE_COUNT = $( echo -n " ${ GENERATED_CORE } " | grep -c '^' )
echo -e " \n $GENERATED_CORE_COUNT test(s) generated core \n ${ GENERATED_CORE } "
fi
2018-01-18 23:24:04 +05:30
TESTS_NEEDED_RETRY = $( echo ${ TESTS_NEEDED_RETRY } | tr ' ' '\n' | sort -u )
RETRY_COUNT = $( echo -n " ${ TESTS_NEEDED_RETRY } " | grep -c '^' )
if [ ${ RETRY_COUNT } -ne 0 ] ; then
echo -e " \n ${ RETRY_COUNT } test(s) needed retry \n ${ TESTS_NEEDED_RETRY } "
fi
2017-07-18 15:47:13 +05:30
2016-02-08 12:13:54 +05:30
echo
2016-02-04 18:18:15 +05:30
echo " Result is $RES "
2016-02-08 12:13:54 +05:30
echo
2016-02-02 19:12:41 +05:30
return ${ RES }
2015-04-07 15:32:18 -04:00
}
2016-03-10 10:50:59 -05:00
function run_head_tests( )
{
2016-03-11 16:20:01 -05:00
[ -d ${ regression_testsdir } /.git ] || return 0
2016-03-10 10:50:59 -05:00
# The git command needs $cwd to be within the repository, but run_tests
# needs it to be back where we started.
pushd $regression_testsdir
2016-03-11 16:20:01 -05:00
git_cmd = "git diff-tree --no-commit-id --name-only --diff-filter=ACMRTUXB"
htests = $( $git_cmd -r HEAD tests | grep '.t$' )
2016-03-10 10:50:59 -05:00
popd
2016-03-11 16:20:01 -05:00
[ -n " $htests " ] || return 0
2016-03-10 10:50:59 -05:00
# Perhaps it's not ideal that we'll end up re-running these tests, but the
# gains from letting them fail fast in the first round should outweigh the
# losses from running them again in the second. OTOH, with so many of our
# tests being non-deterministic, maybe it doesn't hurt to give the newest
# tests an extra workout.
run_tests " $htests "
}
2016-02-01 12:29:40 +05:30
function parse_args ( ) {
2016-03-10 10:50:59 -05:00
args = ` getopt frcbkhH " $@ " `
2016-02-01 12:29:40 +05:30
set -- $args
while [ $# -gt 0 ] ; do
case " $1 " in
-f) force = "yes" ; ;
2016-03-10 10:50:59 -05:00
-h) head = "no" ; ;
-H) head = "only" ; ;
2016-02-01 12:29:40 +05:30
-r) retry = "yes" ; ;
2016-02-04 14:32:12 +05:30
-c) exit_on_failure = "no" ; ;
2016-02-08 12:13:54 +05:30
-b) skip_bad_tests = "no" ; ;
-k) skip_known_bugs = "no" ; ;
2016-02-01 12:29:40 +05:30
--) shift; break; ;
esac
shift
done
tests = " $@ "
}
2014-03-06 16:53:50 +00:00
echo
echo ... GlusterFS Test Framework ...
echo
2016-02-01 12:29:40 +05:30
# Get user options
2016-02-02 19:24:07 +05:30
parse_args " $@ "
2014-07-29 02:32:14 +02:00
2014-03-06 16:53:50 +00:00
# Make sure we're running as the root user
check_user
# Make sure the needed programs are available
check_dependencies
# Check we're running from the right location
check_location
# Run the tests
2016-03-10 10:50:59 -05:00
if [ x" $head " != x"no" ] ; then
run_head_tests || exit 1
fi
if [ x" $head " != x"only" ] ; then
run_tests " $tests " || exit 1
fi