Browse Source

test case for routing rule

Darien Raymond 8 years ago
parent
commit
069837417f
3 changed files with 130 additions and 59 deletions
  1. 1 1
      app/router/condition.go
  2. 88 0
      app/router/condition_test.go
  3. 41 58
      app/router/config.go

+ 1 - 1
app/router/condition.go

@@ -140,7 +140,7 @@ type CIDRMatcher struct {
 func NewCIDRMatcher(ip []byte, mask uint32, onSource bool) (*CIDRMatcher, error) {
 	cidr := &net.IPNet{
 		IP:   net.IP(ip),
-		Mask: net.CIDRMask(int(mask), len(ip)),
+		Mask: net.CIDRMask(int(mask), len(ip)*8),
 	}
 	return &CIDRMatcher{
 		cidr:     cidr,

+ 88 - 0
app/router/condition_test.go

@@ -49,3 +49,91 @@ func TestSubDomainMatcher(t *testing.T) {
 		assert.Bool(matcher.Apply(test.input) == test.output).IsTrue()
 	}
 }
+
+func TestRoutingRule(t *testing.T) {
+	assert := assert.On(t)
+
+	type ruleTest struct {
+		input  context.Context
+		output bool
+	}
+
+	cases := []struct {
+		rule *RoutingRule
+		test []ruleTest
+	}{
+		{
+			rule: &RoutingRule{
+				Domain: []*Domain{
+					{
+						Value: "v2ray.com",
+						Type:  Domain_Plain,
+					},
+					{
+						Value: "google.com",
+						Type:  Domain_Domain,
+					},
+				},
+			},
+			test: []ruleTest{
+				ruleTest{
+					input:  proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.DomainAddress("v2ray.com"), 80)),
+					output: true,
+				},
+				ruleTest{
+					input:  proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.DomainAddress("www.v2ray.com.www"), 80)),
+					output: true,
+				},
+				ruleTest{
+					input:  proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.DomainAddress("v2ray.co"), 80)),
+					output: false,
+				},
+				ruleTest{
+					input:  proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.DomainAddress("www.google.com"), 80)),
+					output: true,
+				},
+			},
+		},
+		{
+			rule: &RoutingRule{
+				Cidr: []*CIDR{
+					{
+						Ip:     []byte{8, 8, 8, 8},
+						Prefix: 32,
+					},
+					{
+						Ip:     []byte{8, 8, 8, 8},
+						Prefix: 32,
+					},
+					{
+						Ip:     net.ParseAddress("2001:0db8:85a3:0000:0000:8a2e:0370:7334").IP(),
+						Prefix: 128,
+					},
+				},
+			},
+			test: []ruleTest{
+				ruleTest{
+					input:  proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.ParseAddress("8.8.8.8"), 80)),
+					output: true,
+				},
+				ruleTest{
+					input:  proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.ParseAddress("8.8.4.4"), 80)),
+					output: false,
+				},
+				ruleTest{
+					input:  proxy.ContextWithTarget(context.Background(), net.TCPDestination(net.ParseAddress("2001:0db8:85a3:0000:0000:8a2e:0370:7334"), 80)),
+					output: true,
+				},
+			},
+		},
+	}
+
+	for _, test := range cases {
+		cond, err := test.rule.BuildCondition()
+		assert.Error(err).IsNil()
+
+		for _, t := range test.test {
+			assert.Bool(cond.Apply(t.input)).Equals(t.output)
+		}
+	}
+}

+ 41 - 58
app/router/config.go

@@ -16,6 +16,39 @@ func (r *Rule) Apply(ctx context.Context) bool {
 	return r.Condition.Apply(ctx)
 }
 
