Files

86 lines
3.1 KiB
Go

package backup
import (
"io"
"log"
"os"
"path/filepath"
"strings"
"testing"
)
// R-658 (v0.268.0) — the unit restore recreated each named volume with a bare `docker volume create`,
// so the volume carried no compose label; the undo (until v0.267.0) selected volumes by that label and
// copied nothing after any restore. The restore now creates the volume WITH compose's labels.
//
// The docker here is a STUB script in t.TempDir() on PATH (R-650's seam) that records every call.
//
// COMPANION RED-PROOF (REPORT.md): drop composeVolumeLabelArgs from the create call. This test then
// fails at "the restore created vikunja_files WITHOUT the project label".
func TestR658_RestoreCreatesLabelledVolumes(t *testing.T) {
bin := t.TempDir()
calls := filepath.Join(bin, "calls.log")
stub := "#!/bin/sh\necho \"$@\" >> " + calls + "\n" +
"case \"$*\" in 'compose version --short') echo v2.29.7;; esac\nexit 0\n"
if err := os.WriteFile(filepath.Join(bin, "docker"), []byte(stub), 0o755); err != nil {
t.Fatal(err)
}
t.Setenv("PATH", bin+string(os.PathListSeparator)+os.Getenv("PATH"))
dump := t.TempDir()
for _, n := range []string{"vikunja_files.tar", "vikunja_db.tar"} {
if err := os.WriteFile(filepath.Join(dump, n), []byte("tar"), 0o644); err != nil {
t.Fatal(err)
}
}
m := &Manager{logger: log.New(io.Discard, "", 0)}
n, err := m.restoreDockerVolumesFrom("vikunja", dump)
if err != nil || n != 2 {
t.Fatalf("restored %d, err %v — want 2, nil", n, err)
}
b, _ := os.ReadFile(calls)
var creates []string
for _, l := range strings.Split(string(b), "\n") {
if strings.HasPrefix(l, "volume create") {
creates = append(creates, l)
}
}
if len(creates) != 2 {
t.Fatalf("want 2 volume creates, got %q", creates)
}
for _, want := range []struct{ vol, key string }{{"vikunja_files", "files"}, {"vikunja_db", "db"}} {
found := false
for _, c := range creates {
if !strings.HasSuffix(c, " "+want.vol) {
continue
}
found = true
if !strings.Contains(c, "--label com.docker.compose.project=vikunja") {
t.Fatalf("the restore created %s WITHOUT the project label: %q", want.vol, c)
}
if !strings.Contains(c, "--label com.docker.compose.volume="+want.key) {
t.Fatalf("the restore created %s without its volume key %q: %q", want.vol, want.key, c)
}
if !strings.Contains(c, "--label com.docker.compose.version=2.29.7") {
t.Fatalf("the restore created %s without the compose version: %q", want.vol, c)
}
if strings.Contains(c, "config-hash") {
t.Fatalf("a guessed config-hash label would make compose offer to recreate the volume: %q", c)
}
}
if !found {
t.Fatalf("no create for %s in %q", want.vol, creates)
}
}
}
// A volume without the `<project>_` prefix is created without labels — never with a guessed key.
func TestR658_LabelArgsNeverGuessAKey(t *testing.T) {
if got := composeVolumeLabelArgs("vikunja", "custom_name", "2.29.7"); got != nil {
t.Fatalf("got %v, want no labels", got)
}
if got := composeVolumeLabelArgs("vikunja", "vikunja_db", ""); len(got) != 4 {
t.Fatalf("an unreadable version drops only the version label; got %v", got)
}
}