Files
felhom.eu/hub/internal/store/r435_windows_between_test.go
T
admin d34dfc84c0 hub: one lost off-site snapshot outside a clean-up window is an error (R-435, D7)
On a pinned tier (the hub holds a CONFIRMED append-only key) the only
legitimate fall of the box's snapshot count is a clean-up window the hub
opened. The checker now compares prev - cur with what the windows closed
since the previous trustworthy report removed (store.RemovedByWindowsBetween,
2 h slack for the in-run count lag); any unexplained fall, even one snapshot,
raises offsite_snapshots_dropped (error) saying 'outside any clean-up window
the hub opened'. A window that cannot say what it removed (timeout, still
open) explains anything: no alarm, one INFO line. Non-pinned tiers keep the
half-rule. Untrustworthy reports: unchanged (no alarm, baseline kept).

Red tests: r435_pinned_drop_test.go (3 fail with the pinned rule disabled;
WindowExplainsFall fails when windows are ignored), r435_windows_between_test.go.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-10-08 15:17:05 +02:00

47 lines
1.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package store
import (
"testing"
"time"
)
// R-435: RemovedByWindowsBetween sums only windows closed inside the interval, and says „unknown"
// for a window that cannot say what it removed.
func TestR435_RemovedByWindowsBetween(t *testing.T) {
s := newTestStore(t)
at := func(ts string) time.Time { v, _ := time.Parse("2006-01-02 15:04:05", ts); return v }
ins := func(cust, opened, closed string, before, after any) {
t.Helper()
var c any
if closed != "" {
c = closed
}
if _, err := s.db.Exec(`INSERT INTO offsite_windows (customer_id, opened_at, closes_by, closed_at, count_before, count_after) VALUES (?, ?, ?, ?, ?, ?)`,
cust, opened, opened, c, before, after); err != nil {
t.Fatal(err)
}
}
ins("a", "2026-10-01 03:00:00", "2026-10-01 03:10:00", 69, 60) // inside → 9
ins("a", "2026-09-20 03:00:00", "2026-09-20 03:10:00", 80, 69) // before the interval
ins("a", "2026-10-03 03:00:00", "2026-10-03 03:10:00", 60, 50) // after the interval
ins("b", "2026-10-01 03:00:00", "2026-10-01 03:10:00", 50, 40) // another customer
from, to := at("2026-09-30 00:00:00"), at("2026-10-02 00:00:00")
if n, unk := s.RemovedByWindowsBetween("a", from, to); n != 9 || unk {
t.Fatalf("a: want 9 known, got %d unknown=%v", n, unk)
}
if n, unk := s.RemovedByWindowsBetween("c", from, to); n != 0 || unk {
t.Fatalf("no window: want 0 known, got %d unknown=%v", n, unk)
}
// a timeout close (count_after −1) inside the interval → unknown
ins("d", "2026-10-01 03:00:00", "2026-10-01 03:40:00", 69, -1)
if _, unk := s.RemovedByWindowsBetween("d", from, to); !unk {
t.Fatal("a timeout-closed window must make the interval unknown")
}
// a window still open → unknown
ins("e", "2026-10-01 03:00:00", "", 69, nil)
if _, unk := s.RemovedByWindowsBetween("e", from, to); !unk {
t.Fatal("an open window must make the interval unknown")
}
}