95 lines
3.0 KiB
Go
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")
|
|
}
|
|
}
|