checker-http/checker/testhelpers_test.go

113 lines
2.8 KiB
Go

// 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
}