97 lines
2.5 KiB
Go
97 lines
2.5 KiB
Go
package cmd
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"flag"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
"github.com/urfave/cli/v2"
|
|
)
|
|
|
|
func TestRunBackupRejectsMutuallyExclusiveModes(t *testing.T) {
|
|
set := flag.NewFlagSet("backup", flag.ContinueOnError)
|
|
set.Bool("db-only", true, "")
|
|
set.Bool("images-only", true, "")
|
|
|
|
err := runBackup(cli.NewContext(nil, set, nil))
|
|
require.EqualError(t, err, "--db-only and --images-only cannot be used together")
|
|
}
|
|
|
|
func TestWriteFileAtomically(t *testing.T) {
|
|
t.Run("success", func(t *testing.T) {
|
|
dir := t.TempDir()
|
|
target := filepath.Join(dir, "backup.sql")
|
|
require.NoError(t, writeFileAtomically(target, func(w io.Writer) error {
|
|
_, err := io.WriteString(w, "complete backup")
|
|
return err
|
|
}))
|
|
|
|
content, err := os.ReadFile(target)
|
|
require.NoError(t, err)
|
|
require.Equal(t, "complete backup", string(content))
|
|
requireNoPartFiles(t, dir)
|
|
})
|
|
|
|
t.Run("failure preserves previous backup", func(t *testing.T) {
|
|
dir := t.TempDir()
|
|
target := filepath.Join(dir, "backup.sql")
|
|
require.NoError(t, os.WriteFile(target, []byte("known good"), 0o600))
|
|
writeErr := errors.New("dump failed")
|
|
|
|
err := writeFileAtomically(target, func(w io.Writer) error {
|
|
_, _ = io.WriteString(w, "partial")
|
|
return writeErr
|
|
})
|
|
require.ErrorIs(t, err, writeErr)
|
|
|
|
content, err := os.ReadFile(target)
|
|
require.NoError(t, err)
|
|
require.Equal(t, "known good", string(content))
|
|
requireNoPartFiles(t, dir)
|
|
})
|
|
|
|
t.Run("failure leaves no new backup", func(t *testing.T) {
|
|
dir := t.TempDir()
|
|
target := filepath.Join(dir, "backup.sql")
|
|
writeErr := errors.New("dump failed")
|
|
|
|
err := writeFileAtomically(target, func(w io.Writer) error {
|
|
_, _ = io.WriteString(w, "partial")
|
|
return writeErr
|
|
})
|
|
require.ErrorIs(t, err, writeErr)
|
|
require.NoFileExists(t, target)
|
|
requireNoPartFiles(t, dir)
|
|
})
|
|
}
|
|
|
|
func requireNoPartFiles(t *testing.T, dir string) {
|
|
t.Helper()
|
|
matches, err := filepath.Glob(filepath.Join(dir, "*.part"))
|
|
require.NoError(t, err)
|
|
require.Empty(t, matches)
|
|
}
|
|
|
|
func TestImageManifestEntryIntegrityFields(t *testing.T) {
|
|
entry := imageManifestEntry{
|
|
Key: "tamabox/image.webp",
|
|
Size: 3,
|
|
SHA256: "actual-content-sha256",
|
|
ETag: "provider-etag",
|
|
}
|
|
encoded, err := json.Marshal(entry)
|
|
require.NoError(t, err)
|
|
require.JSONEq(t, `{
|
|
"key":"tamabox/image.webp",
|
|
"size":3,
|
|
"sha256":"actual-content-sha256",
|
|
"etag":"provider-etag"
|
|
}`, string(encoded))
|
|
require.NotContains(t, string(encoded), "md5")
|
|
}
|