Files
notify-gateway/internal/config/outbound_test.go
T
2026-09-16 06:26:16 +02:00

95 lines
3.0 KiB
Go

package config
import (
"encoding/json"
"os"
"testing"
)
func TestValidateOutbounds(t *testing.T) {
valid := OutboundConfig{ID: "ops", Provider: "discord", URL: "https://discord.com/api/webhooks/123/secret"}
for _, tc := range []struct {
name string
change func(*Config)
}{
{"duplicate", func(c *Config) { c.Outbounds = append(c.Outbounds, valid) }},
{"missing destination", func(c *Config) { c.Mappings[0].OutboundID = "missing" }},
{"mismatched provider", func(c *Config) { c.Mappings[0].Target = "webhook" }},
{"unsafe scheme", func(c *Config) { c.Outbounds[0].URL = "file:///secret" }},
{"discord host", func(c *Config) { c.Outbounds[0].URL = "https://evil.example/api/webhooks/123/secret" }},
{"discord credentials", func(c *Config) { c.Outbounds[0].BearerToken = "secret" }},
{"timeout", func(c *Config) { c.Outbounds[0].TimeoutS = -1 }},
{"template", func(c *Config) { c.Mappings[0].TextTemplate = "{{invalid" }},
{"divera reference", func(c *Config) { c.Mappings[0].Target = "alarm" }},
} {
t.Run(tc.name, func(t *testing.T) {
c := Default()
c.Outbounds = []OutboundConfig{valid}
c.Mappings[0].Target = "discord"
c.Mappings[0].OutboundID = "ops"
if err := Validate(c); err != nil {
t.Fatal(err)
}
tc.change(&c)
if Validate(c) == nil {
t.Fatal("expected validation error")
}
})
}
}
func TestExistingConfigurationCompatibility(t *testing.T) {
c := Default()
if err := Validate(c); err != nil {
t.Fatal(err)
}
var o OutboundConfig
if err := json.Unmarshal([]byte(`{"id":"test","provider":"webhook","url":"https://example.invalid"}`), &o); err != nil {
t.Fatal(err)
}
if o.Live {
t.Fatal("omitted live flag must be dry-run")
}
}
func TestExampleConfig(t *testing.T) {
b, err := os.ReadFile("../../config.example.json")
if err != nil {
t.Fatal(err)
}
var c Config
if err := json.Unmarshal(b, &c); err != nil {
t.Fatal(err)
}
if err := Validate(c); err != nil {
t.Fatal(err)
}
for _, o := range c.Outbounds {
if o.Live {
t.Fatal("example must use dry-run")
}
}
}
func TestMailAndPushConfigurationValidation(t *testing.T) {
for _, o := range []OutboundConfig{
{ID: "smtp", Provider: "smtp", SMTPHost: "smtp.example.org", SMTPPort: 587, TLSMode: "plain", From: "sender@example.org", To: []string{"to@example.org"}},
{ID: "smtp", Provider: "smtp", SMTPHost: "smtp.example.org", SMTPPort: 587, TLSMode: "starttls", From: "sender@example.org\r\nBcc: bad@example.org", To: []string{"to@example.org"}},
{ID: "ntfy", Provider: "ntfy", URL: "https://ntfy.sh", Topic: "bad/topic"},
} {
if ValidateOutbound(o) == nil {
t.Fatalf("invalid destination accepted: %s", o.ID)
}
}
c := Default()
c.Ingress.Mail = []MailIngress{{ID: "mail", Enabled: true, Address: "host:993", Username: "user", Password: "env:PASS", Channel: "ops", PollSeconds: 1}}
if Validate(c) == nil {
t.Fatal("invalid polling interval")
}
c.Ingress.Mail = nil
c.Ingress.Discord = DiscordIngress{Enabled: true}
if Validate(c) == nil {
t.Fatal("incomplete Discord credentials")
}
}