2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-31 14:35:26 +00:00

Merge branch 'tkrizek/pytest-conf-cleanup' into 'main'

Define environment variables in pytest instead of conf.sh

See merge request isc-projects/bind9!8800
This commit is contained in:
Nicki Křížek
2024-05-09 16:26:26 +00:00
40 changed files with 661 additions and 552 deletions

View File

@@ -271,11 +271,11 @@ stages:
# change directory to the workspace before including this
.find_python: &find_python
- PYTHON="$(source bin/tests/system/conf.sh; echo $PYTHON)"
- PYTHON="$(cat bin/tests/system/isctest/vars/.ac_vars/PYTHON)"
- test -x "$PYTHON"
.find_pytest: &find_pytest
- PYTEST="$(source bin/tests/system/conf.sh; echo $PYTEST)"
- PYTEST="$(cat bin/tests/system/isctest/vars/.ac_vars/PYTEST)"
- test -x "$PYTEST"
.parse_tsan: &parse_tsan
@@ -702,7 +702,8 @@ cross-version-config-tests:
# Run the setup phase of all system tests in the most recently tagged BIND 9
# release using the binaries built for the current BIND 9 version. This
# intends to detect obvious backward compatibility issues with the latter.
- sed -i -E "s|(export TOP_BUILDDIR)=.*|\1=${CI_PROJECT_DIR}|" conf.sh
- >
sed -i -E "s|(\s* \"TOP_BUILDDIR\"):.*|\1: \"${CI_PROJECT_DIR}\",|" isctest/vars/autoconf.py
- >
"$PYTEST" --setup-only --junit-xml="$CI_PROJECT_DIR"/junit.xml -n "${TEST_PARALLEL_JOBS:-1}"
needs:
@@ -719,6 +720,7 @@ cross-version-config-tests:
untracked: true
expire_in: "1 day"
when: always
allow_failure: true # pytest env variable refactoring
# Jobs for regular GCC builds on Alpine Linux 3.19 (amd64)

View File

