GPLv3's "How to Apply These Terms" asks for a notice in each source file; this is the modern two-line SPDX form of it rather than the full paragraph. 82 files, including tests. The blank line after the header is load-bearing. In Go a comment block immediately preceding `package X` becomes the package doc comment, so without the separator the SPDX lines would be absorbed into the doc for the eleven packages whose doc.go (or main.go) opens with one, and `go doc` would print them. Verified it doesn't.
89 lines
2.9 KiB
Go
89 lines
2.9 KiB
Go
// SPDX-FileCopyrightText: 2026 LINUXexpert-org
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
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)
|
|
}
|
|
}
|