2023-08-16 11:06:30 +08:00
|
|
|
package rules
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
C "github.com/Dreamacro/clash/constant"
|
|
|
|
|
|
|
|
"github.com/samber/lo"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestParseRule(t *testing.T) {
|
|
|
|
type testCase struct {
|
|
|
|
tp C.RuleConfig
|
|
|
|
payload string
|
|
|
|
target string
|
|
|
|
params []string
|
|
|
|
expectedRule C.Rule
|
|
|
|
expectedError error
|
|
|
|
}
|
|
|
|
|
|
|
|
policy := "DIRECT"
|
|
|
|
|
|
|
|
testCases := []testCase{
|
|
|
|
{
|
|
|
|
tp: C.RuleConfigDomain,
|
|
|
|
payload: "example.com",
|
|
|
|
target: policy,
|
|
|
|
expectedRule: NewDomain("example.com", policy),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
tp: C.RuleConfigDomainSuffix,
|
|
|
|
payload: "example.com",
|
|
|
|
target: policy,
|
|
|
|
expectedRule: NewDomainSuffix("example.com", policy),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
tp: C.RuleConfigDomainKeyword,
|
|
|
|
payload: "example.com",
|
|
|
|
target: policy,
|
|
|
|
expectedRule: NewDomainKeyword("example.com", policy),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
tp: C.RuleConfigGeoIP,
|
|
|
|
payload: "CN",
|
|
|
|
target: policy, params: []string{noResolve},
|
|
|
|
expectedRule: NewGEOIP("CN", policy, true),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
tp: C.RuleConfigIPCIDR,
|
|
|
|
payload: "127.0.0.0/8",
|
|
|
|
target: policy,
|
|
|
|
expectedRule: lo.Must(NewIPCIDR("127.0.0.0/8", policy, WithIPCIDRNoResolve(false))),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
tp: C.RuleConfigIPCIDR,
|
|
|
|
payload: "127.0.0.0/8",
|
|
|
|
target: policy, params: []string{noResolve},
|
|
|
|
expectedRule: lo.Must(NewIPCIDR("127.0.0.0/8", policy, WithIPCIDRNoResolve(true))),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
tp: C.RuleConfigIPCIDR6,
|
|
|
|
payload: "2001:db8::/32",
|
|
|
|
target: policy,
|
|
|
|
expectedRule: lo.Must(NewIPCIDR("2001:db8::/32", policy, WithIPCIDRNoResolve(false))),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
tp: C.RuleConfigIPCIDR6,
|
|
|
|
payload: "2001:db8::/32",
|
|
|
|
target: policy, params: []string{noResolve},
|
|
|
|
expectedRule: lo.Must(NewIPCIDR("2001:db8::/32", policy, WithIPCIDRNoResolve(true))),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
tp: C.RuleConfigSrcIPCIDR,
|
|
|
|
payload: "192.168.1.201/32",
|
|
|
|
target: policy,
|
|
|
|
expectedRule: lo.Must(NewIPCIDR("192.168.1.201/32", policy, WithIPCIDRSourceIP(true), WithIPCIDRNoResolve(true))),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
tp: C.RuleConfigSrcPort,
|
|
|
|
payload: "80",
|
|
|
|
target: policy,
|
|
|
|
expectedRule: lo.Must(NewPort("80", policy, PortTypeSrc)),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
tp: C.RuleConfigDstPort,
|
|
|
|
payload: "80",
|
|
|
|
target: policy,
|
|
|
|
expectedRule: lo.Must(NewPort("80", policy, PortTypeDest)),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
tp: C.RuleConfigInboundPort,
|
|
|
|
payload: "80",
|
|
|
|
target: policy,
|
|
|
|
expectedRule: lo.Must(NewPort("80", policy, PortTypeInbound)),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
tp: C.RuleConfigProcessName,
|
|
|
|
payload: "example.exe",
|
|
|
|
target: policy,
|
|
|
|
expectedRule: lo.Must(NewProcess("example.exe", policy, true)),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
tp: C.RuleConfigProcessPath,
|
|
|
|
payload: "C:\\Program Files\\example.exe",
|
|
|
|
target: policy,
|
|
|
|
expectedRule: lo.Must(NewProcess("C:\\Program Files\\example.exe", policy, false)),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
tp: C.RuleConfigProcessPath,
|
|
|
|
payload: "/opt/example/example",
|
|
|
|
target: policy,
|
|
|
|
expectedRule: lo.Must(NewProcess("/opt/example/example", policy, false)),
|
|
|
|
},
|
|
|
|
{
|
2023-08-16 22:29:36 +08:00
|
|
|
tp: C.RuleConfigIPSet,
|
|
|
|
payload: "example",
|
|
|
|
target: policy,
|
|
|
|
// unit test runs on Linux machine and NewIPSet(...) won't be available
|
|
|
|
expectedError: errors.New("operation not permitted"),
|
2023-08-16 11:06:30 +08:00
|
|
|
},
|
|
|
|
{
|
|
|
|
tp: C.RuleConfigIPSet,
|
|
|
|
payload: "example",
|
|
|
|
target: policy, params: []string{noResolve},
|
2023-08-16 22:29:36 +08:00
|
|
|
// unit test runs on Linux machine and NewIPSet(...) won't be available
|
|
|
|
expectedError: errors.New("operation not permitted"),
|
2023-08-16 11:06:30 +08:00
|
|
|
},
|
|
|
|
{
|
|
|
|
tp: C.RuleConfigMatch,
|
|
|
|
payload: "example",
|
|
|
|
target: policy,
|
|
|
|
expectedRule: NewMatch(policy),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
tp: C.RuleConfigRuleSet,
|
|
|
|
payload: "example",
|
|
|
|
target: policy,
|
|
|
|
expectedError: fmt.Errorf("unsupported rule type %s", C.RuleConfigRuleSet),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
tp: C.RuleConfigScript,
|
|
|
|
payload: "example",
|
|
|
|
target: policy,
|
|
|
|
expectedError: fmt.Errorf("unsupported rule type %s", C.RuleConfigScript),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
tp: "UNKNOWN",
|
|
|
|
payload: "example",
|
|
|
|
target: policy,
|
|
|
|
expectedError: errors.New("unsupported rule type UNKNOWN"),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
tp: "ABCD",
|
|
|
|
payload: "example",
|
|
|
|
target: policy,
|
|
|
|
expectedError: errors.New("unsupported rule type ABCD"),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tc := range testCases {
|
|
|
|
_, err := ParseRule(string(tc.tp), tc.payload, tc.target, tc.params)
|
|
|
|
if tc.expectedError != nil {
|
|
|
|
require.Error(t, err)
|
|
|
|
assert.EqualError(t, err, tc.expectedError.Error())
|
|
|
|
} else {
|
|
|
|
require.NoError(t, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|