Select Git revision
runnable-mail_test.go
runnable-mail_test.go 3.80 KiB
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"
"testing"
"time"
)
func startTestSMTPDockerImageAndContainer(t *testing.T, host string, port string, ctx context.Context) error {
t.Helper()
cli, err := client.NewClientWithOpts(client.WithVersion("1.41"))
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: host,
HostPort: port,
},
},
"8025/tcp": []nat.PortBinding{
{
HostIP: host,
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, _ := context.WithTimeout(context.Background(), 20*time.Second)
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) {
ctb := context.Background()
ctx, cancel := context.WithCancel(ctb)
t.Cleanup(func() {
cancel()
time.Sleep(1 * time.Second)
})
host := "127.0.0.1"
listener, err := net.Listen("tcp", host+":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, host, portAsString, ctx)
if err != nil {
t.Errorf("Unexpected error: %v", err)
cancel()
}
done <- true
}()
waitCtx, waitCancel := context.WithTimeout(ctx, 30*time.Second)
defer waitCancel()
for {
conn, err := net.DialTimeout("tcp", net.JoinHostPort(host, 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: host,
Port: portAsString,
Username: "",
Password: "",
Headers: map[string]string{
"X-Test": "test",
},
}
result, err := mailRunnable.Run()
// 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")
}
}