The traceback files could overwrite each other on systems which do not use different core dump file names for different processes. Prevent that by writing the traceback file to the same directory as the core dump file. These changes still do not prevent the operating system from overwriting a core dump file if the same binary crashes multiple times in the same directory and core dump files are named identically for different processes.
335 lines
10 KiB
Bash
335 lines
10 KiB
Bash
#!/bin/sh
|
|
#
|
|
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
|
#
|
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
#
|
|
# See the COPYRIGHT file distributed with this work for additional
|
|
# information regarding copyright ownership.
|
|
|
|
#
|
|
# Run a system test.
|
|
#
|
|
|
|
top_builddir=@top_builddir@
|
|
builddir=@abs_builddir@
|
|
srcdir=@abs_srcdir@
|
|
|
|
# shellcheck source=conf.sh
|
|
. ${builddir}/conf.sh
|
|
|
|
if [ "$(id -u)" -eq "0" ] && [ "@DEVELOPER_MODE@" != "yes" ]; then
|
|
echofail "Refusing to run test as root. Build with --enable-developer to override." >&2
|
|
exit 1
|
|
fi
|
|
|
|
export builddir
|
|
export srcdir
|
|
|
|
date_with_args() (
|
|
date "+%Y-%m-%dT%T%z"
|
|
)
|
|
|
|
stopservers=true
|
|
# baseport == 0 means random
|
|
baseport=0
|
|
|
|
if [ "${SYSTEMTEST_NO_CLEAN:-0}" -eq 1 ]; then
|
|
clean=false
|
|
else
|
|
clean=true
|
|
fi
|
|
|
|
do_run=false
|
|
log_flags="-r"
|
|
while getopts "sknp:r-:" OPT; do
|
|
log_flags="$log_flags -$OPT$OPTARG"
|
|
if [ "$OPT" = "-" ] && [ -n "$OPTARG" ]; then
|
|
OPT="${OPTARG%%=*}"
|
|
OPTARG="${OPTARG#$OPT}"
|
|
OPTARG="${OPTARG#=}"
|
|
fi
|
|
|
|
# shellcheck disable=SC2214
|
|
case "$OPT" in
|
|
k | keep) stopservers=false ;;
|
|
n | noclean) clean=false ;;
|
|
p | port) baseport=$OPTARG ;;
|
|
r | run) do_run=true ;;
|
|
s | skip) exit 77 ;;
|
|
-) break ;;
|
|
*) echo "invalid option" >&2; exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
shift $((OPTIND-1))
|
|
|
|
if ! $do_run; then
|
|
if [ "$baseport" -eq 0 ]; then
|
|
log_flags="$log_flags -p 5300"
|
|
fi
|
|
env - SLOT="$SLOT" SOFTHSM2_CONF="$SOFTHSM2_CONF" PATH="$PATH" ${LD_LIBRARY_PATH:+"LD_LIBRARY_PATH=${LD_LIBRARY_PATH}"} TESTS="$*" TEST_SUITE_LOG=run.log LOG_DRIVER_FLAGS="--verbose yes --color-tests yes" LOG_FLAGS="$log_flags" make -e check
|
|
exit $?
|
|
fi
|
|
|
|
if [ $# -eq 0 ]; then
|
|
echofail "Usage: $0 [-k] [-n] [-p <PORT>] test-directory [test-options]" >&2;
|
|
exit 1
|
|
fi
|
|
|
|
systest=$(basename "${1%%/}")
|
|
shift
|
|
|
|
if [ ! -d "${srcdir}/$systest" ]; then
|
|
echofail "$0: $systest: no such test" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [ "${srcdir}" != "${builddir}" ]; then
|
|
if [ ! -d common ] || [ ! -r common/.prepared ]; then
|
|
cp -a "${srcdir}/common" "${builddir}"
|
|
fi
|
|
# Some tests require additional files to work for out-of-tree test runs.
|
|
for file in ckdnsrps.sh digcomp.pl ditch.pl packet.pl start.pl stop.pl; do
|
|
if [ ! -r "${file}" ]; then
|
|
cp -a "${srcdir}/${file}" "${builddir}"
|
|
fi
|
|
done
|
|
if [ ! -d "$systest" ] || [ ! -r "$systest/.prepared" ]; then
|
|
mkdir -p "${builddir}/$systest"
|
|
cp -a "${srcdir}/$systest" "${builddir}/"
|
|
touch "$systest/.prepared"
|
|
fi
|
|
fi
|
|
|
|
if [ ! -d "${systest}" ]; then
|
|
echofail "$0: $systest: no such test" >&2
|
|
exit 1
|
|
fi
|
|
|
|
|
|
# Get the first 10 ports in the set (it is assumed that each test has access
|
|
# to ten or more ports): the query port, the control port and eight extra
|
|
# ports. Since the lowest numbered port (specified in the command line)
|
|
# will usually be a multiple of 10, the names are chosen so that if this is
|
|
# true, the last digit of EXTRAPORTn is "n".
|
|
eval "$(${srcdir}/get_ports.sh -p "$baseport")"
|
|
|
|
restart=false
|
|
|
|
start_servers_failed() {
|
|
echoinfo "I:$systest:starting servers failed"
|
|
echofail "R:$systest:FAIL"
|
|
echoend "E:$systest:$(date_with_args)"
|
|
exit 1
|
|
}
|
|
|
|
start_servers() {
|
|
echoinfo "I:$systest:starting servers"
|
|
if $restart; then
|
|
$PERL start.pl --restart --port "$PORT" "$systest" || start_servers_failed
|
|
else
|
|
restart=true
|
|
$PERL start.pl --port "$PORT" "$systest" || start_servers_failed
|
|
fi
|
|
}
|
|
|
|
stop_servers() {
|
|
if $stopservers; then
|
|
echoinfo "I:$systest:stopping servers"
|
|
if ! $PERL stop.pl "$systest"; then
|
|
echoinfo "I:$systest:stopping servers failed"
|
|
return 1
|
|
fi
|
|
fi
|
|
}
|
|
|
|
echostart "S:$systest:$(date_with_args)"
|
|
echoinfo "T:$systest:1:A"
|
|
echoinfo "A:$systest:System test $systest"
|
|
echoinfo "I:$systest:PORTS:${PORT},${TLSPORT},${EXTRAPORT1},${EXTRAPORT2},${EXTRAPORT3},${EXTRAPORT4},${EXTRAPORT5},${EXTRAPORT6},${EXTRAPORT7},${EXTRAPORT8},${CONTROLPORT}"
|
|
|
|
$PERL ${srcdir}/testsock.pl -p "$PORT" || {
|
|
echowarn "I:$systest:Network interface aliases not set up. Skipping test."
|
|
echowarn "R:$systest:FAIL"
|
|
echoend "E:$systest:$(date_with_args)"
|
|
exit 1;
|
|
}
|
|
|
|
# Check for test-specific prerequisites.
|
|
test ! -f "$systest/prereq.sh" || ( cd "${systest}" && $SHELL prereq.sh "$@" )
|
|
result=$?
|
|
|
|
if [ $result -eq 0 ]; then
|
|
: prereqs ok
|
|
else
|
|
echowarn "I:$systest:Prerequisites missing, skipping test."
|
|
if [ $result -eq 255 ]; then
|
|
echowarn "R:$systest:SKIPPED";
|
|
else
|
|
echowarn "R:$systest:UNTESTED"
|
|
fi
|
|
echoend "E:$systest:$(date_with_args)"
|
|
exit 0
|
|
fi
|
|
|
|
# Check for PKCS#11 support
|
|
if
|
|
test ! -f "$systest/usepkcs11" || $SHELL cleanpkcs11.sh
|
|
then
|
|
: pkcs11 ok
|
|
else
|
|
echowarn "I:$systest:Need PKCS#11, skipping test."
|
|
echowarn "R:$systest:PKCS11ONLY"
|
|
echoend "E:$systest:$(date_with_args)"
|
|
exit 0
|
|
fi
|
|
|
|
# Clean up files left from any potential previous runs
|
|
if test -f "$systest/clean.sh"
|
|
then
|
|
if ! ( cd "${systest}" && $SHELL clean.sh "$@" ); then
|
|
echowarn "I:$systest:clean.sh script failed"
|
|
echofail "R:$systest:FAIL"
|
|
echoend "E:$systest:$(date_with_args)"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Set up any dynamically generated test data
|
|
if test -f "$systest/setup.sh"
|
|
then
|
|
if ! ( cd "${systest}" && $SHELL setup.sh "$@" ); then
|
|
echowarn "I:$systest:setup.sh script failed"
|
|
echofail "R:$systest:FAIL"
|
|
echoend "E:$systest:$(date_with_args)"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
status=0
|
|
run=0
|
|
# Run the tests
|
|
if [ -r "$systest/tests.sh" ]; then
|
|
start_servers
|
|
( cd "$systest" && $SHELL tests.sh "$@" )
|
|
status=$?
|
|
run=$((run+1))
|
|
stop_servers || status=1
|
|
fi
|
|
|
|
if [ -n "$PYTEST" ]; then
|
|
run=$((run+1))
|
|
for test in $(cd "${systest}" && find . -name "tests*.py"); do
|
|
start_servers
|
|
rm -f "$systest/$test.status"
|
|
test_status=0
|
|
(cd "$systest" && "$PYTEST" -v "$test" "$@" || echo "$?" > "$test.status") | SYSTESTDIR="$systest" cat_d
|
|
if [ -f "$systest/$test.status" ]; then
|
|
echo_i "FAILED"
|
|
test_status=$(cat "$systest/$test.status")
|
|
fi
|
|
status=$((status+test_status))
|
|
stop_servers || status=1
|
|
done
|
|
else
|
|
echoinfo "I:$systest:pytest not installed, skipping python tests"
|
|
fi
|
|
|
|
if [ "$run" -eq "0" ]; then
|
|
echoinfo "I:$systest:No tests were found and run"
|
|
status=255
|
|
fi
|
|
|
|
if $stopservers
|
|
then
|
|
:
|
|
else
|
|
exit $status
|
|
fi
|
|
|
|
get_core_dumps() {
|
|
find "$systest/" \( -name 'core' -or -name 'core.*' -or -name '*.core' \) ! -name '*.gz' ! -name '*.txt' | sort
|
|
}
|
|
|
|
core_dumps=$(get_core_dumps | tr '\n' ' ')
|
|
assertion_failures=$(find "$systest/" -name named.run -print0 | xargs -0 grep "assertion failure" | wc -l)
|
|
sanitizer_summaries=$(find "$systest/" -name 'tsan.*' | wc -l)
|
|
if [ -n "$core_dumps" ]; then
|
|
status=1
|
|
echoinfo "I:$systest:Core dump(s) found: $core_dumps"
|
|
get_core_dumps | while read -r coredump; do
|
|
export SYSTESTDIR="$systest"
|
|
echoinfo "D:$systest:backtrace from $coredump:"
|
|
echoinfo "D:$systest:--------------------------------------------------------------------------------"
|
|
binary=$(gdb --batch --core="$coredump" 2>/dev/null | sed -ne "s|Core was generated by \`\([^' ]*\)[' ].*|\1|p")
|
|
if [ ! -f "${binary}" ]; then
|
|
binary=$(find "${top_builddir}" -path "*/.libs/${binary}" -type f)
|
|
fi
|
|
"${top_builddir}/libtool" --mode=execute gdb \
|
|
-batch \
|
|
-ex bt \
|
|
-core="$coredump" \
|
|
-- \
|
|
"$binary" 2>/dev/null | sed -n '/^Core was generated by/,$p' | cat_d
|
|
echoinfo "D:$systest:--------------------------------------------------------------------------------"
|
|
coredump_backtrace="${coredump}-backtrace.txt"
|
|
echoinfo "D:$systest:full backtrace from $coredump saved in $coredump_backtrace"
|
|
"${top_builddir}/libtool" --mode=execute gdb \
|
|
-batch \
|
|
-command=run.gdb \
|
|
-core="$coredump" \
|
|
-- \
|
|
"$binary" > "$coredump_backtrace" 2>&1
|
|
echoinfo "D:$systest:core dump $coredump archived as $coredump.gz"
|
|
gzip -1 "${coredump}"
|
|
done
|
|
elif [ "$assertion_failures" -ne 0 ]; then
|
|
status=1
|
|
SYSTESTDIR="$systest"
|
|
echoinfo "I:$systest:$assertion_failures assertion failure(s) found"
|
|
find "$systest/" -name 'tsan.*' -print0 | xargs -0 grep "SUMMARY: " | sort -u | cat_d
|
|
elif [ "$sanitizer_summaries" -ne 0 ]; then
|
|
status=1
|
|
echoinfo "I:$systest:$sanitizer_summaries sanitizer report(s) found"
|
|
fi
|
|
|
|
print_outstanding_files() {
|
|
if test -d ${srcdir}/../../../.git; then
|
|
git status -su --ignored "${systest}" 2>/dev/null | \
|
|
sed -n -e 's|^?? \(.*\)|I:file \1 not removed|p' \
|
|
-e 's|^!! \(.*/named.run\)$|I:file \1 not removed|p' \
|
|
-e 's|^!! \(.*/named.memstats\)$|I:file \1 not removed|p'
|
|
fi
|
|
}
|
|
|
|
print_outstanding_files_oot() {
|
|
if test -d ${srcdir}/../../../.git; then
|
|
git -C "${srcdir}/${systest}" ls-files | sed "s|^|${systest}/|" > gitfiles.txt
|
|
find "${systest}/" -type f ! -name .prepared ! -name Makefile > testfiles.txt
|
|
grep -F -x -v -f gitfiles.txt testfiles.txt
|
|
rm -f gitfiles.txt testfiles.txt
|
|
fi
|
|
}
|
|
|
|
if [ $status -ne 0 ]; then
|
|
echofail "R:$systest:FAIL"
|
|
else
|
|
echopass "R:$systest:PASS"
|
|
if $clean; then
|
|
( cd "${systest}" && $SHELL clean.sh "$@" )
|
|
if [ "${srcdir}" = "${builddir}" ]; then
|
|
print_outstanding_files
|
|
else
|
|
print_outstanding_files_oot | xargs rm -f
|
|
find "${systest}/" \( -type d -empty \) -delete 2>/dev/null
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
echoend "E:$systest:$(date_with_args)"
|
|
|
|
exit $status
|