@@ -47,6 +47,7 @@ Files: **/*.after*
bin/tests/system/forward/CA/index.txt
bin/tests/system/forward/CA/index.txt.attr
bin/tests/system/forward/CA/serial
bin/tests/system/isctest/vars/.ac_vars/*
bin/tests/system/journal/ns1/managed-keys.bind.in
bin/tests/system/journal/ns1/managed-keys.bind.jnl.in
bin/tests/system/journal/ns2/managed-keys.bind.in

View File

@@ -3,7 +3,6 @@ nxtify
sdig
*_test
gsstest
conf.sh
dlopen
keycreate
keydelete

View File

@@ -19,6 +19,8 @@ named.run
/start.sh
/stop.sh
/ifconfig.sh
/isctest/vars/.ac_vars/*
!/isctest/vars/.ac_vars/*.in
# Ignore file names with underscore in their name except python or shell files.
# This is done to ignore the temporary directories and symlinks created by the

View File

@@ -11,146 +11,92 @@
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
# When sourcing the script outside the pytest environment (e.g. during helper
# script development), the env variables have to be loaded.
if [ -z "$TOP_SRCDIR" ]; then
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd | sed -E 's|(.*bin/tests/system).*|\1|')
eval "$(PYTHONPATH="$SCRIPT_DIR:$PYTHONPATH" /usr/bin/env python3 -m isctest)"
fi
testsock6() {
if test -n "$PERL" && $PERL -e "use IO::Socket::IP;" 2> /dev/null
then
$PERL "$TOP_SRCDIR/bin/tests/system/testsock6.pl" "$@"
else
false
fi
if test -n "$PERL" && $PERL -e "use IO::Socket::IP;" 2>/dev/null; then
$PERL "$TOP_SRCDIR/bin/tests/system/testsock6.pl" "$@"
else
false
fi
}
export LANG=C
echofail() {
echo "$*"
}
echowarn() {
echo "$*"
}
echopass() {
echo "$*"
}
echoinfo() {
echo "$*"
}
echostart() {
echo "$*"
}
echoend() {
echo "$*"
}
echo_i() {
echo "$@" | while IFS= read -r __LINE; do
echoinfo "I:$__LINE"
done
}
#
# Set up color-coded test output
#
if [ ${SYSTEMTEST_FORCE_COLOR:-0} -eq 1 ] || test -t 1 && type tput > /dev/null 2>&1 && tput setaf 7 > /dev/null 2>&1 ; then
export COLOR_END=$(tput setaf 4) # blue
export COLOR_FAIL=$(tput setaf 1) # red
export COLOR_INFO=$(tput bold) # bold
export COLOR_NONE=$(tput sgr0)
export COLOR_PASS=$(tput setaf 2) # green
export COLOR_START=$(tput setaf 4) # blue
export COLOR_WARN=$(tput setaf 3) # yellow
else
# set to empty strings so printf succeeds
export COLOR_END=''
export COLOR_FAIL=''
export COLOR_INFO=''
export COLOR_NONE=''
export COLOR_PASS=''
export COLOR_START=''
export COLOR_WARN=''
fi
echo_ic() {
echo "$@" | while IFS= read -r __LINE; do
echoinfo "I: $__LINE"
done
}
export SYSTESTDIR="$(basename $PWD)"
if type printf > /dev/null 2>&1
then
echofail () {
printf "${COLOR_FAIL}%s${COLOR_NONE}\n" "$*"
}
echowarn () {
printf "${COLOR_WARN}%s${COLOR_NONE}\n" "$*"
}
echopass () {
printf "${COLOR_PASS}%s${COLOR_NONE}\n" "$*"
}
echoinfo () {
printf "${COLOR_INFO}%s${COLOR_NONE}\n" "$*"
}
echostart () {
printf "${COLOR_START}%s${COLOR_NONE}\n" "$*"
}
echoend () {
printf "${COLOR_END}%s${COLOR_NONE}\n" "$*"
}
echo_i() {
printf '%s\n' "$*" | while IFS= read -r __LINE ; do
echoinfo "I:$__LINE"
done
}
echo_ic() {
printf '%s\n' "$*" | while IFS= read -r __LINE ; do
echoinfo "I: $__LINE"
done
}
echo_d() {
printf '%s\n' "$*" | while IFS= read -r __LINE ; do
echoinfo "D:$__LINE"
done
}
else
echofail () {
echo "$*"
}
echowarn () {
echo "$*"
}
echopass () {
echo "$*"
}
echoinfo () {
echo "$*"
}
echostart () {
echo "$*"
}
echoend () {
echo "$*"
}
echo_i() {
echo "$@" | while IFS= read -r __LINE ; do
echoinfo "I:$__LINE"
done
}
echo_ic() {
echo "$@" | while IFS= read -r __LINE ; do
echoinfo "I: $__LINE"
done
}
echo_d() {
echo "$@" | while IFS= read -r __LINE ; do
echoinfo "D:$__LINE"
done
}
fi
echo_d() {
echo "$@" | while IFS= read -r __LINE; do
echoinfo "D:$__LINE"
done
}
cat_i() {
while IFS= read -r __LINE ; do
echoinfo "I:$__LINE"
done
while IFS= read -r __LINE; do
echoinfo "I:$__LINE"
done
}
cat_d() {
while IFS= read -r __LINE ; do
echoinfo "D:$__LINE"
done
while IFS= read -r __LINE; do
echoinfo "D:$__LINE"
done
}
digcomp() {
{ output=$($PERL $TOP_SRCDIR/bin/tests/system/digcomp.pl "$@"); result=$?; } || true
[ -n "$output" ] && { echo "digcomp failed:"; echo "$output"; } | cat_i
return $result
{
output=$($PERL $TOP_SRCDIR/bin/tests/system/digcomp.pl "$@")
result=$?
} || true
[ -n "$output" ] && {
echo "digcomp failed:"
echo "$output"
} | cat_i
return $result
}
start_server() {
$PERL "$TOP_SRCDIR/bin/tests/system/start.pl" "$SYSTESTDIR" "$@"
$PERL "$TOP_SRCDIR/bin/tests/system/start.pl" "$SYSTESTDIR" "$@"
}
stop_server() {
$PERL "$TOP_SRCDIR/bin/tests/system/stop.pl" "$SYSTESTDIR" "$@"
$PERL "$TOP_SRCDIR/bin/tests/system/stop.pl" "$SYSTESTDIR" "$@"
}
send() {
$PERL "$TOP_SRCDIR/bin/tests/system/send.pl" "$@"
$PERL "$TOP_SRCDIR/bin/tests/system/send.pl" "$@"
}
#
@@ -199,94 +145,94 @@ export DEFAULT_HMAC=hmac-sha256
# the error using the description of the tested variable provided in $3
# and return 1.
assert_int_equal() {
found="$1"
expected="$2"
description="$3"
found="$1"
expected="$2"
description="$3"
if [ "${expected}" -ne "${found}" ]; then
echo_i "incorrect ${description}: got ${found}, expected ${expected}"
return 1
fi
if [ "${expected}" -ne "${found}" ]; then
echo_i "incorrect ${description}: got ${found}, expected ${expected}"
return 1
fi
return 0
return 0
}
# keyfile_to_keys_section: helper function for keyfile_to_*_keys() which
# converts keyfile data into a key-style trust anchor configuration
# section using the supplied parameters
keyfile_to_keys() {
section_name=$1
key_prefix=$2
shift
shift
echo "$section_name {"
for keyname in $*; do
awk '!/^; /{
section_name=$1
key_prefix=$2
shift
shift
echo "$section_name {"
for keyname in $*; do
awk '!/^; /{
printf "\t\""$1"\" "
printf "'"$key_prefix "'"
printf $4 " " $5 " " $6 " \""
for (i=7; i<=NF; i++) printf $i
printf "\";\n"
}' $keyname.key
done
echo "};"
done
echo "};"
}
# keyfile_to_dskeys_section: helper function for keyfile_to_*_dskeys()
# converts keyfile data into a DS-style trust anchor configuration
# section using the supplied parameters
keyfile_to_dskeys() {
section_name=$1
key_prefix=$2
shift
shift
echo "$section_name {"
for keyname in $*; do
$DSFROMKEY $keyname.key | \
awk '!/^; /{
section_name=$1
key_prefix=$2
shift
shift
echo "$section_name {"
for keyname in $*; do
$DSFROMKEY $keyname.key \
| awk '!/^; /{
printf "\t\""$1"\" "
printf "'"$key_prefix "'"
printf $4 " " $5 " " $6 " \""
for (i=7; i<=NF; i++) printf $i
printf "\";\n"
}'
done
echo "};"
done
echo "};"
}
# keyfile_to_trusted_keys: convert key data contained in the keyfile(s)
# provided to a "trust-keys" section suitable for including in a
# resolver's configuration file
keyfile_to_trusted_keys() {
keyfile_to_keys "trusted-keys" "" $*
keyfile_to_keys "trusted-keys" "" $*
}
# keyfile_to_static_keys: convert key data contained in the keyfile(s)
# provided to a *static-key* "trust-anchors" section suitable for including in
# a resolver's configuration file
keyfile_to_static_keys() {
keyfile_to_keys "trust-anchors" "static-key" $*
keyfile_to_keys "trust-anchors" "static-key" $*
}
# keyfile_to_initial_keys: convert key data contained in the keyfile(s)
# provided to an *initial-key* "trust-anchors" section suitable for including
# in a resolver's configuration file
keyfile_to_initial_keys() {
keyfile_to_keys "trust-anchors" "initial-key" $*
keyfile_to_keys "trust-anchors" "initial-key" $*
}
# keyfile_to_static_ds_keys: convert key data contained in the keyfile(s)
# provided to a *static-ds* "trust-anchors" section suitable for including in a
# resolver's configuration file
keyfile_to_static_ds() {
keyfile_to_dskeys "trust-anchors" "static-ds" $*
keyfile_to_dskeys "trust-anchors" "static-ds" $*
}
# keyfile_to_initial_ds_keys: convert key data contained in the keyfile(s)
# provided to an *initial-ds* "trust-anchors" section suitable for including
# in a resolver's configuration file
keyfile_to_initial_ds() {
keyfile_to_dskeys "trust-anchors" "initial-ds" $*
keyfile_to_dskeys "trust-anchors" "initial-ds" $*
}
# keyfile_to_key_id: convert a key file name to a key ID
@@ -295,7 +241,7 @@ keyfile_to_initial_ds() {
# print the key ID with leading zeros stripped ("6160" for the
# aforementioned example).
keyfile_to_key_id() {
echo "$1" | sed "s/.*+0\{0,4\}//"
echo "$1" | sed "s/.*+0\{0,4\}//"
}
# private_type_record: write a private type record recording the state of the
@@ -305,13 +251,13 @@ keyfile_to_key_id() {
# private type record with default type value of 65534, indicating that the
# signing process for this key is completed.
private_type_record() {
_zone=$1
_algorithm=$2
_keyfile=$3
_zone=$1
_algorithm=$2
_keyfile=$3
_id=$(keyfile_to_key_id "$_keyfile")
_id=$(keyfile_to_key_id "$_keyfile")
printf "%s. 0 IN TYPE65534 %s 5 %02x%04x0000\n" "$_zone" "\\#" "$_algorithm" "$_id"
printf "%s. 0 IN TYPE65534 %s 5 %02x%04x0000\n" "$_zone" "\\#" "$_algorithm" "$_id"
}
# nextpart*() - functions for reading files incrementally
@@ -362,51 +308,51 @@ private_type_record() {
# nextpartreset: reset the marker used by nextpart() and nextpartpeek()
# so that it points to the start of the given file
nextpartreset() {
echo "0" > $1.prev
echo "0" >$1.prev
}
# nextpartread: read everything that's been appended to a file since the
# last time nextpart() was called and print it to stdout, print the
# total number of lines read from that file so far to file descriptor 3
nextpartread() {
[ -f $1.prev ] || nextpartreset $1
prev=$(cat $1.prev)
awk "NR > $prev "'{ print }
[ -f $1.prev ] || nextpartreset $1
prev=$(cat $1.prev)
awk "NR > $prev "'{ print }
END { print NR > "/dev/stderr" }' $1 2>&3
}
# nextpart: read everything that's been appended to a file since the
# last time nextpart() was called
nextpart() {
nextpartread $1 3> $1.prev.tmp
mv $1.prev.tmp $1.prev
nextpartread $1 3>$1.prev.tmp
mv $1.prev.tmp $1.prev
}
# nextpartpeek: read everything that's been appended to a file since the
# last time nextpart() was called
nextpartpeek() {
nextpartread $1 3> /dev/null
nextpartread $1 3>/dev/null
}
# _search_log: look for message $1 in file $2 with nextpart().
_search_log() (
msg="$1"
file="$2"
nextpart "$file" | grep -F -e "$msg" > /dev/null
msg="$1"
file="$2"
nextpart "$file" | grep -F -e "$msg" >/dev/null
)
# _search_log_re: same as _search_log but the message is an grep -E regex
_search_log_re() (
msg="$1"
file="$2"
nextpart "$file" | grep -E -e "$msg" > /dev/null
msg="$1"
file="$2"
nextpart "$file" | grep -E -e "$msg" >/dev/null
)
# _search_log_peek: look for message $1 in file $2 with nextpartpeek().
_search_log_peek() (
msg="$1"
file="$2"
nextpartpeek "$file" | grep -F -e "$msg" > /dev/null
msg="$1"
file="$2"
nextpartpeek "$file" | grep -F -e "$msg" >/dev/null
)
# wait_for_log: wait until message $2 in file $3 appears. Bail out after
@@ -415,108 +361,108 @@ _search_log_peek() (
# set correctly. Tests using wait_for_log() are responsible for cleaning up
# the created <file>.prev files.
wait_for_log() (
timeout="$1"
msg="$2"
file="$3"
retry_quiet "$timeout" _search_log "$msg" "$file" && return 0
echo_i "exceeded time limit waiting for literal '$msg' in $file"
return 1
timeout="$1"
msg="$2"
file="$3"
retry_quiet "$timeout" _search_log "$msg" "$file" && return 0
echo_i "exceeded time limit waiting for literal '$msg' in $file"
return 1
)
# wait_for_log_re: same as wait_for_log, but the message is an grep -E regex
wait_for_log_re() (
timeout="$1"
msg="$2"
file="$3"
retry_quiet "$timeout" _search_log_re "$msg" "$file" && return 0
echo_i "exceeded time limit waiting for regex '$msg' in $file"
return 1
timeout="$1"
msg="$2"
file="$3"
retry_quiet "$timeout" _search_log_re "$msg" "$file" && return 0
echo_i "exceeded time limit waiting for regex '$msg' in $file"
return 1
)
# wait_for_log_peek: similar to wait_for_log() but peeking, so the file offset
# does not change.
wait_for_log_peek() (
timeout="$1"
msg="$2"
file="$3"
retry_quiet "$timeout" _search_log_peek "$msg" "$file" && return 0
echo_i "exceeded time limit waiting for literal '$msg' in $file"
return 1
timeout="$1"
msg="$2"
file="$3"
retry_quiet "$timeout" _search_log_peek "$msg" "$file" && return 0
echo_i "exceeded time limit waiting for literal '$msg' in $file"
return 1
)
# _retry: keep running a command until it succeeds, up to $1 times, with
# one-second intervals, optionally printing a message upon every attempt
_retry() {
__retries="${1}"
shift
__retries="${1}"
shift
while :; do
if "$@"; then
return 0
fi
__retries=$((__retries-1))
if [ "${__retries}" -gt 0 ]; then
if [ "${__retry_quiet}" -ne 1 ]; then
echo_i "retrying"
fi
sleep 1
else
return 1
fi
done
while :; do
if "$@"; then
return 0
fi
__retries=$((__retries - 1))
if [ "${__retries}" -gt 0 ]; then
if [ "${__retry_quiet}" -ne 1 ]; then
echo_i "retrying"
fi
sleep 1
else
return 1
fi
done
}
# retry: call _retry() in verbose mode
retry() {
__retry_quiet=0
_retry "$@"
__retry_quiet=0
_retry "$@"
}
# retry_quiet: call _retry() in silent mode
retry_quiet() {
__retry_quiet=1
_retry "$@"
__retry_quiet=1
_retry "$@"
}
# _repeat: keep running command up to $1 times, unless it fails
_repeat() (
__retries="${1}"
shift
while :; do
if ! "$@"; then
return 1
fi
__retries=$((__retries-1))
if [ "${__retries}" -le 0 ]; then
break
fi
done
return 0
__retries="${1}"
shift
while :; do
if ! "$@"; then
return 1
fi
__retries=$((__retries - 1))
if [ "${__retries}" -le 0 ]; then
break
fi
done
return 0
)
_times() {
awk "BEGIN{ for(i = 1; i <= $1; i++) print i}";
awk "BEGIN{ for(i = 1; i <= $1; i++) print i}"
}
rndc_reload() {
$RNDC -c ../_common/rndc.conf -s $2 -p ${CONTROLPORT} reload $3 2>&1 | sed 's/^/'"I:$1"' /'
# reloading single zone is synchronous, if we're reloading whole server
# we need to wait for reload to finish
if [ -z "$3" ]; then
for _ in $(_times 10); do
$RNDC -c ../_common/rndc.conf -s $2 -p ${CONTROLPORT} status | grep "reload/reconfig in progress" > /dev/null || break
sleep 1
done
fi
$RNDC -c ../_common/rndc.conf -s $2 -p ${CONTROLPORT} reload $3 2>&1 | sed 's/^/'"I:$1"' /'
# reloading single zone is synchronous, if we're reloading whole server
# we need to wait for reload to finish
if [ -z "$3" ]; then
for _ in $(_times 10); do
$RNDC -c ../_common/rndc.conf -s $2 -p ${CONTROLPORT} status | grep "reload/reconfig in progress" >/dev/null || break
sleep 1
done
fi
}
rndc_reconfig() {
seconds=${3:-10}
$RNDC -c ../_common/rndc.conf -s "$2" -p "${CONTROLPORT}" reconfig 2>&1 | sed 's/^/'"I:$1"' /'
for _ in $(_times "$seconds"); do
"$RNDC" -c ../_common/rndc.conf -s "$2" -p "${CONTROLPORT}" status | grep "reload/reconfig in progress" > /dev/null || break
sleep 1
done
seconds=${3:-10}
$RNDC -c ../_common/rndc.conf -s "$2" -p "${CONTROLPORT}" reconfig 2>&1 | sed 's/^/'"I:$1"' /'
for _ in $(_times "$seconds"); do
"$RNDC" -c ../_common/rndc.conf -s "$2" -p "${CONTROLPORT}" status | grep "reload/reconfig in progress" >/dev/null || break
sleep 1
done
}
# rndc_dumpdb: call "rndc dumpdb [...]" and wait until it completes
@@ -535,39 +481,38 @@ rndc_reconfig() {
# code other than 0 or if the "; Dump complete" string does not appear in the
# dump within 10 seconds.
rndc_dumpdb() {
__ret=0
__dump_complete=0
__server="${1}"
__ip="10.53.0.$(echo "${__server}" | tr -c -d "0-9")"
__ret=0
__dump_complete=0
__server="${1}"
__ip="10.53.0.$(echo "${__server}" | tr -c -d "0-9")"
shift
${RNDC} -c ../_common/rndc.conf -p "${CONTROLPORT}" -s "${__ip}" dumpdb "$@" > "rndc.out.test${n}" 2>&1 || __ret=1
shift
${RNDC} -c ../_common/rndc.conf -p "${CONTROLPORT}" -s "${__ip}" dumpdb "$@" >"rndc.out.test${n}" 2>&1 || __ret=1
for _ in 0 1 2 3 4 5 6 7 8 9
do
if grep '^; Dump complete$' "${__server}/named_dump.db" > /dev/null; then
mv "${__server}/named_dump.db" "${__server}/named_dump.db.test${n}"
__dump_complete=1
break
fi
sleep 1
done
for _ in 0 1 2 3 4 5 6 7 8 9; do
if grep '^; Dump complete$' "${__server}/named_dump.db" >/dev/null; then
mv "${__server}/named_dump.db" "${__server}/named_dump.db.test${n}"
__dump_complete=1
break
fi
sleep 1
done
if [ ${__dump_complete} -eq 0 ]; then
echo_i "timed out waiting for 'rndc dumpdb' to finish"
__ret=1
fi
if [ ${__dump_complete} -eq 0 ]; then
echo_i "timed out waiting for 'rndc dumpdb' to finish"
__ret=1
fi
return ${__ret}
return ${__ret}
}
# get_dig_xfer_stats: extract transfer statistics from dig output stored
# in $1, converting them to a format used by some system tests.
get_dig_xfer_stats() {
LOGFILE="$1"
sed -n "s/^;; XFR size: .*messages \([0-9][0-9]*\).*/messages=\1/p" "${LOGFILE}"
sed -n "s/^;; XFR size: \([0-9][0-9]*\) records.*/records=\1/p" "${LOGFILE}"
sed -n "s/^;; XFR size: .*bytes \([0-9][0-9]*\).*/bytes=\1/p" "${LOGFILE}"
LOGFILE="$1"
sed -n "s/^;; XFR size: .*messages \([0-9][0-9]*\).*/messages=\1/p" "${LOGFILE}"
sed -n "s/^;; XFR size: \([0-9][0-9]*\) records.*/records=\1/p" "${LOGFILE}"
sed -n "s/^;; XFR size: .*bytes \([0-9][0-9]*\).*/bytes=\1/p" "${LOGFILE}"
}
# get_named_xfer_stats: from named log file $1, extract transfer
@@ -575,16 +520,16 @@ get_dig_xfer_stats() {
# message which has to contain the string provided in $4), converting
# them to a format used by some system tests.
get_named_xfer_stats() {
LOGFILE="$1"
PEER="$(echo $2 | sed 's/\./\\./g')"
ZONE="$(echo $3 | sed 's/\./\\./g')"
MESSAGE="$4"
grep " ${PEER}#.*${MESSAGE}:" "${LOGFILE}" | \
sed -n "s/.* '${ZONE}\/.* \([0-9][0-9]*\) messages.*/messages=\1/p" | tail -1
grep " ${PEER}#.*${MESSAGE}:" "${LOGFILE}" | \
sed -n "s/.* '${ZONE}\/.* \([0-9][0-9]*\) records.*/records=\1/p" | tail -1
grep " ${PEER}#.*${MESSAGE}:" "${LOGFILE}" | \
sed -n "s/.* '${ZONE}\/.* \([0-9][0-9]*\) bytes.*/bytes=\1/p" | tail -1
LOGFILE="$1"
PEER="$(echo $2 | sed 's/\./\\./g')"
ZONE="$(echo $3 | sed 's/\./\\./g')"
MESSAGE="$4"
grep " ${PEER}#.*${MESSAGE}:" "${LOGFILE}" \
| sed -n "s/.* '${ZONE}\/.* \([0-9][0-9]*\) messages.*/messages=\1/p" | tail -1
grep " ${PEER}#.*${MESSAGE}:" "${LOGFILE}" \
| sed -n "s/.* '${ZONE}\/.* \([0-9][0-9]*\) records.*/records=\1/p" | tail -1
grep " ${PEER}#.*${MESSAGE}:" "${LOGFILE}" \
| sed -n "s/.* '${ZONE}\/.* \([0-9][0-9]*\) bytes.*/bytes=\1/p" | tail -1
}
# copy_setports - Copy Configuration File and Replace Ports
@@ -598,57 +543,33 @@ get_named_xfer_stats() {
# copy_setports infile outfile
#
copy_setports() {
dir=$(echo "$TMPDIR" | sed 's/\//\\\//g')
dir=$(echo "$TMPDIR" | sed 's/\//\\\//g')
sed -e "s/@TMPDIR@/${dir}/g" \
-e "s/@PORT@/${PORT}/g" \
-e "s/@TLSPORT@/${TLSPORT}/g" \
-e "s/@HTTPPORT@/${HTTPPORT}/g" \
-e "s/@HTTPSPORT@/${HTTPSPORT}/g" \
-e "s/@EXTRAPORT1@/${EXTRAPORT1}/g" \
-e "s/@EXTRAPORT2@/${EXTRAPORT2}/g" \
-e "s/@EXTRAPORT3@/${EXTRAPORT3}/g" \
-e "s/@EXTRAPORT4@/${EXTRAPORT4}/g" \
-e "s/@EXTRAPORT5@/${EXTRAPORT5}/g" \
-e "s/@EXTRAPORT6@/${EXTRAPORT6}/g" \
-e "s/@EXTRAPORT7@/${EXTRAPORT7}/g" \
-e "s/@EXTRAPORT8@/${EXTRAPORT8}/g" \
-e "s/@CONTROLPORT@/${CONTROLPORT}/g" \
-e "s/@DEFAULT_ALGORITHM@/${DEFAULT_ALGORITHM}/g" \
-e "s/@DEFAULT_ALGORITHM_NUMBER@/${DEFAULT_ALGORITHM_NUMBER}/g" \
-e "s/@DEFAULT_BITS@/${DEFAULT_BITS}/g" \
-e "s/@ALTERNATIVE_ALGORITHM@/${ALTERNATIVE_ALGORITHM}/g" \
-e "s/@ALTERNATIVE_ALGORITHM_NUMBER@/${ALTERNATIVE_ALGORITHM_NUMBER}/g" \
-e "s/@ALTERNATIVE_BITS@/${ALTERNATIVE_BITS}/g" \
-e "s/@DEFAULT_HMAC@/${DEFAULT_HMAC}/g" \
-e "s/@DISABLED_ALGORITHM@/${DISABLED_ALGORITHM}/g" \
-e "s/@DISABLED_ALGORITHM_NUMBER@/${DISABLED_ALGORITHM_NUMBER}/g" \
-e "s/@DISABLED_BITS@/${DISABLED_BITS}/g" \
$1 > $2
}
# parse_openssl_config - Parse OpenSSL configuration for HSM settings
#
# Will set SOFTHSM2_MODULE, OPENSSL_ENGINE and ENGINE_ARG based on openssl configuration.
parse_openssl_config() {
ENGINE_ARG=""
[ -f "$OPENSSL_CONF" ] || return 0
while IFS="=" read key val; do
# trim variables
key="${key## }"
key="${key%% }"
val="${val## }"
val="${val%% }"
case "$key" in
"engine_id")
OPENSSL_ENGINE="$val"
ENGINE_ARG="-E $OPENSSL_ENGINE"
;;
"MODULE_PATH"|"pkcs11-module-path")
SOFTHSM2_MODULE="$val"
;;
esac
done < "$OPENSSL_CONF"
sed -e "s/@TMPDIR@/${dir}/g" \
-e "s/@PORT@/${PORT}/g" \
-e "s/@TLSPORT@/${TLSPORT}/g" \
-e "s/@HTTPPORT@/${HTTPPORT}/g" \
-e "s/@HTTPSPORT@/${HTTPSPORT}/g" \
-e "s/@EXTRAPORT1@/${EXTRAPORT1}/g" \
-e "s/@EXTRAPORT2@/${EXTRAPORT2}/g" \
-e "s/@EXTRAPORT3@/${EXTRAPORT3}/g" \
-e "s/@EXTRAPORT4@/${EXTRAPORT4}/g" \
-e "s/@EXTRAPORT5@/${EXTRAPORT5}/g" \
-e "s/@EXTRAPORT6@/${EXTRAPORT6}/g" \
-e "s/@EXTRAPORT7@/${EXTRAPORT7}/g" \
-e "s/@EXTRAPORT8@/${EXTRAPORT8}/g" \
-e "s/@CONTROLPORT@/${CONTROLPORT}/g" \
-e "s/@DEFAULT_ALGORITHM@/${DEFAULT_ALGORITHM}/g" \
-e "s/@DEFAULT_ALGORITHM_NUMBER@/${DEFAULT_ALGORITHM_NUMBER}/g" \
-e "s/@DEFAULT_BITS@/${DEFAULT_BITS}/g" \
-e "s/@ALTERNATIVE_ALGORITHM@/${ALTERNATIVE_ALGORITHM}/g" \
-e "s/@ALTERNATIVE_ALGORITHM_NUMBER@/${ALTERNATIVE_ALGORITHM_NUMBER}/g" \
-e "s/@ALTERNATIVE_BITS@/${ALTERNATIVE_BITS}/g" \
-e "s/@DEFAULT_HMAC@/${DEFAULT_HMAC}/g" \
-e "s/@DISABLED_ALGORITHM@/${DISABLED_ALGORITHM}/g" \
-e "s/@DISABLED_ALGORITHM_NUMBER@/${DISABLED_ALGORITHM_NUMBER}/g" \
-e "s/@DISABLED_BITS@/${DISABLED_BITS}/g" \
$1 >$2
}
grep_v() { grep -v "$@" || test $? = 1; }

