package host import ( "errors" "os" "path/filepath" "testing" "time" ) func TestSystemPathsAreDerivedNotTrusted(t *testing.T) { if got := systemCachePath("/data", "v1.2.3"); got != "/data/system/router/v1.2.3/carlos" { t.Fatalf("cache path = %s", got) } if got := systemRequestPath("/data"); got != "/data/system/router/requested.json" { t.Fatalf("request path = %s", got) } if got := systemRootDir("/opt/carlos"); got != "/opt/carlos/system/router" { t.Fatalf("root dir = %s", got) } for _, bad := range []string{"", ".", "..", "../x", "a/b", ".hidden", "v1 2", string(make([]byte, 65))} { if validSystemVersion(bad) { t.Errorf("validSystemVersion(%q) = true", bad) } } for _, good := range []string{"v0.18.0", "66587fa", "a", "release-2026.09.06_rc1"} { if !validSystemVersion(good) { t.Errorf("validSystemVersion(%q) = false", good) } } } func TestWriteFileDurableLeavesWholeFileOrNothing(t *testing.T) { dir := t.TempDir() p := filepath.Join(dir, "journal.json") if err := writeFileDurable(p, []byte("one"), 0o644); err != nil { t.Fatal(err) } if err := writeFileDurable(p, []byte("two"), 0o644); err != nil { t.Fatal(err) } b, _ := os.ReadFile(p) if string(b) != "two" { t.Fatalf("content = %q", b) } if _, err := os.Stat(p + ".tmp"); !errors.Is(err, os.ErrNotExist) { t.Fatal("temp left behind") } st, _ := os.Stat(p) if st.Mode().Perm() != 0o644 { t.Fatalf("mode = %v", st.Mode().Perm()) } // A directory that does not exist is an error, not a silent no-op. if err := writeFileDurable(filepath.Join(dir, "no", "such", "f"), []byte("x"), 0o644); err == nil { t.Fatal("wrote into a missing directory") } } func TestSystemStateReadersRoundTrip(t *testing.T) { opt := t.TempDir() root := systemRootDir(opt) if err := os.MkdirAll(root, 0o755); err != nil { t.Fatal(err) } if r, err := readSystemResult(opt); err != nil || r != nil { t.Fatalf("missing result: %v %v", r, err) } seen, err := readSystemSeen(opt) if err != nil || len(seen) != 0 { t.Fatalf("missing seen: %v %v", seen, err) } if a, err := readSystemApplied(opt); err != nil || a != nil { t.Fatalf("missing applied: %v %v", a, err) } if j, err := readSystemJournal(opt); err != nil || j != nil { t.Fatalf("missing journal: %v %v", j, err) } var nilResult *systemResult if nilResult.matches("stable", "v1", time.Time{}) || nilResult.terminal() { t.Fatal("nil *systemResult must answer matches/terminal as false, not panic") } at := time.Date(2026, 9, 6, 9, 0, 0, 0, time.UTC) res := systemResult{Channel: "stable", Version: "v1", PromotedAt: at, Outcome: systemOutcomeRolledBack, Reason: "gate", At: at} if err := writeJSONDurable(filepath.Join(root, "result.json"), res, 0o644); err != nil { t.Fatal(err) } got, err := readSystemResult(opt) if err != nil || !got.matches("stable", "v1", at) || !got.terminal() { t.Fatalf("result = %+v err=%v", got, err) } if got.matches("canary", "v1", at) || got.matches("stable", "v2", at) || got.matches("stable", "v1", at.Add(time.Second)) { t.Fatal("matches ignores part of the tuple") } got.Outcome = systemOutcomeDeferred if got.terminal() { t.Fatal("deferred is not terminal") } got.Outcome = systemOutcomeNoted if got.terminal() { t.Fatal("noted is not terminal for the leg: the version may still differ next time") } seen["stable"] = at if err := writeJSONDurable(filepath.Join(root, "seen.json"), seen, 0o644); err != nil { t.Fatal(err) } seen2, _ := readSystemSeen(opt) if !seen2["stable"].Equal(at) { t.Fatalf("seen = %v", seen2) } j := systemJournal{Phase: systemPhaseInstalled, Target: "v1", PromotedAt: at.Add(-time.Hour), PrevBuild: "v0", UnitsAdded: []string{"a.path"}, StartedAt: at} if err := writeJSONDurable(filepath.Join(root, "journal.json"), j, 0o600); err != nil { t.Fatal(err) } j2, err := readSystemJournal(opt) if err != nil || j2.Phase != systemPhaseInstalled || j2.UnitsAdded[0] != "a.path" || !j2.promoted().Equal(at.Add(-time.Hour)) { t.Fatalf("journal = %+v err=%v", j2, err) } // A journal from before the field existed still names its apply. old := &systemJournal{Phase: systemPhaseInstalled, Target: "v1", StartedAt: at} if !old.promoted().Equal(at) { t.Fatalf("promoted = %v, want the started_at a journal without promoted_at has", old.promoted()) } applied := systemApplied{Version: "v1", Channel: "stable", At: at} if err := writeJSONDurable(filepath.Join(root, "applied.json"), applied, 0o644); err != nil { t.Fatal(err) } a2, err := readSystemApplied(opt) if err != nil || a2.Version != "v1" || a2.Channel != "stable" || !a2.At.Equal(at) { t.Fatalf("applied = %+v err=%v", a2, err) } }