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\":\"summary\",\"snapshot_id\":\"abc123\",\"data_added\":42,\"files_new\":3}'\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"}} summary, err := runner.Backup(context.Background(), repo, job, []string{"/source path"}) if err != nil { t.Fatal(err) } if summary.SnapshotID != "abc123" || summary.DataAdded != 42 { t.Fatalf("unexpected summary: %+v", summary) } 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") } }