mirror of
https://blitiri.com.ar/repos/chasquid
synced 2025-12-17 14:37:02 +00:00
To send mails, today some tests use msmtp and others our internal smtpc.py. This works, but msmtp slows down the tests significantly, and smtpc.py is also not particularly fast, and also has some limitations. This patch introduces a new SMTP client tool written in Go, and makes almost all the tests use it. Some tests still remain on msmtp, mainly for client-check compatibility. It's likely that this will be moved in later patches to a separate special-purpose test. With this patch, integration tests take ~20% less time than before.
242 lines
5.9 KiB
Bash
242 lines
5.9 KiB
Bash
#!/bin/bash
|
|
# Library to write the shell scripts in the tests.
|
|
|
|
function init() {
|
|
if [ "$V" == "1" ]; then
|
|
set -v
|
|
fi
|
|
|
|
UTILDIR=$(realpath "$(dirname "${BASH_SOURCE[0]}")" )
|
|
export UTILDIR
|
|
|
|
TBASE=$(realpath "$(dirname "$0")" )
|
|
cd "${TBASE}" || exit 1
|
|
|
|
if [ "${RACE}" == "1" ]; then
|
|
GOFLAGS="$GOFLAGS -race"
|
|
fi
|
|
if [ "${GOCOVERDIR}" != "" ]; then
|
|
GOFLAGS="$GOFLAGS -cover -covermode=count"
|
|
fi
|
|
|
|
# Remove the directory where test-mda will deliver mail, so previous
|
|
# runs don't interfere with this one.
|
|
rm -rf .mail
|
|
|
|
# Set traps to kill our subprocesses when we exit (for any reason).
|
|
trap ":" TERM # Avoid the EXIT handler from killing bash.
|
|
trap "exit 2" INT # Ctrl-C, make sure we fail in that case.
|
|
trap "kill 0" EXIT # Kill children on exit.
|
|
}
|
|
|
|
function chasquid() {
|
|
go-build-cached "${TBASE}/../../"
|
|
|
|
# HOSTALIASES: so we "fake" hostnames.
|
|
# PATH: so chasquid can call test-mda without path issues.
|
|
# MDA_DIR: so our test-mda knows where to deliver emails.
|
|
HOSTALIASES=${TBASE}/hosts \
|
|
PATH=${UTILDIR}:${PATH} \
|
|
MDA_DIR=${TBASE}/.mail \
|
|
"${TBASE}/../../chasquid" "$@"
|
|
}
|
|
|
|
function go-build-cached() { (
|
|
# This runs "go build" on the given directory, but only once every
|
|
# 10s, or if the build flags/tags change.
|
|
# Because in tests we run some of the Go programs often, this speeds
|
|
# up the tests.
|
|
cd "$1" || exit 1
|
|
touch -d "10 seconds ago" .reference
|
|
echo "-tags=$GOTAGS : $GOFLAGS" > .flags-new
|
|
if
|
|
! cmp -s .flags-new .flags >/dev/null 2>&1 ||
|
|
[ "$(basename "$PWD")" -ot ".reference" ] ;
|
|
then
|
|
# shellcheck disable=SC2086
|
|
go build -tags="$GOTAGS" $GOFLAGS
|
|
|
|
# Write to .flags instead of renaming, to prevent races where
|
|
# was .flags-new is already renamed by the time we get here.
|
|
# Do this _after_ the build so worst case we build twice,
|
|
# instead of having the chance to run an old binary.
|
|
echo "-tags=$GOTAGS : $GOFLAGS" > .flags
|
|
fi
|
|
) }
|
|
|
|
|
|
function chasquid-util() {
|
|
# Run chasquid-util from inside the config dir, since in our tests
|
|
# data_dir is relative to the config.
|
|
go-build-cached "${TBASE}/../../cmd/chasquid-util/"
|
|
CONFDIR="${CONFDIR:-config}"
|
|
( cd "$CONFDIR" && \
|
|
"${TBASE}/../../cmd/chasquid-util/chasquid-util" \
|
|
-C=. \
|
|
"$@" \
|
|
)
|
|
}
|
|
|
|
# Add a user with chasquid-util. Because this is somewhat cryptographically
|
|
# intensive, it can slow down the tests significantly, so most of the time we
|
|
# use the simpler add_user (below) for testing purposes.
|
|
function chasquid-util-user-add() {
|
|
CONFDIR="${CONFDIR:-config}"
|
|
DOMAIN=$(echo "$1" | cut -d @ -f 2)
|
|
mkdir -p "${CONFDIR}/domains/$DOMAIN/"
|
|
chasquid-util \
|
|
user-add "$1" \
|
|
--password="$2" \
|
|
>> .add_user_logs
|
|
}
|
|
|
|
function add_user() {
|
|
CONFDIR="${CONFDIR:-config}"
|
|
USERNAME=$(echo "$1" | cut -d @ -f 1)
|
|
DOMAIN=$(echo "$1" | cut -d @ -f 2)
|
|
USERDB="${CONFDIR}/domains/$DOMAIN/users"
|
|
mkdir -p "${CONFDIR}/domains/$DOMAIN/"
|
|
if ! [ -f "${USERDB}" ] || ! grep -E -q "key:.*${USERNAME}" "${USERDB}"; then
|
|
echo "users:{ key: '${USERNAME}' value:{ plain:{ password: '$2' }}}" \
|
|
>> "${USERDB}"
|
|
fi
|
|
}
|
|
|
|
function dovecot-auth-cli() {
|
|
go-build-cached "${TBASE}/../../cmd/dovecot-auth-cli/"
|
|
"${TBASE}/../../cmd/dovecot-auth-cli/dovecot-auth-cli" "$@"
|
|
}
|
|
|
|
function run_msmtp() {
|
|
# msmtp will check that the rc file is only user readable.
|
|
chmod 600 msmtprc
|
|
|
|
# msmtp binary is often g+s, which causes $HOSTALIASES to not be
|
|
# honoured, which breaks the tests. Copy the binary to remove the
|
|
# setgid bit as a workaround.
|
|
cp -u "$(command -v msmtp)" "${UTILDIR}/.msmtp-bin"
|
|
|
|
HOSTALIASES=${TBASE}/hosts \
|
|
"${UTILDIR}/.msmtp-bin" -C msmtprc "$@"
|
|
}
|
|
|
|
function mail_diff() {
|
|
"${UTILDIR}/mail_diff" "$@"
|
|
}
|
|
|
|
function chamuyero() {
|
|
"${UTILDIR}/chamuyero" "$@"
|
|
}
|
|
|
|
function generate_cert() {
|
|
go-build-cached "${UTILDIR}/generate_cert/"
|
|
"${UTILDIR}/generate_cert/generate_cert" "$@"
|
|
}
|
|
|
|
function loadgen() {
|
|
go-build-cached "${UTILDIR}/loadgen/"
|
|
"${UTILDIR}/loadgen/loadgen" "$@"
|
|
}
|
|
|
|
function conngen() {
|
|
go-build-cached "${UTILDIR}/conngen/"
|
|
"${UTILDIR}/conngen/conngen" "$@"
|
|
}
|
|
|
|
function minidns_bg() {
|
|
go-build-cached "${UTILDIR}/minidns/"
|
|
"${UTILDIR}/minidns/minidns" "$@" &
|
|
export MINIDNS=$!
|
|
}
|
|
|
|
function fexp() {
|
|
go-build-cached "${UTILDIR}/fexp/"
|
|
"${UTILDIR}/fexp/fexp" "$@"
|
|
}
|
|
|
|
function smtpc() {
|
|
go-build-cached "${UTILDIR}/smtpc/"
|
|
"${UTILDIR}/smtpc/smtpc" "$@"
|
|
}
|
|
|
|
function timeout() {
|
|
MYPID=$$
|
|
(
|
|
sleep "$1"
|
|
echo "timed out after $1, killing test"
|
|
kill -9 $MYPID
|
|
) &
|
|
}
|
|
|
|
function success() {
|
|
echo success
|
|
}
|
|
|
|
function skip() {
|
|
echo "skipped: $*"
|
|
exit 0
|
|
}
|
|
|
|
function fail() {
|
|
echo "FAILED: $*"
|
|
exit 1
|
|
}
|
|
|
|
function check_hostaliases() {
|
|
if ! "${UTILDIR}/check-hostaliases"; then
|
|
skip "\$HOSTALIASES not working (probably systemd-resolved)"
|
|
fi
|
|
}
|
|
|
|
# Wait until there's something listening on the given port.
|
|
function wait_until_ready() {
|
|
PORT=$1
|
|
|
|
while ! bash -c "true < /dev/tcp/localhost/$PORT" 2>/dev/null ; do
|
|
sleep 0.01
|
|
done
|
|
}
|
|
|
|
# Wait for the given file to exist.
|
|
function wait_for_file() {
|
|
while ! [ -e "$1" ]; do
|
|
sleep 0.01
|
|
done
|
|
}
|
|
|
|
function wait_until() {
|
|
while true; do
|
|
if eval "$*"; then
|
|
return 0
|
|
fi
|
|
sleep 0.01
|
|
done
|
|
}
|
|
|
|
# Generate certs for the given hostname.
|
|
function generate_certs_for() {
|
|
CONFDIR="${CONFDIR:-config}"
|
|
|
|
# Generating certs is takes time and slows the tests down, so we keep
|
|
# a little cache that is common to all tests.
|
|
CACHEDIR="${TBASE}/../.generate_certs_cache"
|
|
mkdir -p "${CACHEDIR}/$1/"
|
|
touch -d "10 minutes ago" "${CACHEDIR}/.reference"
|
|
if [ "${CACHEDIR}/$1/privkey.pem" -ot "${CACHEDIR}/.reference" ]; then
|
|
# Cache miss (either was not there, or was too old).
|
|
(
|
|
cd "${CACHEDIR}/$1/" || exit 1
|
|
generate_cert -ca -validfor=1h -host="$1"
|
|
)
|
|
fi
|
|
mkdir -p "${CONFDIR}/certs/$1/"
|
|
cp -p "${CACHEDIR}/$1"/* "${CONFDIR}/certs/$1/"
|
|
}
|
|
|
|
function chasquid_ram_peak() {
|
|
# Find the pid of the daemon, which we expect is running on the
|
|
# background somewhere within our current session.
|
|
SERVER_PID=$(pgrep -s 0 -x chasquid)
|
|
grep VmHWM "/proc/$SERVER_PID/status" | cut -d ':' -f 2-
|
|
}
|