Files
LambdaMail/services/protocols/internal/e2e/migrations_test.go
T

80 lines
2.0 KiB
Go

package e2e
import (
"context"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"math/big"
"os"
"path/filepath"
"sort"
"strings"
"testing"
"time"
"github.com/jackc/pgx/v5/pgxpool"
)
// applyMigrations brings a fresh database up to the current schema by running
// every up-migration in order. It reads the directory instead of taking a
// hand-written list so that adding a migration cannot leave a test silently
// running against a stale schema.
func applyMigrations(t *testing.T, ctx context.Context, pool *pgxpool.Pool) {
t.Helper()
dir := filepath.Join(repoRoot(t), "migrations")
entries, err := os.ReadDir(dir)
if err != nil {
t.Fatalf("read migrations dir: %v", err)
}
var names []string
for _, e := range entries {
if !e.IsDir() && strings.HasSuffix(e.Name(), ".up.sql") {
names = append(names, e.Name())
}
}
if len(names) == 0 {
t.Fatalf("no up-migrations found in %s", dir)
}
sort.Strings(names)
for _, name := range names {
sql, err := os.ReadFile(filepath.Join(dir, name))
if err != nil {
t.Fatalf("read migration %s: %v", name, err)
}
if _, err := pool.Exec(ctx, string(sql)); err != nil {
t.Fatalf("apply migration %s: %v", name, err)
}
}
}
// selfSignedTLSCert issues an in-memory certificate for the STARTTLS handshake
// in tests. Certificate validation is not what these tests exercise.
func selfSignedTLSCert(t *testing.T) tls.Certificate {
t.Helper()
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
t.Fatalf("generate key: %v", err)
}
template := &x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{CommonName: "mail.test"},
DNSNames: []string{"mail.test", "localhost"},
NotBefore: time.Now().Add(-time.Hour),
NotAfter: time.Now().Add(24 * time.Hour),
}
der, err := x509.CreateCertificate(rand.Reader, template, template, &key.PublicKey, key)
if err != nil {
t.Fatalf("create certificate: %v", err)
}
return tls.Certificate{Certificate: [][]byte{der}, PrivateKey: key}
}