85 lines
2.8 KiB
Go
85 lines
2.8 KiB
Go
package model
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestValidateCustomRouteRules(t *testing.T) {
|
|
available := map[string]struct{}{"direct": {}, "block": {}, "warp": {}, "proxy": {}}
|
|
tests := []struct {
|
|
name string
|
|
rules []CustomRouteRule
|
|
kernel string
|
|
wantErr string
|
|
}{
|
|
{
|
|
name: "valid route target",
|
|
rules: []CustomRouteRule{{
|
|
Match: RouteMatch{DomainSuffixes: []string{"example.com"}, Ports: []string{"443"}, Networks: []string{"tcp"}},
|
|
Action: RouteAction{Type: "route", Target: "warp"},
|
|
}},
|
|
kernel: "singbox",
|
|
},
|
|
{
|
|
name: "missing match",
|
|
rules: []CustomRouteRule{{Action: RouteAction{Type: "direct"}}},
|
|
kernel: "singbox",
|
|
wantErr: "custom_route_rules[0].match is required",
|
|
},
|
|
{
|
|
name: "unknown target",
|
|
rules: []CustomRouteRule{{Match: RouteMatch{DomainSuffixes: []string{"example.com"}}, Action: RouteAction{Type: "route", Target: "missing"}}},
|
|
kernel: "singbox",
|
|
wantErr: `custom_route_rules[0].action.target references unknown outbound "missing"`,
|
|
},
|
|
{
|
|
name: "route target required",
|
|
rules: []CustomRouteRule{{Match: RouteMatch{DomainSuffixes: []string{"example.com"}}, Action: RouteAction{Type: "route"}}},
|
|
kernel: "singbox",
|
|
wantErr: "custom_route_rules[0].action.target is required when action.type is route",
|
|
},
|
|
{
|
|
name: "direct target forbidden",
|
|
rules: []CustomRouteRule{{Match: RouteMatch{DomainSuffixes: []string{"example.com"}}, Action: RouteAction{Type: "direct", Target: "warp"}}},
|
|
kernel: "singbox",
|
|
wantErr: "custom_route_rules[0].action.target is only allowed when action.type is route",
|
|
},
|
|
{
|
|
name: "unsupported action",
|
|
rules: []CustomRouteRule{{Match: RouteMatch{DomainSuffixes: []string{"example.com"}}, Action: RouteAction{Type: "dns"}}},
|
|
kernel: "singbox",
|
|
wantErr: `custom_route_rules[0].action.type "dns" is not supported by kernel "singbox"`,
|
|
},
|
|
{
|
|
name: "invalid port range",
|
|
rules: []CustomRouteRule{{Match: RouteMatch{Ports: []string{"2000-1000"}}, Action: RouteAction{Type: "direct"}}},
|
|
kernel: "singbox",
|
|
wantErr: `custom_route_rules[0].match.ports contains invalid port range "2000-1000"`,
|
|
},
|
|
{
|
|
name: "invalid network",
|
|
rules: []CustomRouteRule{{Match: RouteMatch{Networks: []string{"icmp"}}, Action: RouteAction{Type: "direct"}}},
|
|
kernel: "singbox",
|
|
wantErr: `custom_route_rules[0].match.networks contains unsupported network "icmp"`,
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
err := ValidateCustomRouteRules(tc.rules, tc.kernel, available)
|
|
if tc.wantErr == "" && err != nil {
|
|
t.Fatalf("expected no error, got %v", err)
|
|
}
|
|
if tc.wantErr != "" {
|
|
if err == nil {
|
|
t.Fatal("expected error, got nil")
|
|
}
|
|
if !strings.Contains(err.Error(), tc.wantErr) {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|