Files
stalwart-migrator/internal/backup/sqlbackup_test.go
T
jcoffey-dev 719a945d64 Initial commit: stalwart-migrator design and scaffolding
In-place upgrade tool for Stalwart Mail Server (0.15.5 -> latest) with
checkpointed rollback and post-migration validation. Design stage; see
ARCHITECTURE.md.
2026-08-22 18:17:17 -07:00

86 lines
2.8 KiB
Go

package backup
import (
"context"
"os"
"path/filepath"
"strings"
"testing"
)
func TestBuildPgDumpArgs(t *testing.T) {
args := BuildPgDumpArgs(SQLOptions{
Host: "db.internal", Port: "5432", Database: "stalwart", User: "stalwart", OutPath: "/backups/out.sql",
})
joined := strings.Join(args, " ")
for _, want := range []string{"-U stalwart", "-d stalwart", "-h db.internal", "-p 5432", "-f /backups/out.sql"} {
if !strings.Contains(joined, want) {
t.Errorf("BuildPgDumpArgs = %q, missing %q", joined, want)
}
}
for _, table := range criticalTables {
if !strings.Contains(joined, "-t "+table) {
t.Errorf("BuildPgDumpArgs missing critical table flag for %q: %q", table, joined)
}
}
}
func TestBuildMySQLDumpArgs(t *testing.T) {
args := BuildMySQLDumpArgs(SQLOptions{Host: "db.internal", Port: "3306", Database: "stalwart", User: "stalwart"})
joined := strings.Join(args, " ")
if !strings.Contains(joined, "-u stalwart") || !strings.Contains(joined, "-h db.internal") || !strings.Contains(joined, "-P 3306") {
t.Errorf("BuildMySQLDumpArgs = %q, missing expected flags", joined)
}
if !strings.HasSuffix(joined, strings.Join(criticalTables, " ")) {
t.Errorf("BuildMySQLDumpArgs = %q, want it to end with the critical table list", joined)
}
}
func TestRunPgDumpInvokesPgDumpWithArgs(t *testing.T) {
dir := t.TempDir()
log := argsFile(t, dir)
withFakeExecutable(t, "pg_dump", fakeScriptLoggingArgs(log, "exit 0"))
err := RunPgDump(context.Background(), SQLOptions{
User: "stalwart", Database: "stalwart", OutPath: filepath.Join(dir, "out.sql"),
})
if err != nil {
t.Fatalf("RunPgDump: %v", err)
}
got := readArgsFile(t, log)
if !strings.Contains(got, "-U stalwart") {
t.Errorf("pg_dump was invoked with %q, missing -U stalwart", got)
}
}
func TestRunPgDumpPropagatesFailure(t *testing.T) {
dir := t.TempDir()
withFakeExecutable(t, "pg_dump", "#!/bin/sh\necho 'connection refused' >&2\nexit 1\n")
err := RunPgDump(context.Background(), SQLOptions{User: "stalwart", Database: "stalwart", OutPath: filepath.Join(dir, "out.sql")})
if err == nil {
t.Fatal("RunPgDump should have returned an error when pg_dump exits non-zero")
}
if !strings.Contains(err.Error(), "connection refused") {
t.Errorf("error = %v, want it to include pg_dump's stderr", err)
}
}
func TestRunMySQLDumpWritesStdoutToOutPath(t *testing.T) {
dir := t.TempDir()
withFakeExecutable(t, "mysqldump", "#!/bin/sh\necho '-- fake dump output'\n")
outPath := filepath.Join(dir, "out.sql")
err := RunMySQLDump(context.Background(), SQLOptions{User: "stalwart", Database: "stalwart", OutPath: outPath})
if err != nil {
t.Fatalf("RunMySQLDump: %v", err)
}
data, err := os.ReadFile(outPath)
if err != nil {
t.Fatalf("ReadFile: %v", err)
}
if !strings.Contains(string(data), "fake dump output") {
t.Errorf("out.sql = %q, want fake dump output redirected into it", data)
}
}