mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
787662604d
Implement this for local daemons integration tests, dumping last 100 lines of logs. This makes it possible to debug some failures in automated tests where the logs are unavailable for analysis. Signed-off-by: Martin Schwenke <martin@meltin.net> Reviewed-by: Amitay Isaacs <amitay@gmail.com>
392 lines
8.4 KiB
Bash
Executable File
392 lines
8.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
usage() {
|
|
cat <<EOF
|
|
Usage: $0 [OPTIONS] [TESTS]
|
|
|
|
Options:
|
|
-A Use "cat -A" to print test output (only some tests)
|
|
-c Run integration tests on a cluster
|
|
-C Clean up when done by removing test state directory (see -V)
|
|
-D Show diff between failed/expected test output (some tests only)
|
|
-e Exit on the first test failure
|
|
-H No headers - for running single test with other wrapper
|
|
-I <count> Iterate tests <count> times, exiting on failure (implies -e, -N)
|
|
-L Print daemon logs on test failure (only some tests)
|
|
-N Don't print summary of tests results after running all tests
|
|
-q Quiet - don't show tests being run (still displays summary)
|
|
-S <lib> Use socket wrapper library <lib> for local integration tests
|
|
-v Verbose - print test output for non-failures (only some tests)
|
|
-V <dir> Use <dir> as test state directory
|
|
-x Trace this script with the -x option
|
|
-X Trace certain scripts run by tests using -x (only some tests)
|
|
EOF
|
|
exit 1
|
|
}
|
|
|
|
# Print a message and exit.
|
|
die ()
|
|
{
|
|
echo "$1" >&2 ; exit "${2:-1}"
|
|
}
|
|
|
|
######################################################################
|
|
|
|
with_summary=true
|
|
quiet=false
|
|
exit_on_fail=false
|
|
max_iterations=1
|
|
no_header=false
|
|
test_state_dir=""
|
|
cleanup=false
|
|
test_time_limit=3600
|
|
|
|
export TEST_VERBOSE=false
|
|
export TEST_COMMAND_TRACE=false
|
|
export TEST_CAT_RESULTS_OPTS=""
|
|
export TEST_DIFF_RESULTS=false
|
|
export CTDB_TEST_PRINT_LOGS_ON_ERROR=false
|
|
export TEST_LOCAL_DAEMONS
|
|
[ -n "$TEST_LOCAL_DAEMONS" ] || TEST_LOCAL_DAEMONS=3
|
|
export TEST_SOCKET_WRAPPER_SO_PATH=""
|
|
|
|
while getopts "AcCDehHI:LNqS:T:vV:xX?" opt ; do
|
|
case "$opt" in
|
|
A) TEST_CAT_RESULTS_OPTS="-A" ;;
|
|
c) TEST_LOCAL_DAEMONS="" ;;
|
|
C) cleanup=true ;;
|
|
D) TEST_DIFF_RESULTS=true ;;
|
|
e) exit_on_fail=true ;;
|
|
H) no_header=true ;;
|
|
I) max_iterations="$OPTARG" ; exit_on_fail=true ; with_summary=false ;;
|
|
L) CTDB_TEST_PRINT_LOGS_ON_ERROR=true ;;
|
|
N) with_summary=false ;;
|
|
q) quiet=true ;;
|
|
S) TEST_SOCKET_WRAPPER_SO_PATH="$OPTARG" ;;
|
|
T) test_time_limit="$OPTARG" ;;
|
|
v) TEST_VERBOSE=true ;;
|
|
V) test_state_dir="$OPTARG" ;;
|
|
x) set -x ;;
|
|
X) TEST_COMMAND_TRACE=true ;;
|
|
\?|h) usage ;;
|
|
esac
|
|
done
|
|
shift $((OPTIND - 1))
|
|
|
|
case $(basename "$0") in
|
|
*run_cluster_tests*)
|
|
# Running on a cluster... same as -c
|
|
TEST_LOCAL_DAEMONS=""
|
|
;;
|
|
esac
|
|
|
|
if $quiet ; then
|
|
show_progress() { cat >/dev/null ; }
|
|
else
|
|
show_progress() { cat ; }
|
|
fi
|
|
|
|
######################################################################
|
|
|
|
test_header ()
|
|
{
|
|
local name="$1"
|
|
|
|
echo "--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--"
|
|
echo "Running test $name ($(date '+%T'))"
|
|
echo "--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--==--"
|
|
}
|
|
|
|
test_footer ()
|
|
{
|
|
local f="$1"
|
|
local status="$2"
|
|
local interp="$3"
|
|
local duration="$4"
|
|
|
|
local statstr=""
|
|
if [ "$status" -eq 0 ] ; then
|
|
statstr=""
|
|
else
|
|
statstr=" (status $status)"
|
|
fi
|
|
|
|
echo "=========================================================================="
|
|
echo "TEST ${interp}: ${f}${statstr} (duration: ${duration}s)"
|
|
echo "=========================================================================="
|
|
}
|
|
|
|
ctdb_test_run ()
|
|
{
|
|
local f="$1"
|
|
|
|
$no_header || test_header "$f"
|
|
|
|
local status=0
|
|
local start_time
|
|
|
|
start_time=$(date '+%s')
|
|
|
|
if [ -x "$f" ] ; then
|
|
timeout "$test_time_limit" "$f" | show_progress
|
|
status=$?
|
|
else
|
|
echo "TEST IS NOT EXECUTABLE"
|
|
status=99
|
|
fi
|
|
|
|
local duration=$(($(date +%s) - start_time))
|
|
|
|
tests_total=$((tests_total + 1))
|
|
|
|
local interp
|
|
case "$status" in
|
|
0)
|
|
interp="PASSED"
|
|
tests_passed=$((tests_passed + 1))
|
|
;;
|
|
77)
|
|
interp="SKIPPED"
|
|
tests_skipped=$((tests_skipped + 1))
|
|
;;
|
|
99)
|
|
interp="ERROR"
|
|
tests_failed=$((tests_failed + 1))
|
|
;;
|
|
124)
|
|
interp="TIMEDOUT"
|
|
tests_failed=$((tests_failed + 1))
|
|
;;
|
|
*)
|
|
interp="FAILED"
|
|
tests_failed=$((tests_failed + 1))
|
|
;;
|
|
esac
|
|
|
|
$no_header || test_footer "$f" "$status" "$interp" "$duration"
|
|
|
|
if $with_summary ; then
|
|
local t
|
|
if [ $status -eq 0 ] ; then
|
|
t=" ${interp}"
|
|
else
|
|
t="*${interp}*"
|
|
fi
|
|
printf '%-10s %s\n' "$t" "$f" >>"$summary_file"
|
|
fi
|
|
|
|
return $status
|
|
}
|
|
|
|
######################################################################
|
|
|
|
tests_total=0
|
|
tests_passed=0
|
|
tests_skipped=0
|
|
tests_failed=0
|
|
|
|
if ! type mktemp >/dev/null 2>&1 ; then
|
|
# Not perfect, but it will do...
|
|
mktemp ()
|
|
{
|
|
local dir=false
|
|
if [ "$1" = "-d" ] ; then
|
|
dir=true
|
|
fi
|
|
local t="${TMPDIR:-/tmp}/tmp.$$.$RANDOM"
|
|
(
|
|
umask 077
|
|
if $dir ; then
|
|
mkdir "$t"
|
|
else
|
|
: >"$t"
|
|
fi
|
|
)
|
|
echo "$t"
|
|
}
|
|
fi
|
|
|
|
set -o pipefail
|
|
|
|
run_one_test ()
|
|
{
|
|
local f="$1"
|
|
|
|
CTDB_TEST_SUITE_DIR=$(dirname "$f")
|
|
export CTDB_TEST_SUITE_DIR
|
|
# This expands the most probable problem cases like "." and "..".
|
|
if [ "$(dirname "$CTDB_TEST_SUITE_DIR")" = "." ] ; then
|
|
CTDB_TEST_SUITE_DIR=$(cd "$CTDB_TEST_SUITE_DIR" && pwd)
|
|
fi
|
|
|
|
# Set CTDB_TEST_TMP_DIR
|
|
#
|
|
# Determine the relative test suite subdirectory. The top-level
|
|
# test directory needs to be a prefix of the test suite directory,
|
|
# so make absolute versions of both.
|
|
local test_dir test_suite_dir reldir
|
|
test_dir=$(cd "$CTDB_TEST_DIR" && pwd)
|
|
test_suite_dir=$(cd "$CTDB_TEST_SUITE_DIR" && pwd)
|
|
reldir="${test_suite_dir#${test_dir}/}"
|
|
|
|
export CTDB_TEST_TMP_DIR="${test_state_dir}/${reldir}"
|
|
rm -rf "$CTDB_TEST_TMP_DIR"
|
|
mkdir -p "$CTDB_TEST_TMP_DIR"
|
|
|
|
ctdb_test_run "$f"
|
|
status=$?
|
|
}
|
|
|
|
run_tests ()
|
|
{
|
|
local f
|
|
|
|
for f ; do
|
|
case "$f" in
|
|
*/README|*/README.md)
|
|
continue
|
|
;;
|
|
esac
|
|
|
|
if [ ! -e "$f" ] ; then
|
|
# Can't find it? Check relative to CTDB_TEST_DIR.
|
|
# Strip off current directory from beginning,
|
|
# if there, just to make paths more friendly.
|
|
f="${CTDB_TEST_DIR#${PWD}/}/${f}"
|
|
fi
|
|
|
|
if [ -d "$f" ] ; then
|
|
local test_dir dir reldir subtests
|
|
|
|
test_dir=$(cd "$CTDB_TEST_DIR" && pwd)
|
|
dir=$(cd "$f" && pwd)
|
|
reldir="${dir#${test_dir}/}"
|
|
|
|
case "$reldir" in
|
|
*/*/*)
|
|
die "test \"$f\" is not recognised"
|
|
;;
|
|
*/*)
|
|
# This is a test suite
|
|
subtests=$(echo "${f%/}/"*".sh")
|
|
if [ "$subtests" = "${f%/}/*.sh" ] ; then
|
|
# Probably empty directory
|
|
die "test \"$f\" is not recognised"
|
|
fi
|
|
;;
|
|
CLUSTER|INTEGRATION|UNIT)
|
|
# A collection of test suites
|
|
subtests=$(echo "${f%/}/"*)
|
|
;;
|
|
*)
|
|
die "test \"$f\" is not recognised"
|
|
esac
|
|
|
|
# Recurse - word-splitting wanted
|
|
# shellcheck disable=SC2086
|
|
run_tests $subtests
|
|
elif [ -f "$f" ] ; then
|
|
run_one_test "$f"
|
|
else
|
|
# Time to give up
|
|
die "test \"$f\" is not recognised"
|
|
fi
|
|
|
|
if $exit_on_fail && [ $status -ne 0 ] ; then
|
|
return $status
|
|
fi
|
|
done
|
|
}
|
|
|
|
export CTDB_TEST_MODE="yes"
|
|
|
|
# Following 2 lines may be modified by installation script
|
|
CTDB_TESTS_ARE_INSTALLED=false
|
|
CTDB_TEST_DIR=$(dirname "$0")
|
|
export CTDB_TESTS_ARE_INSTALLED CTDB_TEST_DIR
|
|
|
|
if [ -z "$test_state_dir" ] ; then
|
|
if $CTDB_TESTS_ARE_INSTALLED ; then
|
|
test_state_dir=$(mktemp -d)
|
|
else
|
|
test_state_dir="${CTDB_TEST_DIR}/var"
|
|
fi
|
|
fi
|
|
mkdir -p "$test_state_dir"
|
|
|
|
summary_file="${test_state_dir}/.summary"
|
|
: >"$summary_file"
|
|
|
|
export TEST_SCRIPTS_DIR="${CTDB_TEST_DIR}/scripts"
|
|
|
|
# If no tests specified then run some defaults
|
|
if [ -z "$1" ] ; then
|
|
if [ -n "$TEST_LOCAL_DAEMONS" ] ; then
|
|
set -- UNIT INTEGRATION
|
|
else
|
|
set -- INTEGRATION CLUSTER
|
|
fi
|
|
fi
|
|
|
|
do_cleanup ()
|
|
{
|
|
if $cleanup ; then
|
|
echo "Removing test state directory: ${test_state_dir}"
|
|
rm -rf "$test_state_dir"
|
|
else
|
|
echo "Not cleaning up test state directory: ${test_state_dir}"
|
|
fi
|
|
}
|
|
|
|
trap "do_cleanup ; exit 130" SIGINT
|
|
trap "do_cleanup ; exit 143" SIGTERM
|
|
|
|
iterations=0
|
|
# Special case: -I 0 means iterate forever (until failure)
|
|
while [ "$max_iterations" -eq 0 ] || [ $iterations -lt "$max_iterations" ] ; do
|
|
iterations=$((iterations + 1))
|
|
|
|
if [ "$max_iterations" -ne 1 ] ; then
|
|
echo
|
|
echo "##################################################"
|
|
echo "ITERATION ${iterations}"
|
|
echo "##################################################"
|
|
echo
|
|
fi
|
|
|
|
run_tests "$@"
|
|
status=$?
|
|
|
|
if [ $status -ne 0 ] ; then
|
|
break
|
|
fi
|
|
done
|
|
|
|
if $with_summary ; then
|
|
if [ $status -eq 0 ] || ! $exit_on_fail ; then
|
|
echo
|
|
cat "$summary_file"
|
|
|
|
echo
|
|
tests_run=$((tests_total - tests_skipped))
|
|
printf '%d/%d tests passed' $tests_passed $tests_run
|
|
if [ $tests_skipped -gt 0 ] ; then
|
|
printf ' (%d skipped)' $tests_skipped
|
|
fi
|
|
printf '\n'
|
|
fi
|
|
fi
|
|
rm -f "$summary_file"
|
|
|
|
echo
|
|
|
|
do_cleanup
|
|
|
|
if $no_header || $exit_on_fail ; then
|
|
exit $status
|
|
elif [ $tests_failed -gt 0 ] ; then
|
|
exit 1
|
|
else
|
|
exit 0
|
|
fi
|