99 lines
3.2 KiB
Go
99 lines
3.2 KiB
Go
package agent
|
||
|
||
import (
|
||
"context"
|
||
"net/http"
|
||
"net/http/httptest"
|
||
"reflect"
|
||
"testing"
|
||
"time"
|
||
)
|
||
|
||
const page = `<!doctype html><html><head><TITLE> Shop - Willkommen </TITLE></head>
|
||
<body><h1>Hallo</h1><h2 class="fuss"><a href="/impressum">Impressum</a></h2></body></html>`
|
||
|
||
func healthServer(t *testing.T, status int, body string, delay time.Duration) string {
|
||
t.Helper()
|
||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
if delay > 0 {
|
||
select {
|
||
case <-time.After(delay):
|
||
case <-r.Context().Done():
|
||
return
|
||
}
|
||
}
|
||
w.WriteHeader(status)
|
||
w.Write([]byte(body))
|
||
}))
|
||
t.Cleanup(srv.Close)
|
||
return srv.URL
|
||
}
|
||
|
||
func TestCheckHealth(t *testing.T) {
|
||
ok := healthServer(t, 200, page, 0)
|
||
tests := []struct {
|
||
name string
|
||
url string
|
||
spec HealthSpec
|
||
ok bool
|
||
}{
|
||
{"nur Status", ok, HealthSpec{ExpectStatus: 200}, true},
|
||
{"Titel passt (Leerraum, Großschreibung des Tags egal)", ok, HealthSpec{ExpectStatus: 200, ExpectTitle: "Shop - Willkommen"}, true},
|
||
{"Tag mit Text, verschachtelt", ok, HealthSpec{ExpectStatus: 200, ExpectContains: &ContainsSpec{Tag: "H2", Text: "Impressum"}}, true},
|
||
{"falscher Status", healthServer(t, 500, page, 0), HealthSpec{ExpectStatus: 200}, false},
|
||
{"anderer erwarteter Status", healthServer(t, 204, "", 0), HealthSpec{ExpectStatus: 204}, true},
|
||
{"Titel weicht ab", ok, HealthSpec{ExpectStatus: 200, ExpectTitle: "Wartung"}, false},
|
||
{"Text fehlt", ok, HealthSpec{ExpectStatus: 200, ExpectContains: &ContainsSpec{Tag: "h2", Text: "Datenschutz"}}, false},
|
||
{"Text im falschen Tag", ok, HealthSpec{ExpectStatus: 200, ExpectContains: &ContainsSpec{Tag: "h1", Text: "Impressum"}}, false},
|
||
{"Zeitüberschreitung", healthServer(t, 200, page, time.Second), HealthSpec{ExpectStatus: 200, Timeout: Duration{50 * time.Millisecond}}, false},
|
||
{"nicht erreichbar", "http://127.0.0.1:1", HealthSpec{ExpectStatus: 200}, false},
|
||
}
|
||
for _, tt := range tests {
|
||
if tt.spec.Timeout.Duration == 0 {
|
||
tt.spec.Timeout = Duration{2 * time.Second}
|
||
}
|
||
tt.spec.URL = tt.url
|
||
err := checkHealth(context.Background(), http.DefaultClient, tt.spec)
|
||
if (err == nil) != tt.ok {
|
||
t.Errorf("%s: err=%v, erwartet ok=%v", tt.name, err, tt.ok)
|
||
}
|
||
}
|
||
}
|
||
|
||
// Ausfall erst nach N Fehlschlägen in Folge, Erholung nach einem Erfolg –
|
||
// gegen Flattern.
|
||
func TestHealthTracker(t *testing.T) {
|
||
var tr healthTracker
|
||
steps := []struct {
|
||
ok bool
|
||
changed bool
|
||
down []string
|
||
}{
|
||
{true, false, nil},
|
||
{false, false, nil},
|
||
{true, false, nil}, // Zähler zurückgesetzt
|
||
{false, false, nil},
|
||
{false, true, []string{"shop"}},
|
||
{false, false, []string{"shop"}},
|
||
{true, true, nil},
|
||
}
|
||
for i, s := range steps {
|
||
if changed := tr.report("shop", 2, s.ok); changed != s.changed {
|
||
t.Errorf("Schritt %d: changed=%v, erwartet %v", i, changed, s.changed)
|
||
}
|
||
if got := tr.down(); !reflect.DeepEqual(got, s.down) {
|
||
t.Errorf("Schritt %d: down=%v, erwartet %v", i, got, s.down)
|
||
}
|
||
}
|
||
|
||
tr.report("a", 1, false)
|
||
tr.report("b", 1, false)
|
||
if got := tr.down(); !reflect.DeepEqual(got, []string{"a", "b"}) {
|
||
t.Errorf("sortiert: %v", got)
|
||
}
|
||
tr.retain(map[string]bool{"b": true})
|
||
if got := tr.down(); !reflect.DeepEqual(got, []string{"b"}) {
|
||
t.Errorf("nach retain: %v", got)
|
||
}
|
||
}
|