package quiesce import ( "bytes" "log" "os" "path/filepath" "strings" "testing" "time" ) // T-S3a: a corrupt marker is quarantined + logged (not silently dropped). Still returns false. // Companion: pre-fix readMarker (silent return false) → no *.corrupt-* + no log → this fails. func TestReadMarker_QuarantinesCorrupt(t *testing.T) { mp := filepath.Join(t.TempDir(), "quiesce-state.json") if err := os.WriteFile(mp, []byte(`{ "active": true, BROKEN not json`), 0o644); err != nil { t.Fatal(err) } var buf bytes.Buffer l := New(Options{ MarkerPath: mp, Poll: time.Hour, StatusPoll: time.Millisecond, MaxQuiesce: time.Second, Logger: log.New(&buf, "", 0), }) if _, ok := l.readMarker(); ok { t.Fatal("corrupt marker must return ok=false") } if m, _ := filepath.Glob(mp + ".corrupt-*"); len(m) == 0 { t.Error("corrupt marker must be quarantined as *.corrupt-*") } if !strings.Contains(buf.String(), "corrupt") { t.Errorf("expected a WARN about the corrupt marker, got: %q", buf.String()) } } // T-S3b: valid marker → (marker, true), no quarantine (regression). func TestReadMarker_HappyPath(t *testing.T) { mp := filepath.Join(t.TempDir(), "quiesce-state.json") if err := os.WriteFile(mp, []byte(`{"active":true,"stopped_stacks":["romm","komga"]}`), 0o644); err != nil { t.Fatal(err) } l := New(Options{ MarkerPath: mp, Poll: time.Hour, StatusPoll: time.Millisecond, MaxQuiesce: time.Second, Logger: log.New(&bytes.Buffer{}, "", 0), }) m, ok := l.readMarker() if !ok { t.Fatal("valid marker must return ok=true") } if len(m.StoppedStacks) != 2 { t.Errorf("expected 2 stopped stacks, got %d", len(m.StoppedStacks)) } if g, _ := filepath.Glob(mp + ".corrupt-*"); len(g) != 0 { t.Error("happy path must NOT quarantine") } }