+func cidrToCondition(cidr []*CIDR, source bool) (Condition, error) {
+	ipv4Net := v2net.NewIPNet()
+	ipv6Cond := NewAnyCondition()
+	hasIpv6 := false
+
+	for _, ip := range cidr {
+		switch len(ip.Ip) {
+		case net.IPv4len:
+			ipv4Net.AddIP(ip.Ip, byte(ip.Prefix))
+		case net.IPv6len:
+			hasIpv6 = true
+			matcher, err := NewCIDRMatcher(ip.Ip, ip.Prefix, source)
+			if err != nil {
+				return nil, err
+			}
+			ipv6Cond.Add(matcher)
+		default:
+			return nil, newError("invalid IP length").AtError()
+		}
+	}
+
+	if !ipv4Net.IsEmpty() && hasIpv6 {
+		cond := NewAnyCondition()
+		cond.Add(NewIPv4Matcher(ipv4Net, source))
+		cond.Add(ipv6Cond)
+		return cond, nil
+	} else if !ipv4Net.IsEmpty() {
+		return NewIPv4Matcher(ipv4Net, source), nil
+	} else {
+		return ipv6Cond, nil
+	}
+}
+
 func (rr *RoutingRule) BuildCondition() (Condition, error) {
 	conds := NewConditionChan()
 
@@ -41,36 +74,11 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
 	}
 
 	if len(rr.Cidr) > 0 {
-		ipv4Net := v2net.NewIPNet()
-		ipv6Cond := NewAnyCondition()
-		hasIpv6 := false
-
-		for _, ip := range rr.Cidr {
-			switch len(ip.Ip) {
-			case net.IPv4len:
-				ipv4Net.AddIP(ip.Ip, byte(ip.Prefix))
-			case net.IPv6len:
-				hasIpv6 = true
-				matcher, err := NewCIDRMatcher(ip.Ip, ip.Prefix, false)
-				if err != nil {
-					return nil, err
-				}
-				ipv6Cond.Add(matcher)
-			default:
-				return nil, newError("invalid IP length").AtError()
-			}
-		}
-
-		if !ipv4Net.IsEmpty() && hasIpv6 {
-			cond := NewAnyCondition()
-			cond.Add(NewIPv4Matcher(ipv4Net, false))
-			cond.Add(ipv6Cond)
-			conds.Add(cond)
-		} else if !ipv4Net.IsEmpty() {
-			conds.Add(NewIPv4Matcher(ipv4Net, false))
-		} else if hasIpv6 {
-			conds.Add(ipv6Cond)
+		cond, err := cidrToCondition(rr.Cidr, false)
+		if err != nil {
+			return nil, err
 		}
+		conds.Add(cond)
 	}
 
 	if rr.PortRange != nil {
@@ -82,36 +90,11 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
 	}
 
 	if len(rr.SourceCidr) > 0 {
-		ipv4Net := v2net.NewIPNet()
-		ipv6Cond := NewAnyCondition()
-		hasIpv6 := false
-
-		for _, ip := range rr.SourceCidr {
-			switch len(ip.Ip) {
-			case net.IPv4len:
-				ipv4Net.AddIP(ip.Ip, byte(ip.Prefix))
-			case net.IPv6len:
-				hasIpv6 = true
-				matcher, err := NewCIDRMatcher(ip.Ip, ip.Prefix, true)
-				if err != nil {
-					return nil, err
-				}
-				ipv6Cond.Add(matcher)
-			default:
-				return nil, newError("invalid IP length").AtError()
-			}
-		}
-
-		if !ipv4Net.IsEmpty() && hasIpv6 {
-			cond := NewAnyCondition()
-			cond.Add(NewIPv4Matcher(ipv4Net, true))
-			cond.Add(ipv6Cond)
-			conds.Add(cond)
-		} else if !ipv4Net.IsEmpty() {
-			conds.Add(NewIPv4Matcher(ipv4Net, true))
-		} else if hasIpv6 {
-			conds.Add(ipv6Cond)
+		cond, err := cidrToCondition(rr.SourceCidr, true)
+		if err != nil {
+			return nil, err
 		}
+		conds.Add(cond)
 	}
 
 	if len(rr.UserEmail) > 0 {