Files
felhom.eu/hub/internal/notify/r723_first_hour_test.go
T

66 lines
2.5 KiB
Go

package notify
import (
"database/sql"
"io"
"log"
"path/filepath"
"testing"
"time"
"gitea.dooplex.hu/admin/felhom-hub/internal/store"
_ "modernc.org/sqlite"
)
// storeWithHost opens a store with customer c1 and one host enrolled `ago` before now.
func storeWithHost(t *testing.T, ago time.Duration) *store.Store {
t.Helper()
path := filepath.Join(t.TempDir(), "d.db")
st, err := store.New(path, log.New(io.Discard, "", 0))
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() { st.Close() })
st.SaveCustomerConfig(&store.CustomerConfig{CustomerID: "c1", APIKey: "k", RetrievalPassword: "p"})
if err := st.UpsertHost(&store.Host{HostID: "c1-abc123", CustomerID: "c1", APIKey: "hk"}); err != nil {
t.Fatal(err)
}
db, err := sql.Open("sqlite", path)
if err != nil {
t.Fatal(err)
}
defer db.Close()
if _, err := db.Exec(`UPDATE hosts SET created_at = ? WHERE host_id = 'c1-abc123'`,
time.Now().UTC().Add(-ago).Format("2006-01-02 15:04:05")); err != nil {
t.Fatal(err)
}
return st
}
const tierSkipMsg = "Whole-guest backup tier felhom-pbs skipped: its storage does not exist on the host (never provisioned or removed). No app was stopped for it."
// R-723 (v0.126.0) — the 2026-09-29 shape: the first whole-guest run fired 7 min after enrolment, before
// the off-site descriptor arrived, and the operator was mailed „skipped". The CONSEQUENCE asserted: no
// operator mail in a box's first hour.
// COMPANION RED-PROOF: drop the first-hour check in processOperator → 1 operator mail.
func TestR723_FirstHourTierSkipIsNotMailed(t *testing.T) {
st := storeWithHost(t, 7*time.Minute)
d := NewDispatcher(st, "test-key", "hub@felhom.eu", "op@felhom.eu", true, log.New(io.Discard, "", 0))
mails := captureSeam(d)
d.ProcessEvent("c1", "backup_tier_skipped", "warning", tierSkipMsg, `{"tier":"felhom-pbs"}`, "controller")
if op := mailsFor(*mails, "op@felhom.eu"); len(op) != 0 {
t.Fatalf("a first-hour tier skip mailed the operator (%d mails)", len(op))
}
}
// Control: the same skip on a box enrolled a week ago is a real provisioning gap and still mails.
func TestR723_TierSkipOnAnOldBoxStillMails(t *testing.T) {
st := storeWithHost(t, 7*24*time.Hour)
d := NewDispatcher(st, "test-key", "hub@felhom.eu", "op@felhom.eu", true, log.New(io.Discard, "", 0))
mails := captureSeam(d)
d.ProcessEvent("c1", "backup_tier_skipped", "warning", tierSkipMsg, `{"tier":"felhom-pbs"}`, "controller")
if op := mailsFor(*mails, "op@felhom.eu"); len(op) != 1 {
t.Fatalf("an old box's tier skip must still mail the operator, got %d", len(op))
}
}