Skip to content

Commit

Permalink
tests: use "local" variables
Browse files Browse the repository at this point in the history
POSIX sh does not include local variables [1], so we're switching to the
convention of using:
    _func_var_name
for local function variable names, so that we always have distinct names.

This does lead to rather verbose variable names, but this is an
acceptable trade-off in order to have correct program behaviour.

[1] Adding "local" to POSIX was discussed, but rejected, in:
    https://www.austingroupbugs.net/view.php?id=767
    It's possible to get "local variables" by abusing eval, but those
    solutions don't look appealing.
  • Loading branch information
gperciva committed Oct 14, 2023
1 parent 433bd42 commit 171627a
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 147 deletions.
123 changes: 65 additions & 58 deletions tests/shared_test_functions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ _prepdir() {
## find_system (cmd, args):
# Look for ${cmd} in the ${PATH}, and ensure that it supports ${args}.
find_system() {
cmd=$1
cmd_with_args="$1 ${2:-}"
_find_system_cmd=$1
_find_system_cmd_with_args="$1 ${2:-}"

# Sanity check.
if [ "$#" -gt "2" ]; then
Expand All @@ -106,26 +106,28 @@ find_system() {
fi

# Look for ${cmd}; the "|| true" and -} make this work with set -e.
system_binary=$(command -v "${cmd}") || true
if [ -z "${system_binary-}" ]; then
system_binary=""
printf "System %s not found.\n" "${cmd}" 1>&2
_find_system_binary=$(command -v "${_find_system_cmd}") || true
if [ -z "${_find_system_binary-}" ]; then
_find_system_binary=""
printf "System %s not found.\n" "${_find_system_cmd}" 1>&2
# If the command exists, check it ensures the ${args}.
elif ${cmd_with_args} 2>&1 >/dev/null | \
elif ${_find_system_cmd_with_args} 2>&1 >/dev/null | \
grep -qE "(invalid|illegal) option"; then
system_binary=""
printf "Cannot use system %s; does not" "${cmd}" 1>&2
_find_system_binary=""
printf "Cannot use system %s; does not" \
"${_find_system_cmd}" 1>&2
printf " support necessary arguments.\n" 1>&2
fi
echo "${system_binary}"
echo "${_find_system_binary}"
}

## has_pid (cmd):
# Look for ${cmd} in ps; return 0 if ${cmd} exists.
has_pid() {
cmd=$1
pid=$(ps -Aopid,args | grep -F "${cmd}" | grep -v "grep") || true
if [ -n "${pid}" ]; then
_has_pid_cmd=$1
_has_pid_pid=$(ps -Aopid,args | grep -F "${_has_pid_cmd}" | \
grep -v "grep") || true
if [ -n "${_has_pid_pid}" ]; then
return 0
fi
return 1
Expand Down Expand Up @@ -167,12 +169,12 @@ wait_while() {
# file. If ${check_prev} is non-zero, check that the previous
# ${c_exitfile} exists.
setup_check() {
description=$1
check_prev=${2:-1}
_setup_check_description=$1
_setup_check_prev=${2:-1}

# Should we check for the previous exitfile?
if [ "${c_exitfile}" != "${NO_EXITFILE}" ] && \
[ "${check_prev}" -gt 0 ] ; then
[ "${_setup_check_prev}" -gt 0 ] ; then
# Check for the file.
if [ ! -f "${c_exitfile}" ] ; then
# We should have written the result of the
Expand All @@ -188,7 +190,7 @@ setup_check() {
c_exitfile="${s_basename}-${c_count_str}.exit"

# Write the "description" file.
printf "%s\n" "${description}" > \
printf "%s\n" "${_setup_check_description}" > \
"${s_basename}-${c_count_str}.desc"

# Set up the valgrind command (or an empty string).
Expand All @@ -203,12 +205,14 @@ setup_check() {
# ${valgrind_exit_code}, return that. Otherwise, return 1 to indicate
# failure.
expected_exitcode() {
expected=$1
exitcode=$2
_expected_exitcode_expected=$1
_expected_exitcode_exitcode=$2

if [ "${exitcode}" -eq "${expected}" ]; then
if [ "${_expected_exitcode_exitcode}" -eq \
"${_expected_exitcode_expected}" ]; then
echo "0"
elif [ "${exitcode}" -eq "${valgrind_exit_code}" ]; then
elif [ "${_expected_exitcode_exitcode}" -eq \
"${valgrind_exit_code}" ]; then
echo "${valgrind_exit_code}"
else
echo "1"
Expand All @@ -223,60 +227,62 @@ expected_exitcode() {
# logfile. If the test failed and ${VERBOSE} is non-zero, print
# the description to stderr.
_check() {
log_basename=$1
val_log_basename=$2
_check_log_basename=$1
_check_val_log_basename=$2

# Bail if there's no exitfiles.
exitfiles=$(ls "${log_basename}"-*.exit) || true
if [ -z "${exitfiles}" ]; then
_check_exitfiles=$(ls "${_check_log_basename}"-*.exit) || true
if [ -z "${_check_exitfiles}" ]; then
echo "FAILED" 1>&2
s_retval=1
return
fi

# Count results
total_exitfiles=0
skip_exitfiles=0
_check_total=0
_check_skip=0

# Check each exitfile.
for exitfile in $(echo "${exitfiles}" | sort); do
ret=$(cat "${exitfile}")
total_exitfiles=$(( total_exitfiles + 1 ))
if [ "${ret}" -lt 0 ]; then
skip_exitfiles=$(( skip_exitfiles + 1 ))
for _check_exitfile in $(echo "${_check_exitfiles}" | sort); do
_check_ret=$(cat "${_check_exitfile}")
_check_total=$(( _check_total + 1 ))
if [ "${_check_ret}" -lt 0 ]; then
_check_skip=$(( _check_skip + 1 ))
fi

# Check for test failure.
descfile=$(echo "${exitfile}" | sed 's/\.exit/\.desc/g')
if [ "${ret}" -gt 0 ]; then
_check_descfile=$(echo "${_check_exitfile}" \
| sed 's/\.exit/\.desc/g')
if [ "${_check_ret}" -gt 0 ]; then
echo "FAILED!" 1>&2
if [ "${VERBOSE}" -ne 0 ]; then
printf "File %s contains exit code %s.\n" \
"${exitfile}" "${ret}" 1>&2
"${_check_exitfile}" "${_check_ret}" \
1>&2
printf "Test description: " 1>&2
cat "${descfile}" 1>&2
cat "${_check_descfile}" 1>&2
fi
s_retval=${ret}
s_retval=${_check_ret}
return
else
# If there's no failure, delete the files.
rm "${exitfile}"
rm "${descfile}"
rm "${_check_exitfile}"
rm "${_check_descfile}"
fi

# Check valgrind logfile(s).
val_failed="$(valgrind_check "${exitfile}")"
if [ -n "${val_failed}" ]; then
_check_val_failed="$(valgrind_check "${_check_exitfile}")"
if [ -n "${_check_val_failed}" ]; then
echo "FAILED!" 1>&2
s_retval="${valgrind_exit_code}"
cat "${val_failed}" 1>&2
cat "${_check_val_failed}" 1>&2
return
fi
done

# Notify about skip or success.
if [ "${skip_exitfiles}" -gt 0 ]; then
if [ "${skip_exitfiles}" -eq "${total_exitfiles}" ]; then
if [ "${_check_skip}" -gt 0 ]; then
if [ "${_check_skip}" -eq "${_check_total}" ]; then
echo "SKIP!" 1>&2
else
echo "PARTIAL SUCCESS / SKIP!" 1>&2
Expand All @@ -289,24 +295,24 @@ _check() {
## _scenario_runner (scenario_filename):
# Run a test scenario from ${scenario_filename}.
_scenario_runner() {
scenario_filename=$1
basename=$(basename "${scenario_filename}" .sh)
printf " %s... " "${basename}" 1>&2
_scenario_runner_filename=$1
_scenario_runner_basename=$(basename "${_scenario_runner_filename}" .sh)
printf " %s... " "${_scenario_runner_basename}" 1>&2

# Initialize "scenario" and "check" variables.
s_basename=${out}/${basename}
s_val_basename=${out_valgrind}/${basename}
s_basename=${out}/${_scenario_runner_basename}
s_val_basename=${out_valgrind}/${_scenario_runner_basename}
c_count_next=0
c_exitfile="${NO_EXITFILE}"
c_valgrind_min=9
c_valgrind_cmd=""

# Load scenario_cmd() from the scenario file.
unset scenario_cmd
. "${scenario_filename}"
. "${_scenario_runner_filename}"
if ! command -v scenario_cmd 1>/dev/null ; then
printf "ERROR: scenario_cmd() is not defined in\n" 1>&2
printf " %s\n" "${scenario_filename}" 1>&2
printf " %s\n" "${_scenario_runner_filename}" 1>&2
exit 1
fi

Expand All @@ -326,9 +332,10 @@ _scenario_runner() {
run_scenarios() {
# Get the test number(s) to run.
if [ "${N:-0}" -gt "0" ]; then
test_scenarios="$(printf "${scriptdir}/%02d-*.sh" "${N}")"
_run_scenarios_filenames="$(printf \
"${scriptdir}/%02d-*.sh" "${N}")"
else
test_scenarios="${scriptdir}/??-*.sh"
_run_scenarios_filenames="${scriptdir}/??-*.sh"
fi

# Clean up any previous directory, and create a new one.
Expand All @@ -340,13 +347,13 @@ run_scenarios() {

printf -- "Running tests\n" 1>&2
printf -- "-------------\n" 1>&2
for scenario in ${test_scenarios}; do
for _run_scenarios_filename in ${_run_scenarios_filenames}; do
# We can't call this function with $( ... ) because we
# want to allow it to echo values to stdout.
_scenario_runner "${scenario}"
retval=$?
if [ "${retval}" -gt 0 ]; then
exit "${retval}"
_scenario_runner "${_run_scenarios_filename}"
_run_scenarios_retval=$?
if [ "${_run_scenarios_retval}" -gt 0 ]; then
exit "${_run_scenarios_retval}"
fi
done
}
Loading

0 comments on commit 171627a

Please sign in to comment.