package runner import ( "os" "os/exec" "path/filepath" "testing" ) // The one claim this platform makes about `tmctl backup` that no unit test can make: that the LINE // this side parses is the line THIS ENGINE prints, and that what it names is a file. // // ⚠ It is the whole reason the parse is allowed to exist. Reading a path out of another zone's prose // is a coupling with no version on it (17-seam-inbound-law п.3), and the only honest way to hold it // is against the real binary — a fixture string would prove that this file agrees with itself. // When the engine grows a `--out` or a `--json` on this verb, this test is what says the prose form // may go. // // Gated like every live-engine test: a bare clone stays green and says why. func TestTheRealEngineNamesItsRestorePointInTheLineThisPlatformParses(t *testing.T) { bin := os.Getenv("TM_PLATFORM_TEST_ENGINE_BIN") tpl := os.Getenv("TM_PLATFORM_TEST_BOOK_TEMPLATE") if bin == "" || tpl == "" { t.Skip("TM_PLATFORM_TEST_ENGINE_BIN and TM_PLATFORM_TEST_BOOK_TEMPLATE not set: " + "the backup verb's output is not checked against a real engine") } dir := t.TempDir() writeProbeBook(t, tpl, dir, "bk_BACKUPPROBE") // A book with no project database is the state a fresh directory is in, and the engine refuses // there rather than failing — pinned first, because that refusal is what the backup pass reads as // "nothing to copy yet" and it must not be an error. empty, err := New(nil).Backup(t.Context(), bin, dir) if err != nil { t.Fatalf("a book with no database raised an error instead of answering: %v", err) } if !empty.Exited || empty.ExitCode == 0 || empty.Path != "" { t.Fatalf("a book with no database was reported as backed up: %+v", empty) } // `manifest` is the $0 verb that CREATES and migrates the project database (backend/cmd/tmctl, // manifestCmd: "it opens the store exactly as `status` does … EXCEPT on the first touch"). cmd := exec.CommandContext(t.Context(), bin, "manifest", "--config", filepath.Join(dir, ConfigFile)) cmd.Dir = dir if out, err := cmd.CombinedOutput(); err != nil { t.Fatalf("could not give the probe book a project database: %v\n%s", err, out) } out, err := New(nil).Backup(t.Context(), bin, dir) if err != nil { t.Fatalf("the live backup verb was not readable: %v (stderr %q)", err, out.Stderr) } if !out.Exited || out.ExitCode != 0 { t.Fatalf("the live backup verb refused: %+v (stderr %q)", out, out.Stderr) } if out.Path == "" { t.Fatal("the live backup verb exited 0 and this platform read no path out of it") } fi, err := os.Stat(out.Path) if err != nil { t.Fatalf("the path this platform parsed is not a file: %v", err) } if fi.Size() == 0 { t.Errorf("the restore point the engine named is empty: %s", out.Path) } // Inside the book, which is the guard the parse enforces and the copier relies on. if rel, err := filepath.Rel(dir, out.Path); err != nil || rel == ".." { t.Errorf("the engine's restore point is not inside the book's directory: %s", out.Path) } }