package bot import ( "testing" "time" ) func TestBackoffDelay(t *testing.T) { hourly := &ScheduleSpec{Every: "1h"} if err := hourly.validate(); err != nil { t.Fatal(err) } cases := []struct { fails int want time.Duration }{ {0, 0}, // no failures — the schedule stands {1, 2 * time.Hour}, {2, 4 * time.Hour}, {3, 8 * time.Hour}, {5, 24 * time.Hour}, // 32h doubled — capped at a day {50, 24 * time.Hour}, // deep outage must not overflow past the cap } for _, c := range cases { if got := backoffDelay(hourly, c.fails); got != c.want { t.Errorf("backoffDelay(1h, %d) = %s, want %s", c.fails, got, c.want) } } // Daily (at) schedules never stretch — their cadence is already gentle. daily := &ScheduleSpec{At: "08:00", TZ: "Europe/Dublin"} if err := daily.validate(); err != nil { t.Fatal(err) } for _, fails := range []int{0, 1, 7} { if got := backoffDelay(daily, fails); got != 0 { t.Errorf("backoffDelay(daily, %d) = %s, want 0", fails, got) } } } func TestTaskResultSourcesDown(t *testing.T) { cases := []struct { res taskResult want bool }{ {taskResult{fetches: 2, fetchOK: 0}, true}, // every source failed {taskResult{fetches: 2, fetchOK: 1}, false}, // partial reads still count as an edition {taskResult{fetches: 0, fetchOK: 0}, false}, // a no-fetch task (daily poem) can't be "down" } for _, c := range cases { if got := c.res.sourcesDown(); got != c.want { t.Errorf("sourcesDown(%+v) = %v, want %v", c.res, got, c.want) } } }