mirror of
https://github.com/docker-mailserver/docker-mailserver.git
synced 2025-07-23 12:16:01 +02:00
tests(refactor): Improve consistency and documentation for test helpers (#3012)
This commit is contained in:
parent
fb82082cf1
commit
e3c4ef76c6
32 changed files with 936 additions and 656 deletions
|
@ -1,5 +1,19 @@
|
|||
#!/bin/bash
|
||||
|
||||
# ? ABOUT: Functions defined here aid with common functionality during tests.
|
||||
|
||||
# ! ATTENTION: Functions prefixed with `__` are intended for internal use within this file only, not in tests.
|
||||
|
||||
# ! -------------------------------------------------------------------
|
||||
# ? >> Miscellaneous initialization functionality
|
||||
|
||||
# shellcheck disable=SC2155
|
||||
|
||||
# Load additional BATS libraries for more functionality.
|
||||
#
|
||||
# ## Note
|
||||
#
|
||||
# This function is internal and should not be used in tests.
|
||||
function __load_bats_helper() {
|
||||
load "${REPOSITORY_ROOT}/test/test_helper/bats-support/load"
|
||||
load "${REPOSITORY_ROOT}/test/test_helper/bats-assert/load"
|
||||
|
@ -7,241 +21,377 @@ function __load_bats_helper() {
|
|||
|
||||
__load_bats_helper
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
# like _run_in_container_explicit but infers ${1} by using the ENV CONTAINER_NAME
|
||||
# WARNING: Careful using this with _until_success_or_timeout methods,
|
||||
# which can be misleading in the success of `run`, not the command given to `run`.
|
||||
function _run_in_container() {
|
||||
run docker exec "${CONTAINER_NAME}" "${@}"
|
||||
# Properly handle the container name given to tests. This makes the whole
|
||||
# test suite more robust as we can be sure that the container name is
|
||||
# properly set. Sometimes, we need to provide an explicit container name;
|
||||
# this function eases the pain by either providing the explicitly given
|
||||
# name or `CONTAINER_NAME` if it is set.
|
||||
#
|
||||
# @param ${1} = explicit container name [OPTIONAL]
|
||||
#
|
||||
# ## Attention
|
||||
#
|
||||
# Note that this function checks whether the name given to it starts with
|
||||
# the prefix `dms-test_`. One must adhere to this naming convention.
|
||||
#
|
||||
# ## Panics
|
||||
#
|
||||
# If neither an explicit non-empty argument is given nor `CONTAINER_NAME`
|
||||
# is set.
|
||||
#
|
||||
# ## "Calling Convention"
|
||||
#
|
||||
# This function should be called the following way:
|
||||
#
|
||||
# local SOME_VAR=$(__handle_container_name "${X:-}")
|
||||
#
|
||||
# Where `X` is an arbitrary argument of the function you're calling.
|
||||
#
|
||||
# ## Note
|
||||
#
|
||||
# This function is internal and should not be used in tests.
|
||||
function __handle_container_name() {
|
||||
if [[ -n ${1:-} ]] && [[ ${1:-} =~ ^dms-test_ ]]
|
||||
then
|
||||
printf '%s' "${1}"
|
||||
return 0
|
||||
elif [[ -n ${CONTAINER_NAME+set} ]]
|
||||
then
|
||||
printf '%s' "${CONTAINER_NAME}"
|
||||
return 0
|
||||
else
|
||||
echo 'ERROR: (helper/common.sh) Container name was either provided explicitly without the required `dms-test_` prefix, or CONTAINER_NAME is not set for implicit usage' >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# @param ${1} container name [REQUIRED]
|
||||
# @param ... command to execute
|
||||
function _run_in_container_explicit() {
|
||||
local CONTAINER_NAME=${1:?Container name must be given when using explicit}
|
||||
# ? << Miscellaneous initialization functionality
|
||||
# ! -------------------------------------------------------------------
|
||||
# ? >> Functions to execute commands inside a container
|
||||
|
||||
|
||||
# Execute a command inside a container with an explicit name.
|
||||
#
|
||||
# @param ${1} = container name
|
||||
# @param ... = command to execute
|
||||
function _exec_in_container_explicit() {
|
||||
local CONTAINER_NAME=${1:?Container name must be provided when using explicit}
|
||||
shift 1
|
||||
run docker exec "${CONTAINER_NAME}" "${@}"
|
||||
docker exec "${CONTAINER_NAME}" "${@}"
|
||||
}
|
||||
|
||||
function _default_teardown() {
|
||||
docker rm -f "${CONTAINER_NAME}"
|
||||
# Execute a command inside the container with name ${CONTAINER_NAME}.
|
||||
#
|
||||
# @param ... = command to execute
|
||||
function _exec_in_container() {
|
||||
_exec_in_container_explicit "${CONTAINER_NAME:?Container name must be provided}" "${@}"
|
||||
}
|
||||
|
||||
function _reload_postfix() {
|
||||
local CONTAINER_NAME=${1:-${CONTAINER_NAME}}
|
||||
|
||||
# Reloading Postfix config after modifying it in <2 sec will cause Postfix to delay, workaround that:
|
||||
docker exec "${CONTAINER_NAME}" touch -d '2 seconds ago' /etc/postfix/main.cf
|
||||
docker exec "${CONTAINER_NAME}" postfix reload
|
||||
# Execute a command inside a container with an explicit name. The command is run with
|
||||
# BATS' `run` so you can check the exit code and use `assert_`.
|
||||
#
|
||||
# @param ${1} = container name
|
||||
# @param ... = command to execute
|
||||
function _run_in_container_explicit() {
|
||||
local CONTAINER_NAME=${1:?Container name must be provided when using explicit}
|
||||
shift 1
|
||||
run _exec_in_container_explicit "${CONTAINER_NAME}" "${@}"
|
||||
}
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
# @param ${1} target container name [IF UNSET: ${CONTAINER_NAME}]
|
||||
function get_container_ip() {
|
||||
local TARGET_CONTAINER_NAME=${1:-${CONTAINER_NAME}}
|
||||
docker inspect --format '{{ .NetworkSettings.IPAddress }}' "${TARGET_CONTAINER_NAME}"
|
||||
# Execute a command inside the container with name ${CONTAINER_NAME}. The command
|
||||
# is run with BATS' `run` so you can check the exit code and use `assert_`.
|
||||
#
|
||||
# @param ... = command to execute
|
||||
function _run_in_container() {
|
||||
_run_in_container_explicit "${CONTAINER_NAME:?Container name must be provided}" "${@}"
|
||||
}
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# Execute a command inside the container with name ${CONTAINER_NAME}. Moreover,
|
||||
# the command is run by Bash with `/bin/bash -c`.
|
||||
#
|
||||
# @param ... = command to execute with Bash
|
||||
function _exec_in_container_bash() { _exec_in_container /bin/bash -c "${@}" ; }
|
||||
|
||||
# @param ${1} timeout
|
||||
# @param --fatal-test <command eval string> additional test whose failure aborts immediately
|
||||
# @param ... test to run
|
||||
function repeat_until_success_or_timeout {
|
||||
# Execute a command inside the container with name ${CONTAINER_NAME}. The command
|
||||
# is run with BATS' `run` so you can check the exit code and use `assert_`. Moreover,
|
||||
# the command is run by Bash with `/bin/bash -c`.
|
||||
#
|
||||
# @param ... = Bash command to execute
|
||||
function _run_in_container_bash() { _run_in_container /bin/bash -c "${@}" ; }
|
||||
|
||||
# ? << Functions to execute commands inside a container
|
||||
# ! -------------------------------------------------------------------
|
||||
# ? >> Functions about executing commands with timeouts
|
||||
|
||||
# Repeats a given command inside a container until the timeout is over.
|
||||
#
|
||||
# @param ${1} = timeout
|
||||
# @param ${2} = container name
|
||||
# @param ... = test command for container
|
||||
function _repeat_in_container_until_success_or_timeout() {
|
||||
local TIMEOUT="${1:?Timeout duration must be provided}"
|
||||
local CONTAINER_NAME="${2:?Container name must be provided}"
|
||||
shift 2
|
||||
|
||||
_repeat_until_success_or_timeout \
|
||||
--fatal-test "_container_is_running ${CONTAINER_NAME}" \
|
||||
"${TIMEOUT}" \
|
||||
_exec_in_container "${@}"
|
||||
}
|
||||
|
||||
# Repeats a given command until the timeout is over.
|
||||
#
|
||||
# @option --fatal-test <COMMAND EVAL STRING> = additional test whose failure aborts immediately
|
||||
# @param ${1} = timeout
|
||||
# @param ... = test to run
|
||||
function _repeat_until_success_or_timeout() {
|
||||
local FATAL_FAILURE_TEST_COMMAND
|
||||
|
||||
if [[ "${1}" == "--fatal-test" ]]; then
|
||||
FATAL_FAILURE_TEST_COMMAND="${2}"
|
||||
if [[ "${1:-}" == "--fatal-test" ]]
|
||||
then
|
||||
FATAL_FAILURE_TEST_COMMAND="${2:?Provided --fatal-test but no command}"
|
||||
shift 2
|
||||
fi
|
||||
|
||||
if ! [[ "${1}" =~ ^[0-9]+$ ]]; then
|
||||
echo "First parameter for timeout must be an integer, received \"${1}\""
|
||||
local TIMEOUT=${1:?Timeout duration must be provided}
|
||||
shift 1
|
||||
|
||||
if ! [[ "${TIMEOUT}" =~ ^[0-9]+$ ]]
|
||||
then
|
||||
echo "First parameter for timeout must be an integer, received \"${TIMEOUT}\""
|
||||
return 1
|
||||
fi
|
||||
|
||||
local TIMEOUT=${1}
|
||||
local STARTTIME=${SECONDS}
|
||||
shift 1
|
||||
|
||||
until "${@}"
|
||||
do
|
||||
if [[ -n ${FATAL_FAILURE_TEST_COMMAND} ]] && ! eval "${FATAL_FAILURE_TEST_COMMAND}"; then
|
||||
if [[ -n ${FATAL_FAILURE_TEST_COMMAND} ]] && ! eval "${FATAL_FAILURE_TEST_COMMAND}"
|
||||
then
|
||||
echo "\`${FATAL_FAILURE_TEST_COMMAND}\` failed, early aborting repeat_until_success of \`${*}\`" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
sleep 1
|
||||
|
||||
if [[ $(( SECONDS - STARTTIME )) -gt ${TIMEOUT} ]]; then
|
||||
if [[ $(( SECONDS - STARTTIME )) -gt ${TIMEOUT} ]]
|
||||
then
|
||||
echo "Timed out on command: ${*}" >&2
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# like repeat_until_success_or_timeout but with wrapping the command to run into `run` for later bats consumption
|
||||
# @param ${1} timeout
|
||||
# @param ... test command to run
|
||||
function run_until_success_or_timeout {
|
||||
if ! [[ ${1} =~ ^[0-9]+$ ]]; then
|
||||
echo "First parameter for timeout must be an integer, received \"${1}\""
|
||||
# Like `_repeat_until_success_or_timeout` . The command is run with BATS' `run`
|
||||
# so you can check the exit code and use `assert_`.
|
||||
#
|
||||
# @param ${1} = timeout
|
||||
# @param ... = test command to run
|
||||
function _run_until_success_or_timeout() {
|
||||
local TIMEOUT=${1:?Timeout duration must be provided}
|
||||
shift 1
|
||||
|
||||
if [[ ! ${TIMEOUT} =~ ^[0-9]+$ ]]
|
||||
then
|
||||
echo "First parameter for timeout must be an integer, received \"${TIMEOUT}\""
|
||||
return 1
|
||||
fi
|
||||
|
||||
local TIMEOUT=${1}
|
||||
local STARTTIME=${SECONDS}
|
||||
shift 1
|
||||
|
||||
until run "${@}" && [[ $status -eq 0 ]]
|
||||
until run "${@}" && [[ ${status} -eq 0 ]]
|
||||
do
|
||||
sleep 1
|
||||
|
||||
if (( SECONDS - STARTTIME > TIMEOUT )); then
|
||||
if (( SECONDS - STARTTIME > TIMEOUT ))
|
||||
then
|
||||
echo "Timed out on command: ${*}" >&2
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# @param ${1} timeout
|
||||
# @param ${2} container name
|
||||
# @param ... test command for container
|
||||
function repeat_in_container_until_success_or_timeout() {
|
||||
local TIMEOUT="${1}"
|
||||
local CONTAINER_NAME="${2}"
|
||||
shift 2
|
||||
# ? << Functions about executing commands with timeouts
|
||||
# ! -------------------------------------------------------------------
|
||||
# ? >> Functions to wait until a condition is met
|
||||
|
||||
repeat_until_success_or_timeout --fatal-test "container_is_running ${CONTAINER_NAME}" "${TIMEOUT}" docker exec "${CONTAINER_NAME}" "${@}"
|
||||
|
||||
# Wait until a port is ready.
|
||||
#
|
||||
# @param ${1} = port
|
||||
# @param ${2} = container name [OPTIONAL]
|
||||
function _wait_for_tcp_port_in_container() {
|
||||
local PORT=${1:?Port number must be provided}
|
||||
local CONTAINER_NAME=$(__handle_container_name "${2:-}")
|
||||
|
||||
_repeat_until_success_or_timeout \
|
||||
--fatal-test "_container_is_running ${CONTAINER_NAME}" \
|
||||
"${TEST_TIMEOUT_IN_SECONDS}" \
|
||||
_exec_in_container_bash "nc -z 0.0.0.0 ${PORT}"
|
||||
}
|
||||
|
||||
function container_is_running() {
|
||||
[[ "$(docker inspect -f '{{.State.Running}}' "${1}")" == "true" ]]
|
||||
# Wait for SMTP port (25) to become ready.
|
||||
#
|
||||
# @param ${1} = name of the container [OPTIONAL]
|
||||
function _wait_for_smtp_port_in_container() {
|
||||
local CONTAINER_NAME=$(__handle_container_name "${1:-}")
|
||||
_wait_for_tcp_port_in_container 25
|
||||
}
|
||||
|
||||
# @param ${1} port
|
||||
# @param ${2} container name
|
||||
function wait_for_tcp_port_in_container() {
|
||||
repeat_until_success_or_timeout --fatal-test "container_is_running ${2}" "${TEST_TIMEOUT_IN_SECONDS}" docker exec "${2}" /bin/sh -c "nc -z 0.0.0.0 ${1}"
|
||||
}
|
||||
# Wait until the SMPT port (25) can respond.
|
||||
#
|
||||
# @param ${1} = name of the container [OPTIONAL]
|
||||
function _wait_for_smtp_port_in_container_to_respond() {
|
||||
local CONTAINER_NAME=$(__handle_container_name "${1:-}")
|
||||
|
||||
# @param ${1} name of the postfix container
|
||||
function wait_for_smtp_port_in_container() {
|
||||
wait_for_tcp_port_in_container 25 "${1}"
|
||||
}
|
||||
|
||||
# @param ${1} name of the postfix container
|
||||
function wait_for_smtp_port_in_container_to_respond() {
|
||||
local COUNT=0
|
||||
until [[ $(docker exec "${1}" timeout 10 /bin/sh -c "echo QUIT | nc localhost 25") == *"221 2.0.0 Bye"* ]]; do
|
||||
if [[ $COUNT -eq 20 ]]
|
||||
until [[ $(_exec_in_container timeout 10 /bin/bash -c 'echo QUIT | nc localhost 25') == *'221 2.0.0 Bye'* ]]
|
||||
do
|
||||
if [[ ${COUNT} -eq 20 ]]
|
||||
then
|
||||
echo "Unable to receive a valid response from 'nc localhost 25' within 20 seconds"
|
||||
return 1
|
||||
fi
|
||||
|
||||
sleep 1
|
||||
((COUNT+=1))
|
||||
(( COUNT += 1 ))
|
||||
done
|
||||
}
|
||||
|
||||
# @param ${1} name of the postfix container
|
||||
function wait_for_amavis_port_in_container() {
|
||||
wait_for_tcp_port_in_container 10024 "${1}"
|
||||
# Checks whether a service is running inside a container (${1}).
|
||||
#
|
||||
# @param ${1} = service name
|
||||
# @param ${2} = container name [OPTIONAL]
|
||||
function _should_have_service_running_in_container() {
|
||||
local SERVICE_NAME="${1:?Service name must be provided}"
|
||||
local CONTAINER_NAME=$(__handle_container_name "${2:-}")
|
||||
|
||||
_run_in_container /usr/bin/supervisorctl status "${SERVICE_NAME}"
|
||||
assert_success
|
||||
assert_output --partial 'RUNNING'
|
||||
}
|
||||
|
||||
# get the private config path for the given container or test file, if no container name was given
|
||||
function private_config_path() {
|
||||
echo "${PWD}/test/duplicate_configs/${1:-$(basename "${BATS_TEST_FILENAME}")}"
|
||||
}
|
||||
# Wait until a service is running.
|
||||
#
|
||||
# @param ${1} = name of the service to wait for
|
||||
# @param ${2} = container name [OPTIONAL]
|
||||
function _wait_for_service() {
|
||||
local SERVICE_NAME="${1:?Service name must be provided}"
|
||||
local CONTAINER_NAME=$(__handle_container_name "${2:-}")
|
||||
|
||||
function container_has_service_running() {
|
||||
local CONTAINER_NAME="${1}"
|
||||
local SERVICE_NAME="${2}"
|
||||
|
||||
docker exec "${CONTAINER_NAME}" /usr/bin/supervisorctl status "${SERVICE_NAME}" | grep RUNNING >/dev/null
|
||||
}
|
||||
|
||||
function wait_for_service() {
|
||||
local CONTAINER_NAME="${1}"
|
||||
local SERVICE_NAME="${2}"
|
||||
|
||||
repeat_until_success_or_timeout --fatal-test "container_is_running ${CONTAINER_NAME}" "${TEST_TIMEOUT_IN_SECONDS}" \
|
||||
container_has_service_running "${CONTAINER_NAME}" "${SERVICE_NAME}"
|
||||
}
|
||||
|
||||
# NOTE: Relies on ENV `LOG_LEVEL=debug` or higher
|
||||
function _wait_until_expected_count_is_matched() {
|
||||
function __get_count() {
|
||||
# NOTE: `|| true` required due to `set -e` usage:
|
||||
# https://github.com/docker-mailserver/docker-mailserver/pull/2997#discussion_r1070583876
|
||||
docker exec "${CONTAINER_NAME}" grep --count "${MATCH_CONTENT}" "${MATCH_IN_LOG}" || true
|
||||
}
|
||||
|
||||
# WARNING: Keep in mind it is a '>=' comparison.
|
||||
# If you provide an explict count to match, ensure it is not too low to cause a false-positive.
|
||||
function __has_expected_count() {
|
||||
[[ $(__get_count) -ge "${EXPECTED_COUNT}" ]]
|
||||
}
|
||||
|
||||
local CONTAINER_NAME=${1}
|
||||
local EXPECTED_COUNT=${2}
|
||||
|
||||
# Ensure early failure if arg is missing:
|
||||
assert_not_equal "${CONTAINER_NAME}" ''
|
||||
|
||||
# Ensure the container is configured with the required `LOG_LEVEL` ENV:
|
||||
assert_regex \
|
||||
$(docker exec "${CONTAINER_NAME}" env | grep '^LOG_LEVEL=') \
|
||||
'=(debug|trace)$'
|
||||
|
||||
# Default behaviour is to wait until one new match is found (eg: incremented),
|
||||
# unless explicitly set (useful for waiting on a min count to be reached):
|
||||
if [[ -z $EXPECTED_COUNT ]]
|
||||
then
|
||||
# +1 of starting count:
|
||||
EXPECTED_COUNT=$(( $(__get_count) + 1 ))
|
||||
fi
|
||||
|
||||
repeat_until_success_or_timeout 20 __has_expected_count
|
||||
_repeat_until_success_or_timeout \
|
||||
--fatal-test "_container_is_running ${CONTAINER_NAME}" \
|
||||
"${TEST_TIMEOUT_IN_SECONDS}" \
|
||||
_should_have_service_running_in_container "${SERVICE_NAME}"
|
||||
}
|
||||
|
||||
# An account added to `postfix-accounts.cf` must wait for the `changedetector` service
|
||||
# to process the update before Dovecot creates the mail account and associated storage dir:
|
||||
function wait_until_account_maildir_exists() {
|
||||
local CONTAINER_NAME=$1
|
||||
local MAIL_ACCOUNT=$2
|
||||
# to process the update before Dovecot creates the mail account and associated storage dir.
|
||||
#
|
||||
# @param ${1} = mail account name
|
||||
# @param ${2} = container name
|
||||
function _wait_until_account_maildir_exists() {
|
||||
local MAIL_ACCOUNT=${1:?Mail account must be provided}
|
||||
local CONTAINER_NAME=$(__handle_container_name "${2:-}")
|
||||
|
||||
local LOCAL_PART="${MAIL_ACCOUNT%@*}"
|
||||
local DOMAIN_PART="${MAIL_ACCOUNT#*@}"
|
||||
local MAIL_ACCOUNT_STORAGE_DIR="/var/mail/${DOMAIN_PART}/${LOCAL_PART}"
|
||||
|
||||
repeat_in_container_until_success_or_timeout 60 "${CONTAINER_NAME}" bash -c "[[ -d ${MAIL_ACCOUNT_STORAGE_DIR} ]]"
|
||||
_repeat_in_container_until_success_or_timeout 60 "${CONTAINER_NAME}" \
|
||||
/bin/bash -c "[[ -d ${MAIL_ACCOUNT_STORAGE_DIR} ]]"
|
||||
}
|
||||
|
||||
function add_mail_account_then_wait_until_ready() {
|
||||
local CONTAINER_NAME=$1
|
||||
local MAIL_ACCOUNT=$2
|
||||
# Password is optional (omit when the password is not needed during the test)
|
||||
local MAIL_PASS="${3:-password_not_relevant_to_test}"
|
||||
|
||||
run docker exec "${CONTAINER_NAME}" setup email add "${MAIL_ACCOUNT}" "${MAIL_PASS}"
|
||||
assert_success
|
||||
|
||||
wait_until_account_maildir_exists "${CONTAINER_NAME}" "${MAIL_ACCOUNT}"
|
||||
}
|
||||
|
||||
function wait_for_empty_mail_queue_in_container() {
|
||||
local CONTAINER_NAME="${1}"
|
||||
# Wait until the mail queue is empty inside a container (${1}).
|
||||
#
|
||||
# @param ${1} = container name [OPTIONAL]
|
||||
function _wait_for_empty_mail_queue_in_container() {
|
||||
local CONTAINER_NAME=$(__handle_container_name "${1:-}")
|
||||
local TIMEOUT=${TEST_TIMEOUT_IN_SECONDS}
|
||||
|
||||
# shellcheck disable=SC2016
|
||||
repeat_in_container_until_success_or_timeout "${TIMEOUT}" "${CONTAINER_NAME}" bash -c '[[ $(mailq) == *"Mail queue is empty"* ]]'
|
||||
_repeat_in_container_until_success_or_timeout \
|
||||
"${TIMEOUT}" \
|
||||
"${CONTAINER_NAME}" \
|
||||
/bin/bash -c '[[ $(mailq) == "Mail queue is empty" ]]'
|
||||
}
|
||||
|
||||
# `lines` is a special BATS variable updated via `run`:
|
||||
function _should_output_number_of_lines() {
|
||||
assert_equal "${#lines[@]}" $1
|
||||
|
||||
# ? << Functions to wait until a condition is met
|
||||
# ! -------------------------------------------------------------------
|
||||
# ? >> Miscellaneous helper functions
|
||||
|
||||
# Adds a mail account and waits for the associated files to be created.
|
||||
#
|
||||
# @param ${1} = mail account name
|
||||
# @param ${2} = password [OPTIONAL]
|
||||
# @param ${3} = container name [OPTIONAL]
|
||||
function _add_mail_account_then_wait_until_ready() {
|
||||
local MAIL_ACCOUNT=${1:?Mail account must be provided}
|
||||
local MAIL_PASS="${2:-password_not_relevant_to_test}"
|
||||
local CONTAINER_NAME=$(__handle_container_name "${3:-}")
|
||||
|
||||
_run_in_container setup email add "${MAIL_ACCOUNT}" "${MAIL_PASS}"
|
||||
assert_success
|
||||
|
||||
_wait_until_account_maildir_exists "${MAIL_ACCOUNT}"
|
||||
}
|
||||
|
||||
# Assert that the number of lines output by a previous command matches the given
|
||||
# amount (${1}). `lines` is a special BATS variable updated via `run`.
|
||||
#
|
||||
# @param ${1} = number of lines that the output should have
|
||||
function _should_output_number_of_lines() {
|
||||
assert_equal "${#lines[@]}" "${1:?Number of lines not provided}"
|
||||
}
|
||||
|
||||
# Reloads the postfix service.
|
||||
#
|
||||
# @param ${1} = container name [OPTIONAL]
|
||||
function _reload_postfix() {
|
||||
local CONTAINER_NAME=$(__handle_container_name "${1:-}")
|
||||
|
||||
# Reloading Postfix config after modifying it within 2 seconds will cause Postfix to delay reading `main.cf`:
|
||||
# WORKAROUND: https://github.com/docker-mailserver/docker-mailserver/pull/2998
|
||||
_exec_in_container touch -d '2 seconds ago' /etc/postfix/main.cf
|
||||
_exec_in_container postfix reload
|
||||
}
|
||||
|
||||
|
||||
# Get the IP of the container (${1}).
|
||||
#
|
||||
# @param ${1} = container name [OPTIONAL]
|
||||
function _get_container_ip() {
|
||||
local TARGET_CONTAINER_NAME=$(__handle_container_name "${1:-}")
|
||||
docker inspect --format '{{ .NetworkSettings.IPAddress }}' "${TARGET_CONTAINER_NAME}"
|
||||
}
|
||||
|
||||
# Check if a container is running.
|
||||
#
|
||||
# @param ${1} = container name [OPTIONAL]
|
||||
function _container_is_running() {
|
||||
local TARGET_CONTAINER_NAME=$(__handle_container_name "${1:-}")
|
||||
[[ $(docker inspect -f '{{.State.Running}}' "${TARGET_CONTAINER_NAME}") == 'true' ]]
|
||||
}
|
||||
|
||||
# Checks if the directory exists and then how many files it contains at the top-level.
|
||||
#
|
||||
# @param ${1} = directory
|
||||
# @param ${2} = number of files that should be in ${1}
|
||||
# @param ${3} = container name [OPTIONAL]
|
||||
function _count_files_in_directory_in_container()
|
||||
{
|
||||
local DIRECTORY=${1:?No directory provided}
|
||||
local NUMBER_OF_LINES=${2:?No line count provided}
|
||||
local CONTAINER_NAME=$(__handle_container_name "${3:-}")
|
||||
|
||||
_run_in_container_bash "[[ -d ${DIRECTORY} ]]"
|
||||
assert_success
|
||||
|
||||
_run_in_container_bash "find ${DIRECTORY} -maxdepth 1 -type f -printf 'x\n'"
|
||||
assert_success
|
||||
_should_output_number_of_lines "${NUMBER_OF_LINES}"
|
||||
}
|
||||
|
||||
# ? << Miscellaneous helper functions
|
||||
# ! -------------------------------------------------------------------
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue