Something went wrong on our end
Select Git revision
-
Volker Schukai authoredVolker Schukai authored
runnable-mail_test.go 4.26 KiB
// Copyright 2023 schukai GmbH
// SPDX-License-Identifier: AGPL-3.0
//go:build !bench && !race
package jobqueue
import (
"context"
"fmt"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"
"github.com/docker/go-connections/nat"
"github.com/stretchr/testify/assert"
"net"
"os"
"testing"
"time"
)
const DOCKER_TEST_HOST_IP = "127.0.0.1"
func startTestSMTPDockerImageAndContainer(t *testing.T, port string, ctx context.Context) error {
t.Helper()
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
return err
}
imageName := "axllent/mailpit"
reader, err := cli.ImagePull(ctx, imageName, types.ImagePullOptions{})
if err != nil {
return err
}
// if debug image pull, comment out the following lines
//_, _ = io.Copy(os.Stdout, reader)
_ = reader
hostConfig := &container.HostConfig{
PortBindings: nat.PortMap{
"1025/tcp": []nat.PortBinding{
{
HostIP: DOCKER_TEST_HOST_IP,
HostPort: port,
},
},
// if you want to test the web interface, uncomment the following lines
//"8025/tcp": []nat.PortBinding{
// {
// HostIP: DOCKER_TEST_HOST_IP,
// HostPort: "8025",
// },
//},
},
}
resp, err := cli.ContainerCreate(ctx, &container.Config{
Image: imageName,
}, hostConfig, nil, nil, "")
if err != nil {
return err
}
if err := cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil {
return err
}
go func() {
<-ctx.Done()
timeout := 0
stopOptions := container.StopOptions{
Timeout: &timeout,
Signal: "SIGKILL",
}
newCtx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()
if err := cli.ContainerStop(newCtx, resp.ID, stopOptions); err != nil {
t.Errorf("ContainerStop returned error: %v", err)
}
if err := cli.ContainerRemove(newCtx, resp.ID, types.ContainerRemoveOptions{
Force: true,
}); err != nil {
t.Errorf("ContainerRemove returned error: %v", err)
}
}()
statusCh, errCh := cli.ContainerWait(ctx, resp.ID, container.WaitConditionNotRunning)
select {
case err := <-errCh:
if err != nil {
// empty error means container exited normally (see container_wait.go)
if err.Error() == "" {
return nil
}
return err
}
case <-statusCh:
}
return nil
}
func TestMailRunner(t *testing.T) {
if os.Getenv("CI_SERVER") != "" {
t.Skip("Skipping test because CI_SERVER is set")
// TODO: run this test in CI
}
ctb := context.Background()
ctx, cancel := context.WithCancel(ctb)
t.Cleanup(func() {
cancel()
time.Sleep(1 * time.Second)
})
listener, err := net.Listen("tcp", DOCKER_TEST_HOST_IP+":0")
if err != nil {
t.Errorf("Unexpected error: %v", err)
return
}
portAsInt := listener.Addr().(*net.TCPAddr).Port
portAsString := fmt.Sprintf("%d", portAsInt)
_ = listener.Close()
done := make(chan bool)
go func() {
err = startTestSMTPDockerImageAndContainer(t, portAsString, ctx)
if err != nil {
t.Errorf("Unexpected error: %v", err)
cancel()
}
done <- true
}()
waitCtx, waitCancel := context.WithTimeout(ctx, 60*time.Second)
defer waitCancel()
for {
conn, err := net.DialTimeout("tcp", net.JoinHostPort(DOCKER_TEST_HOST_IP, portAsString), 1*time.Second)
if err == nil {
err = conn.Close()
assert.Nil(t, err)
break
}
select {
case <-waitCtx.Done():
t.Error("Timeout waiting for container service")
cancel()
return
default:
time.Sleep(1 * time.Second)
}
}
time.Sleep(1 * time.Second)
mailRunnable := &MailRunnable{
To: "to@example.com",
From: "from@example.com",
Subject: "this is a test",
Body: "this is the body",
Server: DOCKER_TEST_HOST_IP,
Port: portAsString,
Username: "",
Password: "",
Headers: map[string]string{
"X-Test": "test",
},
}
xtx := context.Background()
result, err := mailRunnable.Run(xtx)
// Assertions
assert.NoError(t, err)
assert.Equal(t, ResultStatusSuccess, result.Status)
assert.IsType(t, MailResult{}, result.Data)
// check result.Data contains 4 files
mailResult := result.Data.Sent
assert.Equal(t, true, mailResult)
cancel()
select {
case <-done:
time.Sleep(1 * time.Second)
case <-time.After(1 * time.Minute):
t.Error("test hangs, timeout reached")
}
}