Skip to content

Commit

Permalink
chore: make integration tests more robust
Browse files Browse the repository at this point in the history
  • Loading branch information
d--j committed Mar 13, 2023
1 parent 83f066a commit b4fb051
Show file tree
Hide file tree
Showing 21 changed files with 107 additions and 70 deletions.
8 changes: 4 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
GO_MILTER_DIR := $(shell go list -f '{{.Dir}}' github.com/d--j/go-milter)
GO_MILTER_INTEGRATION_DIR := $(shell cd integration && go list -f '{{.Dir}}' github.com/d--j/go-milter/integration)

integration:
docker build -q --progress=plain -t go-milter-integration "$(GO_MILTER_DIR)/integration/docker" && \
docker run --rm -w /usr/src/root/integration -v $(PWD):/usr/src/root go-milter-integration \
go run github.com/d--j/go-milter/integration/runner -filter '.*' ./tests
docker build -q --progress=plain -t go-milter-integration "$(GO_MILTER_INTEGRATION_DIR)/docker" && \
docker run --rm --hostname=mx.example.com -w /usr/src/root/integration -v $(PWD):/usr/src/root go-milter-integration \
go run github.com/d--j/go-milter/integration/runner -filter '.*' -mtaFilter '.*' ./tests

.PHONY: integration
1 change: 1 addition & 0 deletions integration/docker/syslog-ng.conf
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
@include "scl.conf"

source s_local {
unix-stream("/dev/log");
internal();
};

Expand Down
4 changes: 2 additions & 2 deletions integration/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ module github.com/d--j/go-milter/integration
go 1.18

require (
github.com/d--j/go-milter v0.6.0
github.com/d--j/go-milter v0.6.5
github.com/emersion/go-message v0.16.0
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21
github.com/emersion/go-smtp v0.16.0
golang.org/x/text v0.7.0
golang.org/x/tools v0.1.12
)

require (
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594 // indirect
golang.org/x/net v0.7.0 // indirect
golang.org/x/text v0.7.0 // indirect
)

