Files
sing-box/option/rule_nested_test.go
2026-04-01 16:23:38 +08:00

272 lines
6.4 KiB
Go

package option
import (
"context"
"testing"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing/common/json"
"github.com/stretchr/testify/require"
)
func TestRuleRejectsNestedDefaultRuleAction(t *testing.T) {
t.Parallel()
var rule Rule
err := json.UnmarshalContext(context.Background(), []byte(`{
"type": "logical",
"mode": "and",
"rules": [
{"domain": "example.com", "outbound": "direct"}
]
}`), &rule)
require.ErrorContains(t, err, routeRuleActionNestedUnsupportedMessage)
}
func TestRuleRejectsNestedLogicalRuleAction(t *testing.T) {
t.Parallel()
var rule Rule
err := json.UnmarshalContext(context.Background(), []byte(`{
"type": "logical",
"mode": "and",
"rules": [
{
"type": "logical",
"mode": "or",
"action": "route",
"outbound": "direct",
"rules": [{"domain": "example.com"}]
}
]
}`), &rule)
require.ErrorContains(t, err, routeRuleActionNestedUnsupportedMessage)
}
func TestRuleRejectsNestedDefaultRuleZeroValueOutbound(t *testing.T) {
t.Parallel()
var rule Rule
err := json.UnmarshalContext(context.Background(), []byte(`{
"type": "logical",
"mode": "and",
"rules": [
{"domain": "example.com", "outbound": ""}
]
}`), &rule)
require.ErrorContains(t, err, routeRuleActionNestedUnsupportedMessage)
}
func TestRuleRejectsNestedDefaultRuleZeroValueRouteOption(t *testing.T) {
t.Parallel()
var rule Rule
err := json.UnmarshalContext(context.Background(), []byte(`{
"type": "logical",
"mode": "and",
"rules": [
{"domain": "example.com", "udp_connect": false}
]
}`), &rule)
require.ErrorContains(t, err, routeRuleActionNestedUnsupportedMessage)
}
func TestRuleRejectsNestedLogicalRuleZeroValueAction(t *testing.T) {
t.Parallel()
var rule Rule
err := json.UnmarshalContext(context.Background(), []byte(`{
"type": "logical",
"mode": "and",
"rules": [
{
"type": "logical",
"mode": "or",
"action": "",
"rules": [{"domain": "example.com"}]
}
]
}`), &rule)
require.ErrorContains(t, err, routeRuleActionNestedUnsupportedMessage)
}
func TestRuleRejectsNestedLogicalRuleZeroValueRouteOption(t *testing.T) {
t.Parallel()
var rule Rule
err := json.UnmarshalContext(context.Background(), []byte(`{
"type": "logical",
"mode": "and",
"rules": [
{
"type": "logical",
"mode": "or",
"override_port": 0,
"rules": [{"domain": "example.com"}]
}
]
}`), &rule)
require.ErrorContains(t, err, routeRuleActionNestedUnsupportedMessage)
}
func TestRuleAllowsTopLevelLogicalAction(t *testing.T) {
t.Parallel()
var rule Rule
err := json.UnmarshalContext(context.Background(), []byte(`{
"type": "logical",
"mode": "and",
"outbound": "direct",
"rules": [{"domain": "example.com"}]
}`), &rule)
require.NoError(t, err)
require.Equal(t, C.RuleActionTypeRoute, rule.LogicalOptions.Action)
require.Equal(t, "direct", rule.LogicalOptions.RouteOptions.Outbound)
}
func TestRuleLeavesUnknownNestedKeysToNormalValidation(t *testing.T) {
t.Parallel()
var rule Rule
err := json.UnmarshalContext(context.Background(), []byte(`{
"type": "logical",
"mode": "and",
"rules": [
{"domain": "example.com", "foo": "bar"}
]
}`), &rule)
require.ErrorContains(t, err, "unknown field")
require.NotContains(t, err.Error(), routeRuleActionNestedUnsupportedMessage)
}
func TestDNSRuleRejectsNestedDefaultRuleAction(t *testing.T) {
t.Parallel()
var rule DNSRule
err := json.UnmarshalContext(context.Background(), []byte(`{
"type": "logical",
"mode": "and",
"rules": [
{"domain": "example.com", "server": "default"}
]
}`), &rule)
require.ErrorContains(t, err, dnsRuleActionNestedUnsupportedMessage)
}
func TestDNSRuleRejectsNestedLogicalRuleAction(t *testing.T) {
t.Parallel()
var rule DNSRule
err := json.UnmarshalContext(context.Background(), []byte(`{
"type": "logical",
"mode": "and",
"rules": [
{
"type": "logical",
"mode": "or",
"action": "route",
"server": "default",
"rules": [{"domain": "example.com"}]
}
]
}`), &rule)
require.ErrorContains(t, err, dnsRuleActionNestedUnsupportedMessage)
}
func TestDNSRuleRejectsNestedDefaultRuleZeroValueServer(t *testing.T) {
t.Parallel()
var rule DNSRule
err := json.UnmarshalContext(context.Background(), []byte(`{
"type": "logical",
"mode": "and",
"rules": [
{"domain": "example.com", "server": ""}
]
}`), &rule)
require.ErrorContains(t, err, dnsRuleActionNestedUnsupportedMessage)
}
func TestDNSRuleRejectsNestedDefaultRuleZeroValueRouteOption(t *testing.T) {
t.Parallel()
var rule DNSRule
err := json.UnmarshalContext(context.Background(), []byte(`{
"type": "logical",
"mode": "and",
"rules": [
{"domain": "example.com", "disable_cache": false}
]
}`), &rule)
require.ErrorContains(t, err, dnsRuleActionNestedUnsupportedMessage)
}
func TestDNSRuleRejectsNestedLogicalRuleZeroValueAction(t *testing.T) {
t.Parallel()
var rule DNSRule
err := json.UnmarshalContext(context.Background(), []byte(`{
"type": "logical",
"mode": "and",
"rules": [
{
"type": "logical",
"mode": "or",
"action": "",
"rules": [{"domain": "example.com"}]
}
]
}`), &rule)
require.ErrorContains(t, err, dnsRuleActionNestedUnsupportedMessage)
}
func TestDNSRuleRejectsNestedLogicalRuleZeroValueRouteOption(t *testing.T) {
t.Parallel()
var rule DNSRule
err := json.UnmarshalContext(context.Background(), []byte(`{
"type": "logical",
"mode": "and",
"rules": [
{
"type": "logical",
"mode": "or",
"disable_cache": false,
"rules": [{"domain": "example.com"}]
}
]
}`), &rule)
require.ErrorContains(t, err, dnsRuleActionNestedUnsupportedMessage)
}
func TestDNSRuleAllowsTopLevelLogicalAction(t *testing.T) {
t.Parallel()
var rule DNSRule
err := json.UnmarshalContext(context.Background(), []byte(`{
"type": "logical",
"mode": "and",
"server": "default",
"rules": [{"domain": "example.com"}]
}`), &rule)
require.NoError(t, err)
require.Equal(t, C.RuleActionTypeRoute, rule.LogicalOptions.Action)
require.Equal(t, "default", rule.LogicalOptions.RouteOptions.Server)
}
func TestDNSRuleLeavesUnknownNestedKeysToNormalValidation(t *testing.T) {
t.Parallel()
var rule DNSRule
err := json.UnmarshalContext(context.Background(), []byte(`{
"type": "logical",
"mode": "and",
"rules": [
{"domain": "example.com", "foo": "bar"}
]
}`), &rule)
require.ErrorContains(t, err, "unknown field")
require.NotContains(t, err.Error(), dnsRuleActionNestedUnsupportedMessage)
}