// This file is part of the happyDomain (R) project. // Copyright (c) 2020-2026 happyDomain // Authors: Pierre-Olivier Mercier, et al. package checker import ( "context" "encoding/json" "testing" sdk "git.happydns.org/checker-sdk-go/checker" ) // fakeObs is an in-memory ObservationGetter backed by a single HTTPData // payload stored under ObservationKeyHTTP. A nil payload makes Get return // an error, which lets tests cover the loadHTTPData failure branch. type fakeObs struct { data *HTTPData failGet bool } func (f *fakeObs) Get(_ context.Context, key sdk.ObservationKey, dest any) error { if f.failGet { return errString("forced get failure") } if key != ObservationKeyHTTP { return errString("unexpected key: " + key) } if f.data == nil { return errString("no data") } raw, err := json.Marshal(f.data) if err != nil { return err } return json.Unmarshal(raw, dest) } func (f *fakeObs) GetRelated(_ context.Context, _ sdk.ObservationKey) ([]sdk.RelatedObservation, error) { return nil, nil } type errString string func (e errString) Error() string { return string(e) } // runRule is a small wrapper that builds a fakeObs around the supplied // HTTPData and evaluates the rule with the given options. It returns the // states verbatim; assertion is left to the caller. func runRule(t *testing.T, r sdk.CheckRule, data *HTTPData, opts sdk.CheckerOptions) []sdk.CheckState { t.Helper() if opts == nil { opts = sdk.CheckerOptions{} } states := r.Evaluate(context.Background(), &fakeObs{data: data}, opts) if len(states) == 0 { t.Fatalf("rule %q returned no states (must always return at least one)", r.Name()) } return states } func httpsProbe(addr string) HTTPProbe { return HTTPProbe{ Scheme: "https", Host: "example.test", IP: "203.0.113.1", Port: 443, Address: addr, TCPConnected: true, StatusCode: 200, Headers: map[string]string{}, } } func httpProbe(addr string) HTTPProbe { p := httpsProbe(addr) p.Scheme = "http" p.Port = 80 return p } func mustStatus(t *testing.T, states []sdk.CheckState, want sdk.Status) { t.Helper() for _, s := range states { if s.Status != want { t.Fatalf("status: got %s (%q), want %s; full states: %+v", s.Status, s.Code, want, states) } } } // ruleByName looks a rule up in the global registry by Name(). It exists // so tests can drive rules wired declaratively (HeaderRule and friends) // without depending on a concrete type. func ruleByName(t *testing.T, name string) sdk.CheckRule { t.Helper() for _, r := range Rules() { if r.Name() == name { return r } } t.Fatalf("rule %q not found in registry", name) return nil } func hasCode(states []sdk.CheckState, code string) bool { for _, s := range states { if s.Code == code { return true } } return false }