# SC2154: ... is referenced but not assigned.
# Reason: some variables are taken from keactrl.conf
+# Exit with error if commands exit with non-zero and if undefined variables are
+# used.
+set -eu
+
VERSION="@PACKAGE_VERSION@"
# Set the have_netconf flag to know if netconf is available.
# is to determine whether the keactrl command belongs to the list of
# supported commands.
is_in_list() {
- local member=${1} # Value to be checked
- local list="${2}" # Comma separated list of items
- _inlist=0 # Return value: 0 if not in list, 1 otherwise.
+ local member="${1-}" # Value to be checked
+ local list="${2-}" # Comma separated list of items
+ _inlist=0 # Return value: 0 if not in list, 1 otherwise.
if [ -z "${member}" ]; then
log_error "missing ${member}"
fi
# Check if the Kea configuration file location has been specified in the
# keactrl configuration file. If not, it is a warning or a fatal error.
check_kea_conf() {
- local conf_file=${1} # Kea config file name.
+ local conf_file=${1-} # Kea config file name.
if [ -z "${conf_file}" ]; then
log_error "Configuration file for Kea not specified."
exit 1
# Note that when the configuration is applied this location may be
# altered and only the handful of initial messages will be logged
# to the default file.
-if [ -z "${KEA_LOGGER_DESTINATION}" ]; then
+if [ -z "${KEA_LOGGER_DESTINATION+x}" ]; then
prefix="@prefix@"
export KEA_LOGGER_DESTINATION="@localstatedir@/log/kea.log"
fi
-command=${1}
+command=${1-}
if [ -z "${command}" ]; then
log_error "missing command"
usage
servers="all"
shift
-while [ -n "${1}" ]
+while test ${#} -gt 0
do
option=${1}
case ${option} in
# Override keactrl configuration file.
-c|--ctrl-config)
shift
- keactrl_conf=${1}
+ keactrl_conf=${1-}
if [ -z "${keactrl_conf}" ]; then
log_error "keactrl-config-file not specified"
usage
# executed.
-s|--server)
shift
- servers=$( printf "%s" "${1}" | tr "," "\n" )
+ servers=$(printf '%s' "${1-}" | tr ',' '\n')
if [ -z "${servers}" ]; then
log_error "servers not specified"
usage
# shellcheck disable=SC2154
# SC2154: netconf_srv is referenced but not assigned.
# reason: it is taken from keactrl.conf
- if [ -z "${netconf_srv}" ]; then
+ if [ -z "${netconf_srv+x}" ]; then
log_error "netconf_srv parameter not specified"
exit 1
fi
# Prints error message.
test_lib_error() {
- local s=${1} # Error message.
- local no_new_line=${2} # If specified, the message not terminated with
- # new line.
+ local s=${1-} # Error message.
+ local no_new_line=${2-} # If specified, the message not terminated with
+ # new line.
printf "ERROR/test_lib: %s" "${s}"
if [ -z "${no_new_line}" ]; then
printf '\n'
# Prints info message.
test_lib_info() {
- local s=${1} # Info message.
- local no_new_line=${2} # If specified, the message is not terminated with
- # new line.
+ local s=${1-} # Info message.
+ local no_new_line=${2-} # If specified, the message is not terminated with
+ # new line.
printf "INFO/test_lib: %s" "${s}"
if [ -z "${no_new_line}" ]; then
printf '\n'
# Begins a test by printing its name.
test_start() {
- TEST_NAME=${1}
+ TEST_NAME=${1-}
if [ -z "${TEST_NAME}" ]; then
test_lib_error "test_start requires test name as an argument"
clean_exit 1
# Stores the configuration specified as a parameter in the configuration
# file which name has been set in the ${CFG_FILE} variable.
create_config() {
- local cfg="${1}" # Configuration string.
- if [ -z "${CFG_FILE}" ]; then
+ local cfg="${1-}" # Configuration string.
+ if [ -z "${CFG_FILE+x}" ]; then
test_lib_error "create_config requires CFG_FILE variable be set"
clean_exit 1
# configuration file which name has been set in the ${DHCP4_CFG_FILE}
# variable.
create_dhcp4_config() {
- local cfg="${1}" # Configuration string.
- if [ -z "${DHCP4_CFG_FILE}" ]; then
+ local cfg="${1-}" # Configuration string.
+ if [ -z "${DHCP4_CFG_FILE+x}" ]; then
test_lib_error "create_dhcp4_config requires DHCP4_CFG_FILE \
variable be set"
clean_exit 1
# configuration file which name has been set in the ${DHCP6_CFG_FILE}
# variable.
create_dhcp6_config() {
- local cfg="${1}" # Configuration string.
- if [ -z "${DHCP6_CFG_FILE}" ]; then
+ local cfg="${1-}" # Configuration string.
+ if [ -z "${DHCP6_CFG_FILE+x}" ]; then
test_lib_error "create_dhcp6_config requires DHCP6_CFG_FILE \
variable be set"
clean_exit 1
# configuration file which name has been set in the ${D2_CFG_FILE}
# variable.
create_d2_config() {
- local cfg="${1}" # Configuration string.
- if [ -z "${D2_CFG_FILE}" ]; then
+ local cfg="${1-}" # Configuration string.
+ if [ -z "${D2_CFG_FILE+x}" ]; then
test_lib_error "create_d2_config requires D2_CFG_FILE \
variable be set"
clean_exit 1
# configuration file which name has been set in the ${CA_CFG_FILE}
# variable.
create_ca_config() {
- local cfg="${1}" # Configuration string.
- if [ -z "${CA_CFG_FILE}" ]; then
+ local cfg="${1-}" # Configuration string.
+ if [ -z "${CA_CFG_FILE+x}" ]; then
test_lib_error "create_ca_config requires CA_CFG_FILE \
variable be set"
clean_exit 1
# configuration file which name has been set in the ${NC_CFG_FILE}
# variable.
create_nc_config() {
- local cfg="${1}" # Configuration string.
- if [ -z "${NC_CFG_FILE}" ]; then
+ local cfg="${1-}" # Configuration string.
+ if [ -z "${NC_CFG_FILE+x}" ]; then
test_lib_error "create_nc_config requires NC_CFG_FILE \
variable be set"
clean_exit 1
# configuration file which name has been set in the ${KEACTRL_CFG_FILE}
# variable.
create_keactrl_config() {
- local cfg="${1}" # Configuration string.
- if [ -z "${KEACTRL_CFG_FILE}" ]; then
+ local cfg="${1-}" # Configuration string.
+ if [ -z "${KEACTRL_CFG_FILE+x}" ]; then
test_lib_error "create_keactrl_config requires KEACTRL_CFG_FILE \
variable be set"
clean_exit 1
# Sets Kea logger to write to the file specified by the global value
# ${LOG_FILE}.
set_logger() {
- if [ -z "${LOG_FILE}" ]; then
+ if [ -z "${LOG_FILE+x}" ]; then
test_lib_error "set_logger requires LOG_FILE variable be set"
clean_exit 1
fi
# _GET_PID: holds a PID if process is running
# _GET_PIDS_NUM: holds 1 if process is running, 0 otherwise
get_pid() {
- local proc_name=${1} # Process name
+ local proc_name=${1-} # Process name
local cfg_file_name=${2-} # Configuration file name without extension.
# PID file name includes process name. The process name is required.
# Get the name of the process identified by PID.
get_process_name() {
- local pid=${1}
+ local pid=${1-}
+ if test -z "${pid}"; then
+ test_lib_error 'expected PID parameter in get_process_name'
+ clean_exit 1
+ fi
+
ps "${pid}" | tr -s ' ' | cut -d ' ' -f 6- | head -n 2 | tail -n 1
}
# Wait for file to be created.
wait_for_file() {
- local file=${1}
+ local file=${1-}
+ if test -z "${file}"; then
+ test_lib_error 'expected file parameter in wait_for_file'
+ clean_exit 1
+ fi
+
local timeout='4' # seconds
local deadline=$(($(date +%s) + timeout))
while ! test -f "${file}"; do
# Wait for process identified by PID to die.
wait_for_process_to_stop() {
- local pid=${1}
+ local pid=${1-}
+ if test -z "${pid}"; then
+ test_lib_error 'expected PID parameter in wait_for_process_to_stop'
+ clean_exit 1
+ fi
+
local timeout='4' # seconds
local deadline=$(($(date +%s) + timeout))
while ps "${pid}" >/dev/null; do
# names, add this before pgrep:
# proc_name=$(printf '%s' "${proc_name}" | cut -c1-15)
kill_processes_by_name() {
- local proc_name=${1} # Process name
+ local proc_name=${1-} # Process name
if [ -z "${proc_name}" ]; then
test_lib_error "kill_processes_by_name requires process name"
clean_exit 1
# It performs the cleanup and prints whether the test has passed or failed.
# If a test fails, the Kea log is dumped.
clean_exit() {
- exit_code=${1} # Exit code to be returned by the exit function.
+ exit_code=${1-} # Exit code to be returned by the exit function.
case ${exit_code} in
''|*[!0-9]*)
test_lib_error "argument passed to clean_exit must be a number" ;;
# Starts Kea process in background using a configuration file specified
# in the global variable ${CFG_FILE}.
start_kea() {
- local bin=${1}
+ local bin=${1-}
if [ -z "${bin}" ]; then
test_lib_error "binary name must be specified for start_kea"
clean_exit 1
# Return value:
# _WAIT_FOR_KEA: 0 if Kea hasn't started, 1 otherwise
wait_for_kea() {
- local timeout=${1} # Desired timeout in seconds.
+ local timeout=${1-} # Desired timeout in seconds.
+ if test -z "${timeout}"; then
+ test_lib_error 'expected timeout parameter in wait_for_kea'
+ clean_exit 1
+ fi
case ${timeout} in
''|*[!0-9]*)
test_lib_error "argument passed to wait_for_kea must be a number"
# Return value:
# _WAIT_FOR_MESSAGE: 0 if the message hasn't occurred, 1 otherwise.
wait_for_message() {
- local timeout=${1} # Expected timeout value in seconds.
- local message="${2}" # Expected message id.
- local occurrences=${3} # Number of expected occurrences.
+ local timeout="${1-}" # Expected timeout value in seconds.
+ local message="${2-}" # Expected message id.
+ local occurrences="${3-}" # Number of expected occurrences.
# Validate timeout
case ${timeout} in
# _WAIT_FOR_SERVER_DOWN: 1 if server is down, 0 if timeout occurred and the
# server is still running.
wait_for_server_down() {
- local timeout=${1} # Timeout specified in seconds.
- local proc_name=${2} # Server process name.
+ local timeout="${1-}" # Timeout specified in seconds.
+ local proc_name="${2-}" # Server process name.
+ if test -z "${proc_name}"; then
+ test_lib_error 'expected process name parameter in wait_for_server_down'
+ clean_exit 1
+ fi
case ${timeout} in
''|*[!0-9]*)
# Sends specified signal to the Kea process.
send_signal() {
- local sig=${1} # Signal number.
- local proc_name=${2} # Process name
+ local sig=${1-} # Signal number.
+ local proc_name=${2-} # Process name
# Validate signal
case ${sig} in
# live process it sets _SERVER_PID_FILE and _SERVER_PID to the
# corresponding values. Otherwise, it emits an error and exits.
verify_server_pid() {
- local bin_name="${1}" # binary name of the server
- local cfg_file="${2}" # config file name
+ local bin_name="${1-}" # binary name of the server
+ local cfg_file="${2-}" # config file name
# We will construct the PID file name based on the server config
# and binary name