restic-scheduler/restic_test.go

321 lines
8.3 KiB
Go
Raw Permalink Normal View History

2022-02-23 16:05:24 +00:00
package main_test
import (
"errors"
"log"
2022-02-23 16:05:24 +00:00
"os"
"path/filepath"
2022-02-23 16:05:24 +00:00
"testing"
2022-02-23 22:13:00 +00:00
"time"
2022-02-23 16:05:24 +00:00
main "git.iamthefij.com/iamthefij/restic-scheduler"
)
2022-03-24 17:09:33 +00:00
func TestNoOpts(t *testing.T) {
t.Parallel()
args := main.NoOpts{}.ToArgs()
expected := []string{}
AssertEqual(t, "no opts returned some opts", expected, args)
}
2022-02-23 16:05:24 +00:00
func TestGlobalOptions(t *testing.T) {
t.Parallel()
args := main.ResticGlobalOpts{
CaCertFile: "file",
CacheDir: "directory",
PasswordFile: "file",
TLSClientCertFile: "file",
LimitDownload: 1,
LimitUpload: 1,
VerboseLevel: 1,
CleanupCache: true,
2023-11-06 23:02:07 +00:00
InsecureTLS: true,
2022-02-23 16:05:24 +00:00
NoCache: true,
NoLock: true,
Options: map[string]string{
"key": "a long value",
},
2022-02-23 16:05:24 +00:00
}.ToArgs()
expected := []string{
"--cacert", "file",
"--cache-dir", "directory",
"--password-file", "file",
"--tls-client-cert", "file",
"--limit-download", "1",
"--limit-upload", "1",
"--verbose", "1",
"--cleanup-cache",
2023-11-06 23:02:07 +00:00
"--insecure-tls",
2022-02-23 16:05:24 +00:00
"--no-cache",
"--no-lock",
2022-11-03 23:43:17 +00:00
"--option", "key='a long value'",
2022-02-23 16:05:24 +00:00
}
2022-03-24 17:09:33 +00:00
AssertEqual(t, "args didn't match", expected, args)
2022-02-23 16:05:24 +00:00
}
2022-02-23 22:13:00 +00:00
func TestBackupOpts(t *testing.T) {
t.Parallel()
args := main.BackupOpts{
Exclude: []string{"file1", "file2"},
Include: []string{"directory"},
Tags: []string{"thing"},
Host: "steve",
}.ToArgs()
expected := []string{
"--exclude", "file1",
"--exclude", "file2",
"--include", "directory",
"--tag", "thing",
"--host", "steve",
}
2022-03-24 17:09:33 +00:00
AssertEqual(t, "args didn't match", expected, args)
2022-02-23 22:13:00 +00:00
}
func TestRestoreOpts(t *testing.T) {
t.Parallel()
args := main.RestoreOpts{
Exclude: []string{"file1", "file2"},
Include: []string{"directory"},
Host: []string{"steve"},
Tags: []string{"thing"},
Path: "directory",
Target: "directory",
Verify: true,
}.ToArgs()
expected := []string{
"--exclude", "file1",
"--exclude", "file2",
"--include", "directory",
"--host", "steve",
"--tag", "thing",
"--path", "directory",
"--target", "directory",
"--verify",
}
2022-03-24 17:09:33 +00:00
AssertEqual(t, "args didn't match", expected, args)
2022-02-23 22:13:00 +00:00
}
func TestForgetOpts(t *testing.T) {
t.Parallel()
args := main.ForgetOpts{
KeepLast: 1,
KeepHourly: 1,
KeepDaily: 1,
KeepWeekly: 1,
KeepMonthly: 1,
KeepYearly: 1,
KeepWithin: 1 * time.Second,
KeepWithinHourly: 1 * time.Second,
KeepWithinDaily: 1 * time.Second,
KeepWithinWeekly: 1 * time.Second,
KeepWithinMonthly: 1 * time.Second,
KeepWithinYearly: 1 * time.Second,
Tags: []main.TagList{
{"thing1", "thing2"},
{"otherthing"},
},
KeepTags: []main.TagList{{"thing"}},
Prune: true,
}.ToArgs()
expected := []string{
"--keep-last", "1",
"--keep-hourly", "1",
"--keep-daily", "1",
"--keep-weekly", "1",
"--keep-monthly", "1",
"--keep-yearly", "1",
"--keep-within", "1s",
"--keep-within-hourly", "1s",
"--keep-within-daily", "1s",
"--keep-within-weekly", "1s",
"--keep-within-monthly", "1s",
"--keep-within-yearly", "1s",
"--tag", "thing1,thing2",
"--tag", "otherthing",
"--keep-tag", "thing",
"--prune",
}
2022-03-24 17:09:33 +00:00
AssertEqual(t, "args didn't match", expected, args)
2022-02-23 22:13:00 +00:00
}
func TestUnlockOpts(t *testing.T) {
t.Parallel()
args := main.UnlockOpts{
RemoveAll: true,
}.ToArgs()
expected := []string{
"--remove-all",
}
AssertEqual(t, "args didn't match", expected, args)
}
2022-02-23 16:05:24 +00:00
func TestBuildEnv(t *testing.T) {
t.Parallel()
cases := []struct {
name string
2022-02-24 06:53:18 +00:00
cmd main.Restic
2022-02-23 16:05:24 +00:00
expected []string
}{
{
name: "No Env",
2022-11-10 21:30:30 +00:00
cmd: main.Restic{}, //nolint:exhaustruct
2022-02-23 16:05:24 +00:00
expected: os.Environ(),
},
{
name: "SetEnv",
2022-11-10 21:30:30 +00:00
cmd: main.Restic{ //nolint:exhaustruct
2022-02-23 16:05:24 +00:00
Env: map[string]string{"TestKey": "Value"},
},
expected: append(os.Environ(), "TestKey=Value"),
},
{
name: "SetEnv",
2022-11-10 21:30:30 +00:00
cmd: main.Restic{ //nolint:exhaustruct
2022-02-23 16:05:24 +00:00
Passphrase: "Shhhhhhhh!!",
},
expected: append(os.Environ(), "RESTIC_PASSWORD=Shhhhhhhh!!"),
},
}
for _, c := range cases {
c := c
t.Run(c.name, func(t *testing.T) {
t.Parallel()
2022-03-24 17:09:33 +00:00
AssertEqual(t, "args didn't match", c.expected, c.cmd.BuildEnv())
2022-02-23 16:05:24 +00:00
})
}
}
func TestResticInterface(t *testing.T) {
t.Parallel()
if testing.Short() {
t.Skip("Skip integration test when running short tests")
}
dataDir := t.TempDir()
repoDir := t.TempDir()
cacheDir := t.TempDir()
restoreTarget := t.TempDir()
dataFile := filepath.Join(dataDir, "test.txt")
restoredDataFile := filepath.Join(restoreTarget, dataFile)
restic := main.Restic{
Logger: log.New(os.Stderr, t.Name()+":", log.Lmsgprefix),
Repo: repoDir,
Env: map[string]string{},
Passphrase: "Correct.Horse.Battery.Staple",
2022-11-10 21:30:30 +00:00
//nolint:exhaustruct
GlobalOpts: &main.ResticGlobalOpts{
CacheDir: cacheDir,
2022-11-03 23:43:17 +00:00
Options: map[string]string{
"s3.storage-class": "REDUCED_REDUNDANCY",
},
},
Cwd: dataDir,
}
// Write test file to the data dir
2024-01-06 23:10:29 +00:00
err := os.WriteFile(dataFile, []byte("testing"), 0o644)
AssertEqualFail(t, "unexpected error writing to test file", nil, err)
// Make sure no existing repo is found
_, err = restic.ReadSnapshots()
if err == nil || !errors.Is(err, main.ErrRepoNotFound) {
AssertEqualFail(t, "didn't get expected error for backup", main.ErrRepoNotFound.Error(), err.Error())
}
// Try to backup when repo is not initialized
2022-11-10 21:30:30 +00:00
err = restic.Backup([]string{dataDir}, main.BackupOpts{}) //nolint:exhaustruct
if !errors.Is(err, main.ErrRepoNotFound) {
AssertEqualFail(t, "unexpected error creating making backup", nil, err)
}
// Init repo
err = restic.EnsureInit()
AssertEqualFail(t, "unexpected error initializing repo", nil, err)
// Verify it can be reinitialized with no issues
err = restic.EnsureInit()
AssertEqualFail(t, "unexpected error reinitializing repo", nil, err)
// Backup for real this time
2022-11-10 21:30:30 +00:00
err = restic.Backup([]string{dataDir}, main.BackupOpts{Tags: []string{"test"}}) //nolint:exhaustruct
AssertEqualFail(t, "unexpected error creating making backup", nil, err)
// Check snapshots
expectedHostname, _ := os.Hostname()
snapshots, err := restic.ReadSnapshots()
AssertEqualFail(t, "unexpected error reading snapshots", nil, err)
AssertEqual(t, "unexpected number of snapshots", 1, len(snapshots))
AssertEqual(t, "unexpected snapshot value: hostname", expectedHostname, snapshots[0].Hostname)
AssertEqual(t, "unexpected snapshot value: paths", []string{dataDir}, snapshots[0].Paths)
AssertEqual(t, "unexpected snapshot value: tags", []string{"test"}, snapshots[0].Tags)
// Backup again
2022-11-10 21:30:30 +00:00
err = restic.Backup([]string{dataDir}, main.BackupOpts{}) //nolint:exhaustruct
AssertEqualFail(t, "unexpected error creating making second backup", nil, err)
// Check for second backup
snapshots, err = restic.ReadSnapshots()
AssertEqualFail(t, "unexpected error reading second snapshots", nil, err)
AssertEqual(t, "unexpected number of snapshots", 2, len(snapshots))
// Forget one backup
2022-11-10 21:30:30 +00:00
err = restic.Forget(main.ForgetOpts{KeepLast: 1, Prune: true}) //nolint:exhaustruct
AssertEqualFail(t, "unexpected error forgetting snapshot", nil, err)
// Check forgotten snapshot
snapshots, err = restic.ReadSnapshots()
AssertEqualFail(t, "unexpected error reading post forget snapshots", nil, err)
AssertEqual(t, "unexpected number of snapshots", 1, len(snapshots))
// Check restic repo
err = restic.Check()
AssertEqualFail(t, "unexpected error checking repo", nil, err)
// Change the data file
2024-01-06 23:10:29 +00:00
err = os.WriteFile(dataFile, []byte("unexpected"), 0o644)
AssertEqualFail(t, "unexpected error writing to test file", nil, err)
// Check that data wrote
value, err := os.ReadFile(dataFile)
AssertEqualFail(t, "unexpected error reading from test file", nil, err)
AssertEqualFail(t, "incorrect value in test file (we expect the unexpected!)", "unexpected", string(value))
// Restore files
2022-11-10 21:30:30 +00:00
err = restic.Restore("latest", main.RestoreOpts{Target: restoreTarget}) //nolint:exhaustruct
AssertEqualFail(t, "unexpected error restoring latest snapshot", nil, err)
// Check restored values
value, err = os.ReadFile(restoredDataFile)
AssertEqualFail(t, "unexpected error reading from test file", nil, err)
AssertEqualFail(t, "incorrect value in test file", "testing", string(value))
// Try to unlock the repo (repo shouldn't really be locked, but this should still run without error
err = restic.Unlock(main.UnlockOpts{}) //nolint:exhaustruct
AssertEqualFail(t, "unexpected error unlocking repo", nil, err)
}