Skip to content

Commit f4fa0fa

Browse files
committed
Add initial BATS tests
1 parent d3b3db4 commit f4fa0fa

File tree

6 files changed

+185
-5
lines changed

6 files changed

+185
-5
lines changed

.dockerignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
.git
22
dkim.key
3+
Dockerfile*
4+
test/
5+
Makefile

Dockerfile

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,8 @@ RUN set -x \
1414
&& go install -tags nosystemd,nodocker \
1515
;
1616

17-
# Postfix SMTP Relay
18-
1917
# Debian Trixie
20-
FROM debian:13
18+
FROM debian:13 AS base
2119

2220
EXPOSE 25 587 2525
2321

@@ -61,5 +59,19 @@ RUN set -x \
6159
&& chmod 0644 /etc/postfix/header_checks \
6260
;
6361

62+
# Development image
63+
FROM base AS development
64+
65+
# Install packages
66+
RUN set -x \
67+
&& export DEBIAN_FRONTEND=noninteractive \
68+
&& apt-get update \
69+
&& apt-get install -y --no-install-recommends bats \
70+
&& apt-get clean \
71+
&& rm -rf /var/lib/apt/lists/* \
72+
;
73+
74+
# Postfix SMTP Relay
75+
FROM base AS build
6476
ENTRYPOINT ["/entry.sh"]
6577
CMD ["/usr/bin/s6-svscan", "/etc/s6"]

Makefile

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ NAME := postfix
22
TAG := latest
33
IMAGE_NAME := panubo/$(NAME)
44

5-
.PHONY: help bash run run-* build push clean _ci_test
5+
.PHONY: help bash run run-* build push clean test _ci_test
66

77
help:
88
@printf "$$(grep -hE '^\S+:.*##' $(MAKEFILE_LIST) | sed -e 's/:.*##\s*/:/' -e 's/^\(.\+\):\(.*\)/\\x1b[36m\1\\x1b[m:\2/' | column -c2 -t -s :)\n"
@@ -55,7 +55,11 @@ push: ## Pushes the docker image to hub.docker.com
5555
clean: ## Remove built image
5656
docker rmi $(IMAGE_NAME):$(TAG)
5757

58-
_ci_test:
58+
test: ## Build a test image and run bats tests in docker
59+
docker build --target development -t $(IMAGE_NAME):test-dev .
60+
docker run --rm -v $(shell pwd):/app -w /app $(IMAGE_NAME):test-dev bats test/
61+
62+
_ci_test: test
5963
true
6064

6165
dkim.key:

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,9 @@ echo -e "To: Bob <bob@example.com>\nFrom: Bill <bill@example.com>\nSubject: Test
199199

200200
See the `Makefile` for make targets.
201201

202+
To run the BATS tests, use the `make test` command. This will build a test Docker image and execute the tests within it.
203+
204+
202205
## Releases
203206

204207
For production usage, please use a versioned release rather than the floating 'latest' tag.

test/opendkim.bats

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#!/usr/bin/env bats
2+
3+
# This setup function runs before each test.
4+
setup() {
5+
# Create a temporary directory for our test files.
6+
BATS_TMPDIR=$(mktemp -d -t bats-XXXXXXXX)
7+
export BATS_TMPDIR
8+
9+
# Mock the s6-svscanctl command so the script doesn't fail if it's not installed.
10+
# We create a fake executable that does nothing and returns success.
11+
ln -s /usr/bin/true "${BATS_TMPDIR}/s6-svscanctl"
12+
export PATH="${BATS_TMPDIR}:${PATH}"
13+
}
14+
15+
# This teardown function runs after each test to clean up.
16+
teardown() {
17+
rm -rf "${BATS_TMPDIR}"
18+
}
19+
20+
@test "should generate config with default values" {
21+
# Define test-specific variables
22+
local output_file="${BATS_TMPDIR}/opendkim.conf"
23+
local dkim_keyfile="${BATS_TMPDIR}/dkim.key"
24+
touch "${dkim_keyfile}" # Create the dummy key file
25+
26+
# Run the script in a subshell with a clean environment and execution tracing (-x)
27+
(
28+
export MAILNAME="example.com"
29+
export MYNETWORKS="127.0.0.1"
30+
export DKIM_CONF="${output_file}"
31+
export DKIM_KEYFILE="${dkim_keyfile}"
32+
bash -x etc/opendkim.conf.sh
33+
)
34+
35+
# Check that the generated file contains the expected lines.
36+
run grep "Domain example.com" "${output_file}"
37+
[ "$status" -eq 0 ] # Succeeds if grep finds the line
38+
39+
run grep "Selector mail" "${output_file}"
40+
[ "$status" -eq 0 ]
41+
42+
run grep "InternalHosts 127.0.0.1" "${output_file}"
43+
[ "$status" -eq 0 ]
44+
}
45+
46+
@test "should use DKIM_DOMAINS and DKIM_SELECTOR from environment" {
47+
# Define test-specific variables
48+
local output_file="${BATS_TMPDIR}/opendkim.conf"
49+
local dkim_keyfile="${BATS_TMPDIR}/dkim.key"
50+
touch "${dkim_keyfile}"
51+
52+
# Run the script in a subshell with a clean environment and execution tracing (-x)
53+
(
54+
export DKIM_DOMAINS="custom.net,another.org"
55+
export DKIM_SELECTOR="dkim2024"
56+
export DKIM_CONF="${output_file}"
57+
export DKIM_KEYFILE="${dkim_keyfile}"
58+
bash -x etc/opendkim.conf.sh
59+
)
60+
61+
# Check for the custom values.
62+
run grep "Domain custom.net,another.org" "${output_file}"
63+
[ "$status" -eq 0 ]
64+
65+
run grep "Selector dkim2024" "${output_file}"
66+
[ "$status" -eq 0 ]
67+
}

test/postfix.bats

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
#!/usr/bin/env bats
2+
3+
# Test for /etc/s6/postfix/run
4+
5+
setup() {
6+
BATS_TMPDIR=$(mktemp -d -t bats-XXXXXXXX)
7+
export BATS_TMPDIR
8+
9+
# Backup original files that the script might modify
10+
[ -f /etc/postfix/main.cf ] && cp /etc/postfix/main.cf "${BATS_TMPDIR}/main.cf.bak"
11+
[ -f /etc/sasldb2 ] && cp /etc/sasldb2 "${BATS_TMPDIR}/sasldb2.bak"
12+
cp /usr/lib/postfix/configure-instance.sh "${BATS_TMPDIR}/configure-instance.sh.bak"
13+
14+
# Create a version of the run script without the final 'exec' to prevent blocking
15+
sed 's/exec \/usr\/sbin\/postfix start-fg//' /etc/s6/postfix/run > "${BATS_TMPDIR}/run"
16+
chmod +x "${BATS_TMPDIR}/run"
17+
18+
# The script might create these files, so ensure the directory exists
19+
mkdir -p /etc/postfix/sasl
20+
}
21+
22+
teardown() {
23+
# Restore original files
24+
[ -f "${BATS_TMPDIR}/main.cf.bak" ] && mv "${BATS_TMPDIR}/main.cf.bak" /etc/postfix/main.cf
25+
[ -f "${BATS_TMPDIR}/sasldb2.bak" ] && mv "${BATS_TMPDIR}/sasldb2.bak" /etc/sasldb2
26+
mv "${BATS_TMPDIR}/configure-instance.sh.bak" /usr/lib/postfix/configure-instance.sh
27+
rm -rf "${BATS_TMPDIR}"
28+
}
29+
30+
@test "should configure main.cf with custom values from environment variables" {
31+
# Run the modified script in a subshell with custom environment variables
32+
(
33+
# Set env vars to test against
34+
export MAILNAME="test.example.com"
35+
export MYNETWORKS="10.0.0.0/8 127.0.0.0/8"
36+
export SIZELIMIT="20480000"
37+
export RELAYHOST="[mail.example.com]:587"
38+
export POSTFIX_ADD_MISSING_HEADERS="yes"
39+
export INET_PROTOCOLS="ipv4"
40+
export DISABLE_VRFY_COMMAND="no"
41+
export USE_TLS="no" # Disable TLS to avoid slow cert generation
42+
43+
# Execute the setup script
44+
bash -x "${BATS_TMPDIR}/run"
45+
)
46+
47+
# Use postconf to verify the settings in /etc/postfix/main.cf
48+
run postconf -h myhostname
49+
[ "$status" -eq 0 ]
50+
[ "$output" = "test.example.com" ]
51+
52+
run postconf -h mynetworks
53+
[ "$status" -eq 0 ]
54+
[ "$output" = "10.0.0.0/8 127.0.0.0/8" ]
55+
56+
run postconf -h message_size_limit
57+
[ "$status" -eq 0 ]
58+
[ "$output" = "20480000" ]
59+
60+
run postconf -h relayhost
61+
[ "$status" -eq 0 ]
62+
[ "$output" = "[mail.example.com]:587" ]
63+
64+
run postconf -h always_add_missing_headers
65+
[ "$status" -eq 0 ]
66+
[ "$output" = "yes" ]
67+
68+
run postconf -h inet_protocols
69+
[ "$status" -eq 0 ]
70+
[ "$output" = "ipv4" ]
71+
72+
run postconf -h disable_vrfy_command
73+
[ "$status" -eq 0 ]
74+
[ "$output" = "no" ]
75+
}
76+
77+
@test "should enable DKIM milter when USE_DKIM is 'yes'" {
78+
(
79+
export MAILNAME="test.example.com"
80+
export USE_DKIM="yes"
81+
bash -x "${BATS_TMPDIR}/run"
82+
)
83+
84+
run postconf -h smtpd_milters
85+
[ "$status" -eq 0 ]
86+
[ "$output" = "inet:localhost:8891" ]
87+
88+
run postconf -h non_smtpd_milters
89+
[ "$status" -eq 0 ]
90+
[ "$output" = "inet:localhost:8891" ]
91+
}

0 commit comments

Comments
 (0)