128 lines
3.5 KiB
Go
128 lines
3.5 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"
|
|
"net/http"
|
|
"testing"
|
|
|
|
sdk "git.happydns.org/checker-sdk-go/checker"
|
|
)
|
|
|
|
func TestRulesShape(t *testing.T) {
|
|
rs := Rules()
|
|
if len(rs) == 0 {
|
|
t.Fatal("Rules() returned no rules")
|
|
}
|
|
seen := map[string]bool{}
|
|
for _, r := range rs {
|
|
name := r.Name()
|
|
if name == "" {
|
|
t.Errorf("rule with empty name: %T", r)
|
|
}
|
|
if r.Description() == "" {
|
|
t.Errorf("rule %q has empty description", name)
|
|
}
|
|
if seen[name] {
|
|
t.Errorf("duplicate rule name: %q", name)
|
|
}
|
|
seen[name] = true
|
|
}
|
|
|
|
// The two reachability rules must exist with distinct codes per scheme.
|
|
for _, want := range []string{"http.tcp_reachable", "https.tcp_reachable", "http.https_redirect", "http.hsts", "http.csp", "http.x_frame_options", "http.x_content_type_options", "http.x_xss_protection", "http.cookie_flags", "http.sri"} {
|
|
if !seen[want] {
|
|
t.Errorf("missing rule %q in Rules()", want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestLoadHTTPDataFailure(t *testing.T) {
|
|
obs := &fakeObs{failGet: true}
|
|
data, errSt := loadHTTPData(context.Background(), obs)
|
|
if data != nil {
|
|
t.Fatal("expected nil data on failure")
|
|
}
|
|
if errSt == nil || errSt.Status != sdk.StatusError {
|
|
t.Fatalf("expected StatusError, got %+v", errSt)
|
|
}
|
|
if errSt.Code != "http.observation_error" {
|
|
t.Errorf("unexpected code: %q", errSt.Code)
|
|
}
|
|
}
|
|
|
|
func TestLoadHTTPDataSuccess(t *testing.T) {
|
|
want := &HTTPData{Domain: "example.test", Probes: []HTTPProbe{httpsProbe("203.0.113.1:443")}}
|
|
data, errSt := loadHTTPData(context.Background(), &fakeObs{data: want})
|
|
if errSt != nil {
|
|
t.Fatalf("unexpected error state: %+v", errSt)
|
|
}
|
|
if data == nil || data.Domain != "example.test" || len(data.Probes) != 1 {
|
|
t.Fatalf("unexpected data: %+v", data)
|
|
}
|
|
}
|
|
|
|
func TestProbesByScheme(t *testing.T) {
|
|
probes := []HTTPProbe{
|
|
httpProbe("a:80"),
|
|
httpsProbe("a:443"),
|
|
httpProbe("b:80"),
|
|
}
|
|
if got := probesByScheme(probes, "http"); len(got) != 2 {
|
|
t.Errorf("http: got %d, want 2", len(got))
|
|
}
|
|
if got := probesByScheme(probes, "https"); len(got) != 1 {
|
|
t.Errorf("https: got %d, want 1", len(got))
|
|
}
|
|
if got := probesByScheme(probes, "gopher"); got != nil {
|
|
t.Errorf("unknown scheme should return nil, got %+v", got)
|
|
}
|
|
}
|
|
|
|
func TestSuccessfulHTTPSProbes(t *testing.T) {
|
|
failed := httpsProbe("a:443")
|
|
failed.StatusCode = 0
|
|
failed.TCPConnected = false
|
|
probes := []HTTPProbe{
|
|
httpProbe("a:80"),
|
|
httpsProbe("a:443"),
|
|
failed,
|
|
}
|
|
got := successfulHTTPSProbes(probes)
|
|
if len(got) != 1 {
|
|
t.Fatalf("got %d successful HTTPS probes, want 1", len(got))
|
|
}
|
|
if got[0].Address != "a:443" || got[0].StatusCode != 200 {
|
|
t.Errorf("unexpected probe: %+v", got[0])
|
|
}
|
|
}
|
|
|
|
func TestPassAndUnknownStateBuilders(t *testing.T) {
|
|
if s := passState("c", "m"); s.Status != sdk.StatusOK || s.Code != "c" || s.Message != "m" {
|
|
t.Errorf("passState wrong: %+v", s)
|
|
}
|
|
if s := unknownState("c", "m"); s.Status != sdk.StatusUnknown || s.Code != "c" || s.Message != "m" {
|
|
t.Errorf("unknownState wrong: %+v", s)
|
|
}
|
|
}
|
|
|
|
func TestSameSiteString(t *testing.T) {
|
|
cases := []struct {
|
|
in http.SameSite
|
|
want string
|
|
}{
|
|
{http.SameSiteLaxMode, "Lax"},
|
|
{http.SameSiteStrictMode, "Strict"},
|
|
{http.SameSiteNoneMode, "None"},
|
|
{http.SameSiteDefaultMode, ""},
|
|
{http.SameSite(99), ""},
|
|
}
|
|
for _, c := range cases {
|
|
if got := sameSiteString(c.in); got != c.want {
|
|
t.Errorf("sameSiteString(%v) = %q, want %q", c.in, got, c.want)
|
|
}
|
|
}
|
|
}
|