Found live on 9201: neither sched.Daily nor sched.Every fires on registration, so a box booting with a filesystem already over the line would stay silent for up to 24h — the R-100 shape, and the same gap the hub's own checkers avoid by leaving already-breached keys unseeded at init. The watcher now runs once 90s after startup as well. Safe because the check is edge-triggered against persisted state: an already-warned filesystem stays silent. The delay lets mounts settle so a drive still returning reads as unreadable and is skipped rather than warned about. Pinned by an AST assertion — the schedule registration alone no longer satisfies the test.
This commit is contained in:
@@ -421,6 +421,49 @@ func TestMainWiresTheFillWatcher(t *testing.T) {
|
||||
t.Fatal("the fill watcher is never registered on the scheduler — it would be constructed, " +
|
||||
"wired, and never run, which is indistinguishable from a filesystem that never fills")
|
||||
}
|
||||
|
||||
// It must ALSO run once at startup. Neither `Every` nor `Daily` fires on registration (both wait
|
||||
// for their first tick), so a schedule-only wiring means a box that BOOTS with a filesystem
|
||||
// already over the line stays silent for up to 24 hours — a real fault visible only after a
|
||||
// deadline elapses, which is the R-100 shape. The hub's own checkers leave already-breached keys
|
||||
// unseeded at init for exactly this reason.
|
||||
if indexOfCall(names, "After") < 0 {
|
||||
t.Fatal("nothing delays a startup fill check — see fillWatchStartupDelay")
|
||||
}
|
||||
startupRun := false
|
||||
ast.Inspect(body, func(n ast.Node) bool {
|
||||
g, ok := n.(*ast.GoStmt)
|
||||
if !ok || g.Call == nil {
|
||||
return true
|
||||
}
|
||||
lit, ok := g.Call.Fun.(*ast.FuncLit)
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
var sawDelay, sawCheck bool
|
||||
ast.Inspect(lit.Body, func(m ast.Node) bool {
|
||||
if id, ok := m.(*ast.Ident); ok && id.Name == "fillWatchStartupDelay" {
|
||||
sawDelay = true
|
||||
}
|
||||
if call, ok := m.(*ast.CallExpr); ok {
|
||||
if sel, ok := call.Fun.(*ast.SelectorExpr); ok && sel.Sel.Name == "Check" {
|
||||
if x, ok := sel.X.(*ast.Ident); ok && x.Name == "fillWatcher" {
|
||||
sawCheck = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
if sawDelay && sawCheck {
|
||||
startupRun = true
|
||||
}
|
||||
return true
|
||||
})
|
||||
if !startupRun {
|
||||
t.Fatal("the fill watcher never runs at STARTUP — Daily/Every both wait for their first " +
|
||||
"tick, so a box that boots with a full disk would not warn for up to 24 hours (the " +
|
||||
"R-100 shape: a real fault visible only after a deadline elapses)")
|
||||
}
|
||||
}
|
||||
|
||||
// assignsIdent reports whether a block assigns to the named identifier.
|
||||
|
||||
Reference in New Issue
Block a user