package health import ( "encoding/json" "net/http" "net/http/httptest" "testing" "time" ) func TestProbeHealthyAtBoot(t *testing.T) { p := New(time.Minute) if !p.Healthy() { t.Fatal("probe should be healthy immediately after creation") } } func TestProbeStaleAfterWindow(t *testing.T) { p := New(50 * time.Millisecond) time.Sleep(80 * time.Millisecond) if p.Healthy() { t.Fatal("probe should be stale after the staleness window elapses with no Bump") } p.Bump() if !p.Healthy() { t.Fatal("probe should recover immediately after Bump") } } func TestProbeHandlerStatusCodes(t *testing.T) { p := New(20 * time.Millisecond) // Fresh → 200 if code := probeCode(p); code != http.StatusOK { t.Fatalf("fresh probe: want 200, got %d", code) } // Stale → 503 time.Sleep(40 * time.Millisecond) if code := probeCode(p); code != http.StatusServiceUnavailable { t.Fatalf("stale probe: want 503, got %d", code) } } func TestProbeHandlerBody(t *testing.T) { p := New(time.Minute) rec := httptest.NewRecorder() p.Handler().ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/healthz", nil)) var body map[string]any if err := json.Unmarshal(rec.Body.Bytes(), &body); err != nil { t.Fatalf("invalid JSON body: %v (body=%q)", err, rec.Body.String()) } if body["status"] != "ok" { t.Fatalf("want status=ok, got %v", body["status"]) } if _, ok := body["last_heartbeat"].(string); !ok { t.Fatalf("want last_heartbeat string, got %v", body["last_heartbeat"]) } } func TestNewDefaultsStale(t *testing.T) { p := New(0) if p.stale <= 0 { t.Fatal("New(0) should fall back to a positive staleness window") } } func probeCode(p *Probe) int { rec := httptest.NewRecorder() p.Handler().ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/healthz", nil)) return rec.Code }