Files
URBM/internal/restic/restic_test.go
T

91 lines
4.1 KiB
Go

package restic
import (
"context"
"fmt"
"os"
"path/filepath"
"strings"
"testing"
"github.com/backupper-unraid/backupper/internal/model"
)
type fakeSecrets map[string]string
func (s fakeSecrets) Get(id string) (string, error) { return s[id], nil }
func TestBackupUsesPasswordFileAndStructuredArguments(t *testing.T) {
dir := t.TempDir()
argsPath := filepath.Join(dir, "args")
passwordPath := filepath.Join(dir, "password")
script := filepath.Join(dir, "restic")
body := fmt.Sprintf("#!/bin/sh\nprintf '%%s\\n' \"$@\" > '%s'\ncat \"$RESTIC_PASSWORD_FILE\" > '%s'\nprintf '%%s\\n' '{\"message_type\":\"status\",\"percent_done\":0.5,\"total_files\":12,\"files_done\":6,\"total_bytes\":1024,\"bytes_done\":512,\"seconds_remaining\":4,\"current_files\":[\"/source path/file.txt\"]}'\nprintf '%%s\\n' '{\"message_type\":\"summary\",\"snapshot_id\":\"abc123\",\"data_added\":42,\"files_new\":3,\"files_changed\":2,\"total_bytes_processed\":1024,\"total_files_processed\":12}'\n", argsPath, passwordPath)
if err := os.WriteFile(script, []byte(body), 0700); err != nil {
t.Fatal(err)
}
runner := &Runner{Binary: script, RuntimeDir: dir, Secrets: fakeSecrets{"password": "top-secret"}}
repo := model.Repository{Type: model.RepositoryLocal, Location: "/repo path", PasswordRef: "password"}
job := model.Job{ID: "job", Compression: "auto", Tags: []string{"daily"}, Excludes: []string{"*.tmp"}}
var progress Progress
summary, err := runner.Backup(context.Background(), repo, job, []string{"/source path"}, func(value Progress) { progress = value })
if err != nil {
t.Fatal(err)
}
if summary.SnapshotID != "abc123" || summary.DataAdded != 42 || summary.FilesChanged != 2 || summary.TotalBytesProcessed != 1024 || summary.TotalFilesProcessed != 12 {
t.Fatalf("unexpected summary: %+v", summary)
}
if progress.PercentDone != 0.5 || progress.FilesDone != 6 || progress.BytesDone != 512 || len(progress.CurrentFiles) != 1 {
t.Fatalf("unexpected progress: %+v", progress)
}
args, _ := os.ReadFile(argsPath)
for _, expected := range []string{"/repo path", "backup", "--json", "/source path"} {
if !strings.Contains(string(args), expected) {
t.Fatalf("arguments missing %q: %s", expected, args)
}
}
password, _ := os.ReadFile(passwordPath)
if string(password) != "top-secret" {
t.Fatal("password file was not provided")
}
}
func TestForgetUsesAgeAndCalendarRetention(t *testing.T) {
dir := t.TempDir()
argsPath := filepath.Join(dir, "args")
script := filepath.Join(dir, "restic")
body := fmt.Sprintf("#!/bin/sh\nprintf '%%s\\n' \"$@\" > '%s'\n", argsPath)
if err := os.WriteFile(script, []byte(body), 0700); err != nil {
t.Fatal(err)
}
runner := &Runner{Binary: script, RuntimeDir: dir, Secrets: fakeSecrets{"password": "secret"}}
repo := model.Repository{Type: model.RepositoryLocal, Location: "/repo", PasswordRef: "password"}
job := model.Job{ID: "job", Retention: model.Retention{KeepWithinDays: 30, Weekly: 4, Monthly: 12}}
if err := runner.Forget(context.Background(), repo, job); err != nil {
t.Fatal(err)
}
args, _ := os.ReadFile(argsPath)
for _, expected := range []string{"--keep-within", "30d", "--keep-weekly", "4", "--keep-monthly", "12"} {
if !strings.Contains(string(args), expected) {
t.Fatalf("retention arguments missing %q: %s", expected, args)
}
}
if strings.Contains(string(args), "--keep-daily") {
t.Fatalf("disabled daily retention was included: %s", args)
}
}
func TestResticErrorExplainsExistingRepository(t *testing.T) {
err := resticError("Fatal: create repository failed: config file already exists", fmt.Errorf("exit status 1"))
if !strings.Contains(err.Error(), "already initialized") || !strings.Contains(err.Error(), "select Test") {
t.Fatalf("unexpected error: %v", err)
}
}
func TestResticErrorExplainsCiphertextVerification(t *testing.T) {
err := resticError(`{"message_type":"exit_error","message":"Fatal: config or key abc is damaged: ciphertext verification failed"}`, fmt.Errorf("exit status 1"))
if !strings.Contains(err.Error(), "password does not match") || strings.Contains(err.Error(), "abc") {
t.Fatalf("unexpected error: %v", err)
}
}