replace github.com/d--j/go-milter => ../
18 changes: 10 additions & 8 deletions integration/mta/mock/mta.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ type Backend struct {

func (bkd *Backend) NewSession(conn *smtp.Conn) (smtp.Session, error) {
macros := milter.NewMacroBag()
macros.Set(milter.MacroMTAFullyQualifiedDomainName, "localhost.local")
macros.Set(milter.MacroDaemonName, "localhost.local")
macros.Set(milter.MacroMTAVersion, "MOCK-SMTP 0.0.0")
macros.Set(milter.MacroMTAFQDN, "localhost.local")
macros.Set(milter.MacroDaemonName, "mock-smtp")
macros.Set(milter.MacroIfName, "eth99")
addr, _, err := net.SplitHostPort(conn.Conn().LocalAddr().String())
if err != nil {
Expand Down Expand Up @@ -289,21 +290,22 @@ func (s *Session) Data(r io.Reader) error {
for _, act := range modActions {
switch act.Type {
case milter.ActionChangeFrom:
log.Printf("[%s] ACT = ActionChangeFrom <%s> %s", s.queueId, act.From, act.FromArgs)
s.MailFrom = act.From
log.Printf("[%s] ACT = ActionChangeFrom %s %s", s.queueId, act.From, act.FromArgs)
s.MailFrom = milter.RemoveAngle(act.From)
s.MailFromArgs = act.FromArgs
case milter.ActionDelRcpt:
log.Printf("[%s] ACT = ActionDelRcpt <%s>", s.queueId, act.Rcpt)
log.Printf("[%s] ACT = ActionDelRcpt %s", s.queueId, act.Rcpt)
rcpt := milter.RemoveAngle(act.Rcpt)
again:
for i, r := range s.Recipients {
if act.Rcpt == r.Addr {
if rcpt == r.Addr {
s.Recipients = append(s.Recipients[:i], s.Recipients[i+1:]...)
goto again
}
}
case milter.ActionAddRcpt:
log.Printf("[%s] ACT = ActionAddRcpt <%s> %s", s.queueId, act.Rcpt, act.RcptArgs)
s.Recipients = append(s.Recipients, Rcpt{Addr: act.Rcpt, Args: act.RcptArgs})
log.Printf("[%s] ACT = ActionAddRcpt %s %s", s.queueId, act.Rcpt, act.RcptArgs)
s.Recipients = append(s.Recipients, Rcpt{Addr: milter.RemoveAngle(act.Rcpt), Args: act.RcptArgs})
case milter.ActionReplaceBody:
log.Printf("[%s] ACT = ActionReplaceBody %q", s.queueId, act.Body)
replacedBody = append(replacedBody, act.Body...)
Expand Down
2 changes: 0 additions & 2 deletions integration/mta/mock/mta.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,12 @@ if [ "tags" = "$1" ]; then
fi

if [ "start" = "$1" ]; then
shift
parse_args "$@"
go build -o "$SCRATCH_DIR/mta.exe" -v "$SCRIPT_DIR"
exec "$SCRATCH_DIR/mta.exe" -mta ":$MTA_PORT" -next ":$RECEIVER_PORT" -milter ":$MILTER_PORT" -cert "$SCRATCH_DIR/../cert.pem" -key "$SCRATCH_DIR/../key.pem"
fi

if [ "stop" = "$1" ]; then
shift
parse_args "$@"
exit 0
fi
Expand Down
2 changes: 0 additions & 2 deletions integration/mta/postfix/mta.sh
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,6 @@ setup_chroot() {
}

if [ "start" = "$1" ]; then
shift
parse_args "$@"
mkdir "$SCRATCH_DIR/conf" "$SCRATCH_DIR/conf/sasl" "$SCRATCH_DIR/data" "$SCRATCH_DIR/queue" || die "could not create $SCRATCH_DIR/{conf,data,queue}"
render_template <"$SCRIPT_DIR/main.cf" >"$SCRATCH_DIR/conf/main.cf" || die "could not create $SCRATCH_DIR/conf/main.cf"
Expand All @@ -156,7 +155,6 @@ if [ "start" = "$1" ]; then
fi

if [ "stop" = "$1" ]; then
shift
parse_args "$@"
sudo -n -- postfix -v -c "$SCRATCH_DIR/conf" stop
exit 0
Expand Down
1 change: 1 addition & 0 deletions integration/mta/script.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ usage() {
}

parse_args() {
shift
while [ $# -gt 0 ]; do
case $1 in
-mtaPort)
Expand Down
8 changes: 4 additions & 4 deletions integration/mta/sendmail/mta.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,24 @@ if [ "tags" = "$1" ]; then
echo "auth-no"
#echo "auth-plain"
echo "tls-no"
#echo "tls-starttls"
echo "tls-starttls"
exit 0
fi

if [ "start" = "$1" ]; then
shift
parse_args "$@"
cp "$SCRATCH_DIR/../cert.pem" "$SCRATCH_DIR/cert.pem" || die "could not create $SCRATCH_DIR/cert.pem"
cp "$SCRATCH_DIR/../key.pem" "$SCRATCH_DIR/key.pem" || die "could not create $SCRATCH_DIR/key.pem"
render_template <"$SCRIPT_DIR/sendmail.cf" >"$SCRATCH_DIR/sendmail.cf" || die "could not create $SCRATCH_DIR/sendmail.cf"
mkdir "${SCRATCH_DIR}/mqueue" || die "could not create $SCRATCH_DIR/mqueue"
sudo -n -- chown smmta:smmsp "${SCRATCH_DIR}/mqueue" || die "could not chown $SCRATCH_DIR/mqueue"
sudo -n -- chmod u=rwx,g=rs,o= "${SCRATCH_DIR}/mqueue" || die "could not chmod $SCRATCH_DIR/mqueue"
sudo -n -- syslog-ng || die "could not start syslog-ng"
sudo -n -- syslog-ng --no-caps || die "could not start syslog-ng"
sudo -n -- /usr/libexec/sendmail/sendmail -bd "-C${SCRATCH_DIR}/sendmail.cf"
exit 0
fi

if [ "stop" = "$1" ]; then
shift
parse_args "$@"
# echo "SHUTDOWN" > "${SCRATCH_DIR}/smcontrol"
kill "$(head -n1 "${SCRATCH_DIR}/sendmail.pid")"
Expand Down
18 changes: 9 additions & 9 deletions integration/mta/sendmail/sendmail.cf
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ Fw/etc/mail/local-host-names %[^\#]

# my official domain name
# ... define this only if sendmail cannot automatically determine your domain
#Dj$w.Foo.COM
Djmx.example.com

# host/domain names ending with a token in class P are canonical
CP.
Expand Down Expand Up @@ -253,7 +253,7 @@ O UseErrorsTo=False
#O UseCompressedIPv6Addresses

# log level
O LogLevel=9
O LogLevel=50

# send to me too, even in an alias expansion?
O MeToo=True
Expand Down Expand Up @@ -299,8 +299,8 @@ O MaxRunnersPerQueue=5
# shall we sort the queue by hostname first?
#O QueueSortOrder=priority

# increase milter log level (breaks sendmail?)
#O Milter.LogLevel=99
# increase milter log level
O Milter.LogLevel=50

# minimum time in queue before retry
#O MinQueueAge=30m
Expand Down Expand Up @@ -570,19 +570,19 @@ O ProcessTitlePrefix=MTA


# CA directory
#O CACertPath
O CACertPath=/etc/ssl/certs/
# CA file
#O CACertFile
O CACertFile=%{SCRATCH_DIR}/cert.pem
# Server Cert
#O ServerCertFile
O ServerCertFile=%{SCRATCH_DIR}/cert.pem
# Server private key
#O ServerKeyFile
O ServerKeyFile=%{SCRATCH_DIR}/key.pem
# Client Cert
#O ClientCertFile
# Client private key
#O ClientKeyFile
# File containing certificate revocation lists
#O CRLFile
O CRLFile=/dev/null
# DHParameters (only required if DSA/DH is used)
#O DHParameters
# Random data source (required for systems without /dev/urandom under OpenSSL)
Expand Down
23 changes: 19 additions & 4 deletions integration/runner/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ func ParseConfig() *Config {
flag.UintVar(&milterPort, "milterPort", 34126, "`port` for test milter servers (1024 < port < 65536")
filter := ""
flag.StringVar(&filter, "filter", "", "regexp `pattern` to filter testcases")
mtaFilter := ""
flag.StringVar(&mtaFilter, "mtaFilter", "", "regexp `pattern` to filter MTAs")
flag.Usage = func() {
fmt.Fprintf(flag.CommandLine.Output(), "Usage of %s:\n", os.Args[0])
flag.PrintDefaults()
Expand All @@ -62,6 +64,13 @@ func ParseConfig() *Config {
if err != nil {
LevelOneLogger.Fatal(err)
}
if mtaFilter == "" {
mtaFilter = ".*"
}
mtaFilterRe, err := regexp.Compile(mtaFilter)
if err != nil {
LevelOneLogger.Fatal(err)
}
config := Config{
MtaStartPort: uint16(mtaPort),
ReceiverPort: uint16(receiverPort),
Expand Down Expand Up @@ -97,21 +106,27 @@ func ParseConfig() *Config {
if mtas == nil {
LevelOneLogger.Fatalf("did not find any MTAs")
}
if mtaPort+uint(len(mtas)) > math.MaxUint16 {
var filteredMtas []string
for _, m := range mtas {
if mtaFilterRe.MatchString(m) {
filteredMtas = append(filteredMtas, m)
}
}
if mtaPort+uint(len(filteredMtas)) > math.MaxUint16 {
LevelOneLogger.Fatal("too many MTAs, pick a lower -mtaPort")
}
if overlap(receiverPort, receiverPort, mtaPort, mtaPort+uint(len(mtas))) {
if overlap(receiverPort, receiverPort, mtaPort, mtaPort+uint(len(filteredMtas))) {
LevelOneLogger.Fatal("-receiverPort and -mtaPort overlap")
}
if overlap(milterPort, milterPort, mtaPort, mtaPort+uint(len(mtas))) {
if overlap(milterPort, milterPort, mtaPort, mtaPort+uint(len(filteredMtas))) {
LevelOneLogger.Fatal("-milterPort and -mtaPort overlap")
}
if overlap(receiverPort, receiverPort, milterPort, milterPort) {
LevelOneLogger.Fatal("-receiverPort and -milterPort overlap")
}
var dirs []*TestDir
var tests []*TestCase
for _, p := range mtas {
for _, p := range filteredMtas {
mta, err := NewMTA(p, uint16(mtaPort), &config)
mtaPort++
if err != nil {
Expand Down
6 changes: 5 additions & 1 deletion integration/runner/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,9 @@ func main() {
}
defer receiver.Cleanup()
runner := NewRunner(config, &receiver)
runner.Run()
if !runner.Run() {
receiver.Cleanup()
config.Cleanup()
os.Exit(1)
}
}
18 changes: 11 additions & 7 deletions integration/runner/mta.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,12 @@ func (m *MTA) MarkFailedTest() {
}

func (m *MTA) Start() error {
err := os.Chmod(m.path, 0755)
if err != nil {
return err
}
m.dir = path.Join(m.config.ScratchDir, fmt.Sprintf("mta-%d", m.Port))
err := os.Mkdir(m.dir, 0755)
err = os.Mkdir(m.dir, 0755)
if err != nil && !os.IsExist(err) {
return err
}
Expand All @@ -92,13 +96,13 @@ func (m *MTA) Start() error {
b, err := m.cmd.CombinedOutput()
failed := !IsExpectedExitErr(err)
if failed {
LevelTwoLogger.Print(err)
LevelOneLogger.Print(err)
}
m.m.Lock()
failedTest := m.failedTest
m.m.Unlock()
if failed || failedTest {
LevelTwoLogger.Printf("MTA %s\n%s", m.path, b)
if failed || failedTest && len(b) > 0 {
LevelOneLogger.Printf("MTA %s output\n%s", m.path, b)
}
m.wg.Done()
cancel()
Expand All @@ -109,7 +113,7 @@ func (m *MTA) Start() error {
m.Stop()
return err
}
LevelTwoLogger.Printf("MTA %s ready", m.path)
LevelOneLogger.Printf("MTA %s ready", m.path)
return nil
}

Expand All @@ -131,8 +135,8 @@ func (m *MTA) Stop() {
m.m.Lock()
failedTest := m.failedTest
m.m.Unlock()
if failedTest {
LevelTwoLogger.Printf("MTA %s stop\n%s", m.path, b)
if failedTest && len(b) > 0 {
LevelOneLogger.Printf("MTA %s stop output\n%s", m.path, b)
}
})
}
Loading

0 comments on commit b4fb051

Please sign in to comment.