load "${REPOSITORY_ROOT}/test/test_helper/common" TEST_NAME_PREFIX='test helper functions:' @test "${TEST_NAME_PREFIX} repeat_until_success_or_timeout returns instantly on success" { SECONDS=0 repeat_until_success_or_timeout 1 true [[ ${SECONDS} -le 1 ]] } @test "${TEST_NAME_PREFIX} repeat_until_success_or_timeout waits for timeout on persistent failure" { SECONDS=0 run repeat_until_success_or_timeout 2 false [[ ${SECONDS} -ge 2 ]] assert_failure assert_output --partial "Timed out on command" } @test "${TEST_NAME_PREFIX} repeat_until_success_or_timeout aborts immediately on fatal failure" { SECONDS=0 run repeat_until_success_or_timeout --fatal-test false 2 false [[ ${SECONDS} -le 1 ]] assert_failure assert_output --partial "early aborting" } @test "${TEST_NAME_PREFIX} repeat_until_success_or_timeout expects integer timeout" { run repeat_until_success_or_timeout 1 true assert_success run repeat_until_success_or_timeout timeout true assert_failure run repeat_until_success_or_timeout --fatal-test true timeout true assert_failure } @test "${TEST_NAME_PREFIX} run_until_success_or_timeout returns instantly on success" { SECONDS=0 run_until_success_or_timeout 2 true [[ ${SECONDS} -le 1 ]] assert_success } @test "${TEST_NAME_PREFIX} run_until_success_or_timeout waits for timeout on persistent failure" { SECONDS=0 ! run_until_success_or_timeout 2 false [[ ${SECONDS} -ge 2 ]] assert_failure } @test "${TEST_NAME_PREFIX} repeat_in_container_until_success_or_timeout fails immediately for non-running container" { SECONDS=0 ! repeat_in_container_until_success_or_timeout 10 name-of-non-existing-container true [[ ${SECONDS} -le 1 ]] } @test "${TEST_NAME_PREFIX} repeat_in_container_until_success_or_timeout run command in container" { local CONTAINER_NAME CONTAINER_NAME=$(docker run --rm -d alpine sleep 100) SECONDS=0 ! repeat_in_container_until_success_or_timeout 10 "${CONTAINER_NAME}" sh -c "echo '${CONTAINER_NAME}' > /tmp/marker" [[ ${SECONDS} -le 1 ]] run docker exec "${CONTAINER_NAME}" cat /tmp/marker assert_output "${CONTAINER_NAME}" } @test "${TEST_NAME_PREFIX} container_is_running" { local CONTAINER_NAME CONTAINER_NAME=$(docker run --rm -d alpine sleep 100) container_is_running "${CONTAINER_NAME}" docker rm -f "${CONTAINER_NAME}" ! container_is_running "${CONTAINER_NAME}" } @test "${TEST_NAME_PREFIX} wait_for_smtp_port_in_container aborts wait after timeout" { local CONTAINER_NAME CONTAINER_NAME=$(docker run --rm -d alpine sleep 100) SECONDS=0 TEST_TIMEOUT_IN_SECONDS=2 run wait_for_smtp_port_in_container "${CONTAINER_NAME}" [[ ${SECONDS} -ge 2 ]] assert_failure assert_output --partial "Timed out on command" } # NOTE: Test requires external network access available @test "${TEST_NAME_PREFIX} wait_for_smtp_port_in_container returns immediately when port found" { local CONTAINER_NAME CONTAINER_NAME=$(docker run --rm -d alpine sh -c "sleep 10") docker exec "${CONTAINER_NAME}" apk add netcat-openbsd docker exec "${CONTAINER_NAME}" nc -l 25 & SECONDS=0 TEST_TIMEOUT_IN_SECONDS=5 run wait_for_smtp_port_in_container "${CONTAINER_NAME}" [[ ${SECONDS} -lt 5 ]] assert_success } @test "${TEST_NAME_PREFIX} wait_for_finished_setup_in_container" { # variable not local to make visible to teardown local PRIVATE_CONFIG PRIVATE_CONFIG=$(duplicate_config_for_container .) CONTAINER_NAME=$(docker run -d --rm \ -v "${PRIVATE_CONFIG}":/tmp/docker-mailserver \ -h mail.my-domain.com \ -t "${NAME}") teardown() { docker rm -f "${CONTAINER_NAME}"; } # the setup should not be finished immediately after starting ! TEST_TIMEOUT_IN_SECONDS=0 wait_for_finished_setup_in_container "${CONTAINER_NAME}" # but it will finish eventually SECONDS=1 wait_for_finished_setup_in_container "${CONTAINER_NAME}" [[ ${SECONDS} -gt 0 ]] } @test "${TEST_NAME_PREFIX} duplicate_config_for_container" { local path path=$(duplicate_config_for_container duplicate_config_test) run cat "${path}/marker" assert_line "This marker file is there to identify the correct config being copied" run duplicate_config_for_container non-existant-source-folder "${BATS_TEST_NAME}2" assert_failure } @test "${TEST_NAME_PREFIX} container_has_service_running/wait_for_service" { local PRIVATE_CONFIG PRIVATE_CONFIG=$(duplicate_config_for_container .) # variable not local to make visible to teardown CONTAINER_NAME=$(docker run -d --rm \ -v "${PRIVATE_CONFIG}":/tmp/docker-mailserver \ -h mail.my-domain.com \ -t "${NAME}") teardown() { docker rm -f "${CONTAINER_NAME}"; } # pick a service that was not started ! container_has_service_running "${CONTAINER_NAME}" clamav # wait for a service that should be started wait_for_service "${CONTAINER_NAME}" postfix # shut down the service docker exec "${CONTAINER_NAME}" supervisorctl stop postfix # now it should be off SECONDS=0 TEST_TIMEOUT_IN_SECONDS=5 run wait_for_service "${CONTAINER_NAME}" postfix [[ ${SECONDS} -ge 5 ]] assert_failure } @test "${TEST_NAME_PREFIX} wait_for_changes_to_be_detected_in_container fails when timeout is reached" { local PRIVATE_CONFIG PRIVATE_CONFIG=$(duplicate_config_for_container .) # variable not local to make visible to teardown CONTAINER_NAME=$(docker run -d --rm \ -v "${PRIVATE_CONFIG}":/tmp/docker-mailserver \ -h mail.my-domain.com \ -t "${NAME}") teardown() { docker rm -f "${CONTAINER_NAME}"; } # wait for the initial checksum file to be created # shellcheck disable=SC2016 repeat_in_container_until_success_or_timeout 60 "${CONTAINER_NAME}" bash -c 'source /usr/local/bin/helpers/index.sh; test -e "${CHKSUM_FILE}"' # there should be no changes in the beginning TEST_TIMEOUT_IN_SECONDS=0 wait_for_changes_to_be_detected_in_container "${CONTAINER_NAME}" # trigger some change docker exec "${CONTAINER_NAME}" /bin/sh -c "addmailuser auser3@mail.my-domain.com mypassword" # that should be picked up as not yet detected ! TEST_TIMEOUT_IN_SECONDS=0 wait_for_changes_to_be_detected_in_container "${CONTAINER_NAME}" } @test "${TEST_NAME_PREFIX} wait_for_changes_to_be_detected_in_container succeeds within timeout" { local PRIVATE_CONFIG PRIVATE_CONFIG=$(duplicate_config_for_container .) # variable not local to make visible to teardown CONTAINER_NAME=$(docker run -d --rm \ -v "${PRIVATE_CONFIG}":/tmp/docker-mailserver \ -h mail.my-domain.com \ -t "${NAME}") teardown() { docker rm -f "${CONTAINER_NAME}"; } # wait for the initial checksum file to be created # shellcheck disable=SC2016 repeat_in_container_until_success_or_timeout 60 "${CONTAINER_NAME}" bash -c 'source /usr/local/bin/helpers/index.sh; test -e "${CHKSUM_FILE}"' # trigger some change docker exec "${CONTAINER_NAME}" /bin/sh -c "addmailuser auser3@mail.my-domain.com mypassword" # that should eventually be detected SECONDS=0 wait_for_changes_to_be_detected_in_container "${CONTAINER_NAME}" [[ ${SECONDS} -gt 0 ]] } # TODO investigate why this test fails @test "${TEST_NAME_PREFIX} wait_for_empty_mail_queue_in_container fails when timeout reached" { skip 'disabled as it fails randomly: https://github.com/docker-mailserver/docker-mailserver/pull/2177' local PRIVATE_CONFIG PRIVATE_CONFIG=$(duplicate_config_for_container .) # variable not local to make visible to teardown # enable ClamAV to make message delivery slower, so we can detect it CONTAINER_NAME=$(docker run -d --rm \ -v "${PRIVATE_CONFIG}":/tmp/docker-mailserver \ -v "$(pwd)/test/test-files":/tmp/docker-mailserver-test:ro \ -e ENABLE_CLAMAV=1 \ -h mail.my-domain.com \ -t "${NAME}") teardown() { docker rm -f "${CONTAINER_NAME}"; } wait_for_smtp_port_in_container "${CONTAINER_NAME}" || docker logs "${CONTAINER_NAME}" SECONDS=0 # no mails -> should return immediately TEST_TIMEOUT_IN_SECONDS=5 wait_for_empty_mail_queue_in_container "${CONTAINER_NAME}" [[ ${SECONDS} -lt 5 ]] # fill the queue with a message docker exec "${CONTAINER_NAME}" /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/amavis-virus.txt" # that should still be stuck in the queue ! TEST_TIMEOUT_IN_SECONDS=0 wait_for_empty_mail_queue_in_container "${CONTAINER_NAME}" } # TODO investigate why this test fails @test "${TEST_NAME_PREFIX} wait_for_empty_mail_queue_in_container succeeds within timeout" { skip 'disabled as it fails randomly: https://github.com/docker-mailserver/docker-mailserver/pull/2177' local PRIVATE_CONFIG PRIVATE_CONFIG=$(duplicate_config_for_container .) # variable not local to make visible to teardown # enable ClamAV to make message delivery slower, so we can detect it CONTAINER_NAME=$(docker run -d --rm \ -v "${PRIVATE_CONFIG}":/tmp/docker-mailserver \ -v "$(pwd)/test/test-files":/tmp/docker-mailserver-test:ro \ -e ENABLE_CLAMAV=1 \ -h mail.my-domain.com \ -t "${NAME}") teardown() { docker rm -f "${CONTAINER_NAME}"; } wait_for_smtp_port_in_container "${CONTAINER_NAME}" || docker logs "${CONTAINER_NAME}" # fill the queue with a message docker exec "${CONTAINER_NAME}" /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/amavis-virus.txt" # give it some time to clear the queue SECONDS=0 wait_for_empty_mail_queue_in_container "${CONTAINER_NAME}" [[ ${SECONDS} -gt 0 ]] }