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} }