View File

@@ -1,100 +0,0 @@
#!/bin/sh
#
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# SPDX-License-Identifier: MPL-2.0
#
# 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 https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
#
# Common configuration data for system tests, to be sourced into
# other shell scripts.
#
# Find the top of the BIND9 tree.
export TOP_BUILDDIR=@abs_top_builddir@
export TOP_SRCDIR=@abs_top_srcdir@
# Provide TMPDIR variable for tests that need it.
export TMPDIR=${TMPDIR:-/tmp}
export ARPANAME=$TOP_BUILDDIR/bin/tools/arpaname
export CDS=$TOP_BUILDDIR/bin/dnssec/dnssec-cds
export CHECKCONF=$TOP_BUILDDIR/bin/check/named-checkconf
export CHECKZONE=$TOP_BUILDDIR/bin/check/named-checkzone
if [ -z "$TSAN_OPTIONS" ]; then # workaround for GL#4119
export DELV=$TOP_BUILDDIR/bin/delv/delv
else
export DELV=:
fi
export DIG=$TOP_BUILDDIR/bin/dig/dig
export DNSTAPREAD=$TOP_BUILDDIR/bin/tools/dnstap-read
export DSFROMKEY=$TOP_BUILDDIR/bin/dnssec/dnssec-dsfromkey
export FEATURETEST=$TOP_BUILDDIR/bin/tests/system/feature-test
export FSTRM_CAPTURE=@FSTRM_CAPTURE@
export HOST=$TOP_BUILDDIR/bin/dig/host
export IMPORTKEY=$TOP_BUILDDIR/bin/dnssec/dnssec-importkey
export JOURNALPRINT=$TOP_BUILDDIR/bin/tools/named-journalprint
export KEYFRLAB=$TOP_BUILDDIR/bin/dnssec/dnssec-keyfromlabel
export KEYGEN=$TOP_BUILDDIR/bin/dnssec/dnssec-keygen
export KSR=$TOP_BUILDDIR/bin/dnssec/dnssec-ksr
export MDIG=$TOP_BUILDDIR/bin/tools/mdig
export NAMED=$TOP_BUILDDIR/bin/named/named
export NSEC3HASH=$TOP_BUILDDIR/bin/tools/nsec3hash
export NSLOOKUP=$TOP_BUILDDIR/bin/dig/nslookup
export NSUPDATE=$TOP_BUILDDIR/bin/nsupdate/nsupdate
export NZD2NZF=$TOP_BUILDDIR/bin/tools/named-nzd2nzf
export REVOKE=$TOP_BUILDDIR/bin/dnssec/dnssec-revoke
export RNDC=$TOP_BUILDDIR/bin/rndc/rndc
export RNDCCONFGEN=$TOP_BUILDDIR/bin/confgen/rndc-confgen
export RRCHECKER=$TOP_BUILDDIR/bin/tools/named-rrchecker
export SETTIME=$TOP_BUILDDIR/bin/dnssec/dnssec-settime
export SIGNER=$TOP_BUILDDIR/bin/dnssec/dnssec-signzone
export TSIGKEYGEN=$TOP_BUILDDIR/bin/confgen/tsig-keygen
export VERIFY=$TOP_BUILDDIR/bin/dnssec/dnssec-verify
export WIRETEST=$TOP_BUILDDIR/bin/tests/wire_test
export BIGKEY=$TOP_BUILDDIR/bin/tests/system/rsabigexponent/bigkey
export GENCHECK=$TOP_BUILDDIR/bin/tests/system/rndc/gencheck
export MAKEJOURNAL=$TOP_BUILDDIR/bin/tests/system/makejournal
export PIPEQUERIES=$TOP_BUILDDIR/bin/tests/system/pipelined/pipequeries
# we don't want a KRB5_CONFIG setting breaking the tests
export KRB5_CONFIG=/dev/null
# use local keytab instead of default /etc/krb5.keytab
export KRB5_KTNAME=dns.keytab
export ANS_LOG_LEVEL=debug
#
# Programs detected by configure
# Variables will be empty if no program was found by configure
#
export SHELL=@SHELL@
export CURL=@CURL@
export NC=@NC@
export XMLLINT=@XMLLINT@
export XSLTPROC=@XSLTPROC@
export PYTEST=@PYTEST@
#
# Interpreters for system tests detected by configure
#
export PERL=$(command -v "@PERL@" || true)
if ! test -x "$PERL"; then
echo "Perl interpreter is required for system tests."
exit 77
fi
export PYTHON=$(command -v "@PYTHON@" || true)
if ! test -x "$PYTHON"; then
echo "Python interpreter is required for system tests."
exit 77
fi
# Load common values
. $TOP_SRCDIR/bin/tests/system/conf.sh.common

