216 lines
5.8 KiB
Bash
Executable File
216 lines
5.8 KiB
Bash
Executable File
#!/bin/sh
|
|
#
|
|
# Exercise Queue administration, retry preservation, expiry, and DSN creation
|
|
# against a running local Bongo installation.
|
|
|
|
set -eu
|
|
|
|
user=${1:-stqqueue}
|
|
domain=${2:-bongo.test}
|
|
queue_tool=${BONGO_QUEUE_TOOL:-/usr/bin/bongo-queuetool}
|
|
store_tool=${BONGO_STORE_TOOL:-/usr/bin/bongo-storetool}
|
|
service=${BONGO_SERVICE:-bongo.service}
|
|
run_as=${BONGO_TEST_RUN_AS:-bongo}
|
|
as_root=${BONGO_TEST_AS_ROOT:-sudo -n}
|
|
|
|
if [ "$(id -un)" = "$run_as" ]; then
|
|
as_bongo=
|
|
else
|
|
as_bongo="sudo -n -u $run_as"
|
|
fi
|
|
|
|
work=$(mktemp -d "${TMPDIR:-/tmp}/bongo-stq05.XXXXXX")
|
|
chmod 0755 "$work"
|
|
managed_id=
|
|
retry_id=
|
|
expiry_id=
|
|
|
|
cleanup()
|
|
{
|
|
status=$?
|
|
for queue_id in "$managed_id" "$retry_id" "$expiry_id"; do
|
|
if [ -n "$queue_id" ]; then
|
|
$as_bongo "$queue_tool" delete "$queue_id" \
|
|
>/dev/null 2>&1 || true
|
|
fi
|
|
done
|
|
rm -rf "$work"
|
|
exit "$status"
|
|
}
|
|
trap cleanup EXIT HUP INT TERM
|
|
|
|
wait_queue()
|
|
{
|
|
attempts=30
|
|
while [ "$attempts" -gt 0 ]; do
|
|
if $as_bongo "$queue_tool" list >/dev/null 2>&1; then
|
|
return 0
|
|
fi
|
|
attempts=$((attempts - 1))
|
|
sleep 1
|
|
done
|
|
echo "STQ-05: Queue did not become ready" >&2
|
|
return 1
|
|
}
|
|
|
|
queue_contains()
|
|
{
|
|
$as_bongo "$queue_tool" list |
|
|
grep -F "$1 " >/dev/null
|
|
}
|
|
|
|
wait_message()
|
|
{
|
|
queue_id=$1
|
|
output=$2
|
|
attempts=30
|
|
while [ "$attempts" -gt 0 ]; do
|
|
if $as_bongo "$queue_tool" message "$queue_id" \
|
|
>"$output" 2>/dev/null; then
|
|
return 0
|
|
fi
|
|
attempts=$((attempts - 1))
|
|
sleep 1
|
|
done
|
|
echo "STQ-05: queue entry $queue_id did not become readable" >&2
|
|
return 1
|
|
}
|
|
|
|
printf '%s\r\n' \
|
|
"From: STQ-05 <stq05@$domain>" \
|
|
"To: $user@$domain" \
|
|
'Subject: STQ-05 queue lifecycle' \
|
|
'Date: Thu, 23 Jul 2026 12:34:56 +0200' \
|
|
'Message-ID: <stq05-lifecycle@bongo.test>' \
|
|
'' \
|
|
'Queue listing, hold, retry, expiry, bounce, and deletion.' \
|
|
>"$work/message.eml"
|
|
chmod 0644 "$work/message.eml"
|
|
|
|
# A normal committed entry must be listable, movable to hold, preserved across
|
|
# restart, releasable to an explicit target, and deletable.
|
|
managed_id=$($as_bongo "$queue_tool" hold-local "$work/message.eml" 9)
|
|
case "$managed_id" in
|
|
009-*) ;;
|
|
*)
|
|
echo "STQ-05: unexpected management fixture ID: $managed_id" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
queue_contains "$managed_id"
|
|
|
|
held_id=$($as_bongo "$queue_tool" hold "$managed_id")
|
|
managed_id=$held_id
|
|
case "$managed_id" in
|
|
999-*) ;;
|
|
*)
|
|
echo "STQ-05: hold did not return a queue-999 ID: $managed_id" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
queue_contains "$managed_id"
|
|
|
|
$as_root /usr/bin/systemctl restart "$service"
|
|
wait_queue
|
|
queue_contains "$managed_id"
|
|
|
|
released_id=$($as_bongo "$queue_tool" release "$managed_id" 9)
|
|
managed_id=$released_id
|
|
case "$managed_id" in
|
|
009-*) ;;
|
|
*)
|
|
echo "STQ-05: release did not return a queue-9 ID: $managed_id" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
queue_contains "$managed_id"
|
|
$as_bongo "$queue_tool" delete "$managed_id"
|
|
if queue_contains "$managed_id"; then
|
|
echo "STQ-05: deleted entry remains in the listing" >&2
|
|
exit 1
|
|
fi
|
|
managed_id=
|
|
|
|
# A failed remote attempt must remain queued without changing the message.
|
|
retry_id=$($as_bongo "$queue_tool" enqueue-remote \
|
|
"$work/message.eml" "$user@$domain" nobody@retry.invalid 7)
|
|
case "$retry_id" in
|
|
007-*) ;;
|
|
*)
|
|
echo "STQ-05: unexpected retry fixture ID: $retry_id" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
wait_message "$retry_id" "$work/retry-before.eml"
|
|
retry_before=$(sha256sum "$work/retry-before.eml" | awk '{ print $1 }')
|
|
$as_bongo "$queue_tool" flush
|
|
wait_message "$retry_id" "$work/retry-after.eml"
|
|
retry_after=$(sha256sum "$work/retry-after.eml" | awk '{ print $1 }')
|
|
if [ "$retry_before" != "$retry_after" ]; then
|
|
echo "STQ-05: retry changed the queued message" >&2
|
|
exit 1
|
|
fi
|
|
$as_bongo "$queue_tool" delete "$retry_id"
|
|
retry_id=
|
|
|
|
# Deterministic expiry starts in hold so the normal remote worker cannot race
|
|
# the diagnostic command. Exactly one DSN must appear in the isolated inbox.
|
|
$as_bongo "$store_tool" -u "$user" \
|
|
document-list /mail/INBOX >"$work/inbox-before"
|
|
expiry_id=$($as_bongo "$queue_tool" enqueue-remote \
|
|
"$work/message.eml" "$user@$domain" nobody@retry.invalid 999)
|
|
case "$expiry_id" in
|
|
999-*) ;;
|
|
*)
|
|
echo "STQ-05: unexpected expiry fixture ID: $expiry_id" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
$as_bongo "$queue_tool" expire "$expiry_id" >/dev/null
|
|
expiry_id=
|
|
|
|
attempts=30
|
|
while [ "$attempts" -gt 0 ]; do
|
|
$as_bongo "$store_tool" -u "$user" \
|
|
document-list /mail/INBOX >"$work/inbox-after"
|
|
awk '{ print $1 }' "$work/inbox-before" | sort -u \
|
|
>"$work/inbox-before.ids"
|
|
awk '{ print $1 }' "$work/inbox-after" | sort -u \
|
|
>"$work/inbox-after.ids"
|
|
comm -13 "$work/inbox-before.ids" "$work/inbox-after.ids" \
|
|
>"$work/new.ids"
|
|
if [ "$(wc -l <"$work/new.ids")" -eq 1 ]; then
|
|
break
|
|
fi
|
|
attempts=$((attempts - 1))
|
|
sleep 1
|
|
done
|
|
|
|
if [ "$(wc -l <"$work/new.ids")" -ne 1 ]; then
|
|
echo "STQ-05: expiry did not create exactly one DSN" >&2
|
|
diff -u "$work/inbox-before" "$work/inbox-after" >&2 || true
|
|
exit 1
|
|
fi
|
|
|
|
document=$(sed -n '1p' "$work/new.ids")
|
|
document_path=$(awk -v id="$document" '$1 == id { print $3 }' \
|
|
"$work/inbox-after")
|
|
$as_bongo "$store_tool" -u "$user" \
|
|
document-get "$document_path" - >"$work/dsn.eml"
|
|
|
|
for expected in \
|
|
'Subject: Returned mail: Delivery time exceeded' \
|
|
'Original-recipient: rfc822;nobody@retry.invalid' \
|
|
'Final-recipient: rfc822;nobody@retry.invalid' \
|
|
'Action: failed' \
|
|
'Status: 5.4.7'
|
|
do
|
|
if ! grep -F "$expected" "$work/dsn.eml" >/dev/null; then
|
|
echo "STQ-05: generated DSN lacks '$expected'" >&2
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
printf 'STQ-05 PASS management=hold/restart/release/delete retry-sha256=%s dsn=%s status=5.4.7\n' \
|
|
"$retry_after" "$document"
|