package config import ( "fmt" "strings" "testing" "time" ) func TestEffectiveCheckOverlaysScalarsAndClonesURLs(t *testing.T) { defaults := Check{ Interval: Duration(time.Minute), Jitter: 20, MaxInFlight: 12, Timeout: Duration(5 * time.Second), MaxAttempts: 3, MaxConsecutiveFailures: 2, UnhealthyRemoveAfter: Duration(3 * time.Minute), URLs: []string{"https://egress.example/check"}, } override := Check{Timeout: Duration(8 * time.Second), MaxAttempts: 5} effective := EffectiveCheck(defaults, override) if effective.Interval != defaults.Interval || effective.Jitter != defaults.Jitter || effective.MaxInFlight != defaults.MaxInFlight || effective.Timeout != override.Timeout || effective.MaxAttempts != override.MaxAttempts || effective.MaxConsecutiveFailures != defaults.MaxConsecutiveFailures || effective.UnhealthyRemoveAfter != defaults.UnhealthyRemoveAfter || len(effective.URLs) != 1 || effective.URLs[0] != defaults.URLs[0] { t.Fatalf("EffectiveCheck() = %+v", effective) } effective.URLs[0] = "https://changed.example/check" if defaults.URLs[0] == effective.URLs[0] { t.Fatal("EffectiveCheck() aliases default URLs") } effective = EffectiveCheck(defaults, Check{URLs: []string{}}) if effective.URLs == nil || len(effective.URLs) != 0 { t.Fatalf("EffectiveCheck(explicit empty URLs) = %+v", effective) } effective = EffectiveCheck(defaults, Check{UnhealthyRemoveAfter: Duration(5 * time.Minute)}) if effective.UnhealthyRemoveAfter != Duration(5*time.Minute) { t.Fatalf("EffectiveCheck(remove after override) = %+v", effective) } } func TestValidateUsesEffectiveCheckAndRejectsUnsafeURLs(t *testing.T) { cfg := mustLoadValidConfig(t) defaults := cfg.Upstreams["provider-a"].Check cfg.Defaults.Check = defaults upstream := cfg.Upstreams["provider-a"] upstream.Check = Check{Timeout: Duration(7 * time.Second)} cfg.Upstreams["provider-a"] = upstream if err := Validate(cfg); err != nil { t.Fatalf("Validate(effective check) = %v", err) } for _, invalid := range []string{ "target.example/check", "ftp://target.example/check", "https://user:pass@target.example/check", "https://target.example/check#fragment", " https://target.example/check", "https://target.example/check", } { cfg := mustLoadValidConfig(t) upstream := cfg.Upstreams["provider-a"] if strings.HasPrefix(invalid, "https://target.example/check") && invalid == "https://target.example/check" { upstream.Check.URLs = []string{invalid, invalid} } else { upstream.Check.URLs = []string{invalid} } cfg.Upstreams["provider-a"] = upstream if err := Validate(cfg); err == nil || !strings.Contains(err.Error(), "check.urls") { t.Fatalf("Validate(check URL %q) error = %v, want check.urls", invalid, err) } } } func TestValidateRejectsUnboundedCheckURLReferences(t *testing.T) { cfg := mustLoadValidConfig(t) upstream := cfg.Upstreams["provider-a"] upstream.Check.URLs = make([]string, MaximumCheckURLs+1) for index := range upstream.Check.URLs { upstream.Check.URLs[index] = fmt.Sprintf("https://egress-%d.example/check", index) } cfg.Upstreams["provider-a"] = upstream if err := Validate(cfg); err == nil || !strings.Contains(err.Error(), "at most") { t.Fatalf("Validate(unbounded check URLs) error = %v, want maximum URL error", err) } }