View File

@@ -17,13 +17,14 @@ import shutil
import subprocess
import tempfile
import time
from typing import Any, Dict, List, Optional
from typing import Any, List, Optional
import pytest
pytest.register_assert_rewrite("isctest")
import isctest
from isctest.vars.dirs import SYSTEM_TEST_DIR_GIT_PATH
# Silence warnings caused by passing a pytest fixture to another fixture.
@@ -32,6 +33,7 @@ import isctest
isctest.log.init_conftest_logger()
isctest.log.avoid_duplicated_logs()
isctest.vars.init_vars()
# ----------------- Older pytest / xdist compatibility -------------------
# As of 2023-01-11, the minimal supported pytest / xdist versions are
@@ -52,9 +54,6 @@ else:
XDIST_WORKER = os.environ.get("PYTEST_XDIST_WORKER", "")
FILE_DIR = os.path.abspath(Path(__file__).parent)
ENV_RE = re.compile(b"([^=]+)=(.*)")
PORT_MIN = 5001
PORT_MAX = 32767
PORTS_PER_TEST = 20
PRIORITY_TESTS = [
# Tests that are scheduled first. Speeds up parallel execution.
"rpz/",
@@ -64,48 +63,13 @@ PRIORITY_TESTS = [
"upforwd/",
]
PRIORITY_TESTS_RE = re.compile("|".join(PRIORITY_TESTS))
SYSTEM_TEST_DIR_GIT_PATH = "bin/tests/system"
SYSTEM_TEST_NAME_RE = re.compile(f"{SYSTEM_TEST_DIR_GIT_PATH}" + r"/([^/]+)")
SYMLINK_REPLACEMENT_RE = re.compile(r"/tests(_.*)\.py")
# ---------------------- Module initialization ---------------------------
# ----------------------- Global requirements ----------------------------
def parse_env(env_bytes):
"""Parse the POSIX env format into Python dictionary."""
out = {}
for line in env_bytes.splitlines():
match = ENV_RE.match(line)
if match:
# EL8+ workaround for https://access.redhat.com/solutions/6994985
# FUTURE: can be removed when we no longer need to parse env vars
if match.groups()[0] in [b"which_declare", b"BASH_FUNC_which%%"]:
continue
out[match.groups()[0]] = match.groups()[1]
return out
def get_env_bytes(cmd):
try:
proc = subprocess.run(
[cmd],
shell=True,
check=True,
cwd=FILE_DIR,
stdout=subprocess.PIPE,
)
except subprocess.CalledProcessError as exc:
isctest.log.error("failed to get shell env: %s", exc)
raise exc
env_bytes = proc.stdout
return parse_env(env_bytes)
# Read common environment variables for running tests from conf.sh.
# FUTURE: Remove conf.sh entirely and define all variables in pytest only.
CONF_ENV = get_env_bytes(". ./conf.sh && env")
os.environb.update(CONF_ENV)
isctest.log.debug("variables in env: %s", ", ".join([str(key) for key in CONF_ENV]))
isctest.check.is_executable(isctest.vars.ALL["PYTHON"], "Python interpreter required")
isctest.check.is_executable(isctest.vars.ALL["PERL"], "Perl interpreter required")
# --------------------------- pytest hooks -------------------------------
@@ -236,8 +200,10 @@ def module_base_ports(modules):
exactly what happens - every worker thread will call this fixture to
determine test ports.
"""
port_min = PORT_MIN
port_max = PORT_MAX - len(modules) * PORTS_PER_TEST
port_min = isctest.vars.ports.PORT_MIN
port_max = (
isctest.vars.ports.PORT_MAX - len(modules) * isctest.vars.ports.PORTS_PER_TEST
)
if port_max < port_min:
raise RuntimeError("not enough ports to assign unique port set to each module")
@@ -249,65 +215,38 @@ def module_base_ports(modules):
# be misleading.
base_port = int(time.time() // 3600) % (port_max - port_min) + port_min
return {mod: base_port + i * PORTS_PER_TEST for i, mod in enumerate(modules)}
return {
mod: base_port + i * isctest.vars.ports.PORTS_PER_TEST
for i, mod in enumerate(modules)
}
@pytest.fixture(scope="module")
@pytest.fixture(autouse=True, scope="module")
def base_port(request, module_base_ports):
"""Start of the port range assigned to a particular test module."""
port = module_base_ports[request.fspath]
isctest.vars.ports.set_base_port(port)
return port
@pytest.fixture(scope="module")
def ports(base_port):
"""Dictionary containing port names and their assigned values."""
return {
"PORT": base_port,
"TLSPORT": base_port + 1,
"HTTPPORT": base_port + 2,
"HTTPSPORT": base_port + 3,
"EXTRAPORT1": base_port + 4,
"EXTRAPORT2": base_port + 5,
"EXTRAPORT3": base_port + 6,
"EXTRAPORT4": base_port + 7,
"EXTRAPORT5": base_port + 8,
"EXTRAPORT6": base_port + 9,
"EXTRAPORT7": base_port + 10,
"EXTRAPORT8": base_port + 11,
"CONTROLPORT": base_port + 12,
}
def named_port():
return int(os.environ["PORT"])
@pytest.fixture(scope="module")
def named_port(ports):
return ports["PORT"]
def named_tlsport():
return int(os.environ["TLSPORT"])
@pytest.fixture(scope="module")
def named_tlsport(ports):
return ports["TLSPORT"]
def named_httpsport():
return int(os.environ["HTTPSPORT"])
@pytest.fixture(scope="module")
def named_httpsport(ports):
return ports["HTTPSPORT"]
@pytest.fixture(scope="module")
def control_port(ports):
return ports["CONTROLPORT"]
@pytest.fixture(scope="module")
def env(ports):
"""Dictionary containing environment variables for the test."""
env = os.environ.copy()
for portname, portnum in ports.items():
env[portname] = str(portnum)
env["builddir"] = f"{env['TOP_BUILDDIR']}/{SYSTEM_TEST_DIR_GIT_PATH}"
env["srcdir"] = f"{env['TOP_SRCDIR']}/{SYSTEM_TEST_DIR_GIT_PATH}"
return env
def control_port():
return int(os.environ["CONTROLPORT"])
@pytest.fixture(scope="module")
@@ -348,7 +287,7 @@ def logger(request, system_test_name):
@pytest.fixture(scope="module")
def system_test_dir(
request, env, system_test_name
request, system_test_name
): # pylint: disable=too-many-statements,too-many-locals
"""
Temporary directory for executing the test.
@@ -398,12 +337,13 @@ def system_test_dir(
pass
# Create a temporary directory with a copy of the original system test dir contents
system_test_root = Path(f"{env['TOP_BUILDDIR']}/{SYSTEM_TEST_DIR_GIT_PATH}")
system_test_root = Path(os.environ["builddir"])
testdir = Path(
tempfile.mkdtemp(prefix=f"{system_test_name}_tmp_", dir=system_test_root)
)
shutil.rmtree(testdir)
shutil.copytree(system_test_root / system_test_name, testdir)
isctest.vars.dirs.set_system_test_name(testdir.name)
# Create a convenience symlink with a stable and predictable name
module_name = SYMLINK_REPLACEMENT_RE.sub(r"\1", request.node.name)
@@ -458,7 +398,6 @@ def system_test_dir(
def _run_script( # pylint: disable=too-many-arguments
env,
system_test_dir: Path,
interpreter: str,
script: str,
@@ -482,7 +421,6 @@ def _run_script( # pylint: disable=too-many-arguments
cmd = [interpreter, script] + args
with subprocess.Popen(
cmd,
env=env,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
bufsize=1,
@@ -500,15 +438,15 @@ def _run_script( # pylint: disable=too-many-arguments
@pytest.fixture(scope="module")
def shell(env, system_test_dir):
def shell(system_test_dir):
"""Function to call a shell script with arguments."""
return partial(_run_script, env, system_test_dir, env["SHELL"])
return partial(_run_script, system_test_dir, os.environ["SHELL"])
@pytest.fixture(scope="module")
def perl(env, system_test_dir):
def perl(system_test_dir):
"""Function to call a perl script with arguments."""
return partial(_run_script, env, system_test_dir, env["PERL"])
return partial(_run_script, system_test_dir, os.environ["PERL"])
@pytest.fixture(scope="module")
@@ -524,7 +462,6 @@ def run_tests_sh(system_test_dir, shell):
@pytest.fixture(scope="module", autouse=True)
def system_test( # pylint: disable=too-many-arguments,too-many-statements
request,
env: Dict[str, str],
system_test_dir,
shell,
perl,
@@ -553,7 +490,7 @@ def system_test( # pylint: disable=too-many-arguments,too-many-statements
def check_net_interfaces():
try:
perl("testsock.pl", ["-p", env["PORT"]])
perl("testsock.pl", ["-p", os.environ["PORT"]])
except subprocess.CalledProcessError as exc:
isctest.log.error("testsock.pl: exited with code %d", exc.returncode)
pytest.skip("Network interface aliases not set up.")
@@ -577,7 +514,7 @@ def system_test( # pylint: disable=too-many-arguments,too-many-statements
def start_servers():
try:
perl("start.pl", ["--port", env["PORT"], system_test_dir.name])
perl("start.pl", ["--port", os.environ["PORT"], system_test_dir.name])
except subprocess.CalledProcessError as exc:
isctest.log.error("Failed to start servers")
pytest.fail(f"start.pl exited with {exc.returncode}")
@@ -597,10 +534,11 @@ def system_test( # pylint: disable=too-many-arguments,too-many-statements
isctest.log.error("Found core dumps or sanitizer reports")
pytest.fail(f"get_core_dumps.sh exited with {exc.returncode}")
os.environ.update(env) # Ensure pytests have the same env vars as shell tests.
isctest.log.info(f"test started: {request.node.name}")
port = int(env["PORT"])
isctest.log.info("using port range: <%d, %d>", port, port + PORTS_PER_TEST - 1)
port = int(os.environ["PORT"])
isctest.log.info(
"using port range: <%d, %d>", port, port + isctest.vars.ports.PORTS_PER_TEST - 1
)
if not hasattr(request.node, "stash"): # compatibility with pytest<7.0.0
request.node.stash = {} # use regular dict instead of pytest.Stash
@@ -628,17 +566,13 @@ def system_test( # pylint: disable=too-many-arguments,too-many-statements
@pytest.fixture
def servers(ports, system_test_dir):
def servers(system_test_dir):
instances = {}
for entry in system_test_dir.rglob("*"):
if entry.is_dir():
try:
dir_name = entry.name
# LATER: Make ports fixture return NamedPorts directly
named_ports = isctest.instance.NamedPorts(
dns=int(ports["PORT"]), rndc=int(ports["CONTROLPORT"])
)
instance = isctest.instance.NamedInstance(dir_name, named_ports)
instance = isctest.instance.NamedInstance(dir_name)
instances[dir_name] = instance
except ValueError:
continue

View File

@@ -23,7 +23,6 @@
exit 255
}
parse_openssl_config
[ -f "$SOFTHSM2_MODULE" ] || {
echo_i "skip: softhsm2 module not available"
exit 1

View File

@@ -20,7 +20,6 @@ $SHELL clean.sh
OPENSSL_CONF= softhsm2-util --init-token --free --pin 1234 --so-pin 1234 --label "softhsm2-enginepkcs11" | awk '/^The token has been initialized and is reassigned to slot/ { print $NF }'
parse_openssl_config
printf '%s' "${HSMPIN:-1234}" >ns1/pin
PWD=$(pwd)

View File

@@ -16,7 +16,6 @@ set -e
# shellcheck source=conf.sh
. ../conf.sh
parse_openssl_config
PWD=$(pwd)
status=0

View File

@@ -15,6 +15,7 @@ from . import query
from . import rndc
from . import run
from . import log
from . import vars # pylint: disable=redefined-builtin
# isctest.mark module is intentionally NOT imported, because it relies on
# environment variables which might not be set at the time of import of the

View File

@@ -0,0 +1,17 @@
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# SPDX-License-Identifier: MPL-2.0
#
# 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 https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
from .vars import ALL
if __name__ == "__main__":
for name, value in ALL.items():
print(f"export {name}={value}")

View File

@@ -9,6 +9,7 @@
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
import shutil
from typing import Any, Optional
import dns.rcode
@@ -95,3 +96,8 @@ def zones_equal(
)
assert found_rdataset
assert found_rdataset.ttl == rdataset.ttl
def is_executable(cmd: str, errmsg: str) -> None:
executable = shutil.which(cmd)
assert executable is not None, errmsg

View File

@@ -25,6 +25,13 @@ class NamedPorts(NamedTuple):
dns: int = 53
rndc: int = 953
@staticmethod
def from_env():
return NamedPorts(
dns=int(os.environ["PORT"]),
rndc=int(os.environ["CONTROLPORT"]),
)
class NamedInstance:
"""
@@ -42,7 +49,7 @@ class NamedInstance:
def __init__(
self,
identifier: str,
ports: NamedPorts = NamedPorts(),
ports: Optional[NamedPorts] = None,
rndc_logger: Optional[logging.Logger] = None,
rndc_executor: Optional[RNDCExecutor] = None,
) -> None:
@@ -52,7 +59,8 @@ class NamedInstance:
`ports` is the `NamedPorts` instance listing the UDP/TCP ports on which
this `named` instance is listening for various types of traffic (both
DNS traffic and RNDC commands).
DNS traffic and RNDC commands). Defaults to ports set by the test
framework.
`rndc_logger` is the `logging.Logger` to use for logging RNDC
commands sent to this `named` instance.
@@ -61,6 +69,8 @@ class NamedInstance:
that is used for executing RNDC commands on this `named` instance.
"""
self.ip = self._identifier_to_ip(identifier)
if ports is None:
ports = NamedPorts.from_env()
self.ports = ports
self.log = LogFile(os.path.join(identifier, "named.run"))
self._rndc_executor = rndc_executor or RNDCBinaryExecutor()

View File

@@ -0,0 +1 @@
@CURL@

View File

@@ -0,0 +1 @@
@FSTRM_CAPTURE@

View File

@@ -0,0 +1 @@
@NC@

View File

@@ -0,0 +1 @@
@PERL@

View File

@@ -0,0 +1 @@
@PYTEST@

View File

@@ -0,0 +1 @@
@PYTHON@

View File

@@ -0,0 +1 @@
@SHELL@

View File

@@ -0,0 +1 @@
@abs_top_builddir@

View File

@@ -0,0 +1 @@
@abs_top_srcdir@

View File

@@ -0,0 +1 @@
@XSLTPROC@

View File

@@ -0,0 +1,24 @@
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# SPDX-License-Identifier: MPL-2.0
#
# 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 https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
import os
from .all import ALL
from .openssl import parse_openssl_config
from .. import log
def init_vars():
"""Initializes the environment variables."""
parse_openssl_config(ALL["OPENSSL_CONF"])
os.environ.update(ALL)
log.debug("setting following env vars: %s", ", ".join([str(key) for key in ALL]))

View File

@@ -0,0 +1,55 @@
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# SPDX-License-Identifier: MPL-2.0
#
# 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 https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
from collections import ChainMap
# pylint: disable=import-error
from .autoconf import AC_VARS # type: ignore
# pylint: enable=import-error
from .basic import BASIC_VARS
from .dirs import DIR_VARS
from .openssl import OPENSSL_VARS
from .ports import PORT_VARS
class VarLookup(ChainMap):
"""A dictionary-like structure to coalesce the variables from different
modules without making a copy (which would prevent updating these values
from inside the modules). Values which are None are treated as unset when
iterating."""
def __init__(self, *maps):
keys = set()
for m in maps:
overlap = keys.intersection(m.keys())
if overlap:
raise RuntimeError(f"key(s) are defined multiple times: {overlap}")
keys = keys.union(m.keys())
super().__init__(*maps)
def __setitem__(self, *args, **kwargs):
raise RuntimeError("read-only structure")
def keys(self):
result = set()
for m in self.maps:
for key, val in m.items():
if val is None: # treat None as unset
continue
result.add(key)
return list(result)
def __iter__(self):
return iter(self.keys())
ALL = VarLookup(AC_VARS, BASIC_VARS, OPENSSL_VARS, PORT_VARS, DIR_VARS)

View File

@@ -0,0 +1,29 @@
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# SPDX-License-Identifier: MPL-2.0
#
# 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 https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
from pathlib import Path
from typing import Dict
def load_ac_vars_from_files() -> Dict[str, str]:
ac_vars = {}
ac_vars_dir = Path(__file__).resolve().parent / ".ac_vars"
var_paths = [
path
for path in ac_vars_dir.iterdir()
if path.is_file() and not path.name.endswith(".in")
]
for var_path in var_paths:
ac_vars[var_path.name] = var_path.read_text(encoding="utf-8").strip()
return ac_vars
AC_VARS = load_ac_vars_from_files()

View File

@@ -0,0 +1,64 @@
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# SPDX-License-Identifier: MPL-2.0
#
# 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 https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
import os
# pylint: disable=import-error
from .autoconf import AC_VARS # type: ignore
# pylint: enable=import-error
BASIC_VARS = {
"ARPANAME": f"{AC_VARS['TOP_BUILDDIR']}/bin/tools/arpaname",
"CDS": f"{AC_VARS['TOP_BUILDDIR']}/bin/dnssec/dnssec-cds",
"CHECKCONF": f"{AC_VARS['TOP_BUILDDIR']}/bin/check/named-checkconf",
"CHECKZONE": f"{AC_VARS['TOP_BUILDDIR']}/bin/check/named-checkzone",
"DIG": f"{AC_VARS['TOP_BUILDDIR']}/bin/dig/dig",
"DNSTAPREAD": f"{AC_VARS['TOP_BUILDDIR']}/bin/tools/dnstap-read",
"DSFROMKEY": f"{AC_VARS['TOP_BUILDDIR']}/bin/dnssec/dnssec-dsfromkey",
"FEATURETEST": f"{AC_VARS['TOP_BUILDDIR']}/bin/tests/system/feature-test",
"HOST": f"{AC_VARS['TOP_BUILDDIR']}/bin/dig/host",
"IMPORTKEY": f"{AC_VARS['TOP_BUILDDIR']}/bin/dnssec/dnssec-importkey",
"JOURNALPRINT": f"{AC_VARS['TOP_BUILDDIR']}/bin/tools/named-journalprint",
"KEYFRLAB": f"{AC_VARS['TOP_BUILDDIR']}/bin/dnssec/dnssec-keyfromlabel",
"KEYGEN": f"{AC_VARS['TOP_BUILDDIR']}/bin/dnssec/dnssec-keygen",
"KSR": f"{AC_VARS['TOP_BUILDDIR']}/bin/dnssec/dnssec-ksr",
"MDIG": f"{AC_VARS['TOP_BUILDDIR']}/bin/tools/mdig",
"NAMED": f"{AC_VARS['TOP_BUILDDIR']}/bin/named/named",
"NSEC3HASH": f"{AC_VARS['TOP_BUILDDIR']}/bin/tools/nsec3hash",
"NSLOOKUP": f"{AC_VARS['TOP_BUILDDIR']}/bin/dig/nslookup",
"NSUPDATE": f"{AC_VARS['TOP_BUILDDIR']}/bin/nsupdate/nsupdate",
"NZD2NZF": f"{AC_VARS['TOP_BUILDDIR']}/bin/tools/named-nzd2nzf",
"REVOKE": f"{AC_VARS['TOP_BUILDDIR']}/bin/dnssec/dnssec-revoke",
"RNDC": f"{AC_VARS['TOP_BUILDDIR']}/bin/rndc/rndc",
"RNDCCONFGEN": f"{AC_VARS['TOP_BUILDDIR']}/bin/confgen/rndc-confgen",
"RRCHECKER": f"{AC_VARS['TOP_BUILDDIR']}/bin/tools/named-rrchecker",
"SETTIME": f"{AC_VARS['TOP_BUILDDIR']}/bin/dnssec/dnssec-settime",
"SIGNER": f"{AC_VARS['TOP_BUILDDIR']}/bin/dnssec/dnssec-signzone",
"TSIGKEYGEN": f"{AC_VARS['TOP_BUILDDIR']}/bin/confgen/tsig-keygen",
"VERIFY": f"{AC_VARS['TOP_BUILDDIR']}/bin/dnssec/dnssec-verify",
"WIRETEST": f"{AC_VARS['TOP_BUILDDIR']}/bin/tests/wire_test",
"BIGKEY": f"{AC_VARS['TOP_BUILDDIR']}/bin/tests/system/rsabigexponent/bigkey",
"GENCHECK": f"{AC_VARS['TOP_BUILDDIR']}/bin/tests/system/rndc/gencheck",
"MAKEJOURNAL": f"{AC_VARS['TOP_BUILDDIR']}/bin/tests/system/makejournal",
"PIPEQUERIES": f"{AC_VARS['TOP_BUILDDIR']}/bin/tests/system/pipelined/pipequeries",
"TMPDIR": os.getenv("TMPDIR", "/tmp"),
"KRB5_CONFIG": "/dev/null", # we don't want a KRB5_CONFIG setting breaking the tests
"KRB5_KTNAME": "dns.keytab", # use local keytab instead of default /etc/krb5.keytab
"DELV": (
f"{AC_VARS['TOP_BUILDDIR']}/bin/delv/delv"
if not os.getenv("TSAN_OPTIONS", "")
else ":" # workaround for GL#4119
),
"LANG": "C",
"ANS_LOG_LEVEL": "debug",
}

View File

@@ -0,0 +1,31 @@
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# SPDX-License-Identifier: MPL-2.0
#
# 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 https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
import os
# pylint: disable=import-error
from .autoconf import AC_VARS # type: ignore
# pylint: enable=import-error
SYSTEM_TEST_DIR_GIT_PATH = "bin/tests/system"
DIR_VARS = {
"builddir": f"{AC_VARS['TOP_BUILDDIR']}/{SYSTEM_TEST_DIR_GIT_PATH}",
"srcdir": f"{AC_VARS['TOP_SRCDIR']}/{SYSTEM_TEST_DIR_GIT_PATH}",
"SYSTESTDIR": None,
}
def set_system_test_name(name: str):
DIR_VARS["SYSTESTDIR"] = name
os.environ["SYSTESTDIR"] = name

View File

@@ -0,0 +1,53 @@
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# SPDX-License-Identifier: MPL-2.0
#
# 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 https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
import os
import re
from typing import Optional
from .. import log
OPENSSL_VARS = {
"OPENSSL_CONF": os.getenv("OPENSSL_CONF", None),
"SOFTHSM2_CONF": os.getenv("SOFTHSM2_CONF", None),
"SOFTHSM2_MODULE": None,
"ENGINE_ARG": None,
}
def parse_openssl_config(path: Optional[str]):
if path is None or not os.path.exists(path):
OPENSSL_VARS["ENGINE_ARG"] = None
OPENSSL_VARS["SOFTHSM2_MODULE"] = None
os.environ.pop("ENGINE_ARG", None)
os.environ.pop("SOFTHSM2_MODULE", None)
return
assert os.path.isfile(path), f"{path} exists, but it's not a file"
regex = re.compile(r"([^=]+)=(.*)")
log.debug(f"parsing openssl config: {path}")
with open(path, "r", encoding="utf-8") as conf:
for line in conf:
res = regex.match(line)
if res:
key = res.group(1).strip()
val = res.group(2).strip()
if key == "engine_id":
OPENSSL_VARS["ENGINE_ARG"] = f"-E {val}"
os.environ["ENGINE_ARG"] = f"-E {val}"
log.debug("ENGINE_ARG set to {OPENSSL_VARS['ENGINE_ARG']}")
elif key in ["MODULE_PATH", "pkcs11-module-path"]:
OPENSSL_VARS["SOFTHSM2_MODULE"] = val
os.environ["SOFTHSM2_MODULE"] = val
log.debug(
"SOFTHSM2_MODULE set to {OPENSSL_VARS['SOFTHSM2_MODULE']}"
)

View File

@@ -0,0 +1,54 @@
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# SPDX-License-Identifier: MPL-2.0
#
# 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 https://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
import os
from .. import log
PORT_MIN = 5001
PORT_MAX = 32767
PORTS_PER_TEST = 20
PORT_VARS = {
"PORT": "5300",
"TLSPORT": "5301",
"HTTPPORT": "5302",
"HTTPSPORT": "5303",
"EXTRAPORT1": "5304",
"EXTRAPORT2": "5305",
"EXTRAPORT3": "5306",
"EXTRAPORT4": "5307",
"EXTRAPORT5": "5308",
"EXTRAPORT6": "5309",
"EXTRAPORT7": "5310",
"EXTRAPORT8": "5311",
"CONTROLPORT": "5312",
}
def set_base_port(base_port: int):
log.debug(f"setting base port {base_port}")
assert base_port >= PORT_MIN
assert base_port <= PORT_MAX
PORT_VARS["PORT"] = str(base_port)
PORT_VARS["TLSPORT"] = str(base_port + 1)
PORT_VARS["HTTPPORT"] = str(base_port + 2)
PORT_VARS["HTTPSPORT"] = str(base_port + 3)
PORT_VARS["EXTRAPORT1"] = str(base_port + 4)
PORT_VARS["EXTRAPORT2"] = str(base_port + 5)
PORT_VARS["EXTRAPORT3"] = str(base_port + 6)
PORT_VARS["EXTRAPORT4"] = str(base_port + 7)
PORT_VARS["EXTRAPORT5"] = str(base_port + 8)
PORT_VARS["EXTRAPORT6"] = str(base_port + 9)
PORT_VARS["EXTRAPORT7"] = str(base_port + 10)
PORT_VARS["EXTRAPORT8"] = str(base_port + 11)
PORT_VARS["CONTROLPORT"] = str(base_port + 12)
os.environ.update(PORT_VARS)

View File

@@ -18,7 +18,6 @@
exit 255
}
parse_openssl_config
[ -f "$SOFTHSM2_MODULE" ] || {
echo_i "skip: softhsm2 module not available"
exit 1

View File

@@ -16,7 +16,6 @@ set -e
# shellcheck source=conf.sh
. ../conf.sh
parse_openssl_config
PWD=$(pwd)
keygen() {

View File

@@ -13,8 +13,6 @@
. ../../conf.sh
SYSTESTDIR=legacy
echo_i "sign edns512"
zone=edns512

View File

@@ -13,8 +13,6 @@
. ../../conf.sh
SYSTESTDIR=legacy
echo_i "sign edns512-notcp"
zone=edns512-notcp

View File

@@ -170,7 +170,7 @@ def wait_for_proc_termination(proc, max_timeout=10):
"kill_method",
["rndc", "sigterm"],
)
def test_named_shutdown(ports, kill_method):
def test_named_shutdown(kill_method):
# pylint: disable-msg=too-many-locals
cfg_dir = os.path.join(os.getcwd(), "resolver")
assert os.path.isdir(cfg_dir)
@@ -186,9 +186,7 @@ def test_named_shutdown(ports, kill_method):
# necessary for sending RNDC commands to that instance. This "custom"
# instance listens on 10.53.0.3, so use "ns3" as the identifier passed to
# the NamedInstance constructor.
named_ports = isctest.instance.NamedPorts(
dns=ports["PORT"], rndc=ports["CONTROLPORT"]
)
named_ports = isctest.instance.NamedPorts.from_env()
instance = isctest.instance.NamedInstance("ns3", named_ports)
# We create a resolver instance that will be used to send queries.

View File

@@ -9,9 +9,11 @@
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
import os
import pytest
@pytest.fixture(scope="module")
def statsport(ports):
return ports["EXTRAPORT1"]
def statsport():
return int(os.environ["EXTRAPORT1"])

View File

@@ -13,8 +13,6 @@
. ../../conf.sh
SYSTESTDIR=verify
dumpit() {
echo_d "${debug}: dumping ${1}"
cat "${1}" | cat_d

View File

@@ -13,8 +13,6 @@
. ../../conf.sh
SYSTESTDIR=wildcard
dssets=
# RFC 4592 example zone.

View File

@@ -1656,7 +1656,16 @@ AC_CONFIG_FILES([tests/unit-test-driver.sh],
AC_CONFIG_FILES([bin/tests/Makefile
bin/tests/system/Makefile
bin/tests/system/conf.sh
bin/tests/system/isctest/vars/.ac_vars/TOP_BUILDDIR
bin/tests/system/isctest/vars/.ac_vars/TOP_SRCDIR
bin/tests/system/isctest/vars/.ac_vars/FSTRM_CAPTURE
bin/tests/system/isctest/vars/.ac_vars/SHELL
bin/tests/system/isctest/vars/.ac_vars/PYTHON
bin/tests/system/isctest/vars/.ac_vars/PERL
bin/tests/system/isctest/vars/.ac_vars/CURL
bin/tests/system/isctest/vars/.ac_vars/NC
bin/tests/system/isctest/vars/.ac_vars/XSLTPROC
bin/tests/system/isctest/vars/.ac_vars/PYTEST
bin/tests/system/dyndb/driver/Makefile
bin/tests/system/dlzexternal/driver/Makefile
bin/tests/system/hooks/driver/Makefile