mirror of
https://github.com/XTLS/Xray-core.git
synced 2024-12-27 07:59:47 +00:00
017f53b5fc
* Add session context outbounds as slice slice is needed for dialer proxy where two outbounds work on top of each other There are two sets of target addr for example It also enable Xtls to correctly do splice copy by checking both outbounds are ready to do direct copy * Fill outbound tag info * Splice now checks capalibility from all outbounds * Fix unit tests
267 lines
6.6 KiB
Go
267 lines
6.6 KiB
Go
package router_test
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/golang/mock/gomock"
|
|
. "github.com/xtls/xray-core/app/router"
|
|
"github.com/xtls/xray-core/common"
|
|
"github.com/xtls/xray-core/common/net"
|
|
"github.com/xtls/xray-core/common/session"
|
|
"github.com/xtls/xray-core/features/dns"
|
|
"github.com/xtls/xray-core/features/outbound"
|
|
routing_session "github.com/xtls/xray-core/features/routing/session"
|
|
"github.com/xtls/xray-core/testing/mocks"
|
|
)
|
|
|
|
type mockOutboundManager struct {
|
|
outbound.Manager
|
|
outbound.HandlerSelector
|
|
}
|
|
|
|
func TestSimpleRouter(t *testing.T) {
|
|
config := &Config{
|
|
Rule: []*RoutingRule{
|
|
{
|
|
TargetTag: &RoutingRule_Tag{
|
|
Tag: "test",
|
|
},
|
|
Networks: []net.Network{net.Network_TCP},
|
|
},
|
|
},
|
|
}
|
|
|
|
mockCtl := gomock.NewController(t)
|
|
defer mockCtl.Finish()
|
|
|
|
mockDNS := mocks.NewDNSClient(mockCtl)
|
|
mockOhm := mocks.NewOutboundManager(mockCtl)
|
|
mockHs := mocks.NewOutboundHandlerSelector(mockCtl)
|
|
|
|
r := new(Router)
|
|
common.Must(r.Init(context.TODO(), config, mockDNS, &mockOutboundManager{
|
|
Manager: mockOhm,
|
|
HandlerSelector: mockHs,
|
|
}, nil))
|
|
|
|
ctx := session.ContextWithOutbounds(context.Background(), []*session.Outbound{{
|
|
Target: net.TCPDestination(net.DomainAddress("example.com"), 80),
|
|
}})
|
|
route, err := r.PickRoute(routing_session.AsRoutingContext(ctx))
|
|
common.Must(err)
|
|
if tag := route.GetOutboundTag(); tag != "test" {
|
|
t.Error("expect tag 'test', bug actually ", tag)
|
|
}
|
|
}
|
|
|
|
func TestSimpleBalancer(t *testing.T) {
|
|
config := &Config{
|
|
Rule: []*RoutingRule{
|
|
{
|
|
TargetTag: &RoutingRule_BalancingTag{
|
|
BalancingTag: "balance",
|
|
},
|
|
Networks: []net.Network{net.Network_TCP},
|
|
},
|
|
},
|
|
BalancingRule: []*BalancingRule{
|
|
{
|
|
Tag: "balance",
|
|
OutboundSelector: []string{"test-"},
|
|
},
|
|
},
|
|
}
|
|
|
|
mockCtl := gomock.NewController(t)
|
|
defer mockCtl.Finish()
|
|
|
|
mockDNS := mocks.NewDNSClient(mockCtl)
|
|
mockOhm := mocks.NewOutboundManager(mockCtl)
|
|
mockHs := mocks.NewOutboundHandlerSelector(mockCtl)
|
|
|
|
mockHs.EXPECT().Select(gomock.Eq([]string{"test-"})).Return([]string{"test"})
|
|
|
|
r := new(Router)
|
|
common.Must(r.Init(context.TODO(), config, mockDNS, &mockOutboundManager{
|
|
Manager: mockOhm,
|
|
HandlerSelector: mockHs,
|
|
}, nil))
|
|
|
|
ctx := session.ContextWithOutbounds(context.Background(), []*session.Outbound{{
|
|
Target: net.TCPDestination(net.DomainAddress("example.com"), 80),
|
|
}})
|
|
route, err := r.PickRoute(routing_session.AsRoutingContext(ctx))
|
|
common.Must(err)
|
|
if tag := route.GetOutboundTag(); tag != "test" {
|
|
t.Error("expect tag 'test', bug actually ", tag)
|
|
}
|
|
}
|
|
|
|
/*
|
|
|
|
Do not work right now: need a full client setup
|
|
|
|
func TestLeastLoadBalancer(t *testing.T) {
|
|
config := &Config{
|
|
Rule: []*RoutingRule{
|
|
{
|
|
TargetTag: &RoutingRule_BalancingTag{
|
|
BalancingTag: "balance",
|
|
},
|
|
Networks: []net.Network{net.Network_TCP},
|
|
},
|
|
},
|
|
BalancingRule: []*BalancingRule{
|
|
{
|
|
Tag: "balance",
|
|
OutboundSelector: []string{"test-"},
|
|
Strategy: "leastLoad",
|
|
StrategySettings: serial.ToTypedMessage(&StrategyLeastLoadConfig{
|
|
Baselines: nil,
|
|
Expected: 1,
|
|
}),
|
|
},
|
|
},
|
|
}
|
|
|
|
mockCtl := gomock.NewController(t)
|
|
defer mockCtl.Finish()
|
|
|
|
mockDNS := mocks.NewDNSClient(mockCtl)
|
|
mockOhm := mocks.NewOutboundManager(mockCtl)
|
|
mockHs := mocks.NewOutboundHandlerSelector(mockCtl)
|
|
|
|
mockHs.EXPECT().Select(gomock.Eq([]string{"test-"})).Return([]string{"test1"})
|
|
|
|
r := new(Router)
|
|
common.Must(r.Init(context.TODO(), config, mockDNS, &mockOutboundManager{
|
|
Manager: mockOhm,
|
|
HandlerSelector: mockHs,
|
|
}, nil))
|
|
ctx := session.ContextWithOutbound(context.Background(), &session.Outbound{Target: net.TCPDestination(net.DomainAddress("v2ray.com"), 80)})
|
|
route, err := r.PickRoute(routing_session.AsRoutingContext(ctx))
|
|
common.Must(err)
|
|
if tag := route.GetOutboundTag(); tag != "test1" {
|
|
t.Error("expect tag 'test1', bug actually ", tag)
|
|
}
|
|
}*/
|
|
|
|
func TestIPOnDemand(t *testing.T) {
|
|
config := &Config{
|
|
DomainStrategy: Config_IpOnDemand,
|
|
Rule: []*RoutingRule{
|
|
{
|
|
TargetTag: &RoutingRule_Tag{
|
|
Tag: "test",
|
|
},
|
|
Cidr: []*CIDR{
|
|
{
|
|
Ip: []byte{192, 168, 0, 0},
|
|
Prefix: 16,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
mockCtl := gomock.NewController(t)
|
|
defer mockCtl.Finish()
|
|
|
|
mockDNS := mocks.NewDNSClient(mockCtl)
|
|
mockDNS.EXPECT().LookupIP(gomock.Eq("example.com"), dns.IPOption{
|
|
IPv4Enable: true,
|
|
IPv6Enable: true,
|
|
FakeEnable: false,
|
|
}).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes()
|
|
|
|
r := new(Router)
|
|
common.Must(r.Init(context.TODO(), config, mockDNS, nil, nil))
|
|
|
|
ctx := session.ContextWithOutbounds(context.Background(), []*session.Outbound{{
|
|
Target: net.TCPDestination(net.DomainAddress("example.com"), 80),
|
|
}})
|
|
route, err := r.PickRoute(routing_session.AsRoutingContext(ctx))
|
|
common.Must(err)
|
|
if tag := route.GetOutboundTag(); tag != "test" {
|
|
t.Error("expect tag 'test', bug actually ", tag)
|
|
}
|
|
}
|
|
|
|
func TestIPIfNonMatchDomain(t *testing.T) {
|
|
config := &Config{
|
|
DomainStrategy: Config_IpIfNonMatch,
|
|
Rule: []*RoutingRule{
|
|
{
|
|
TargetTag: &RoutingRule_Tag{
|
|
Tag: "test",
|
|
},
|
|
Cidr: []*CIDR{
|
|
{
|
|
Ip: []byte{192, 168, 0, 0},
|
|
Prefix: 16,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
mockCtl := gomock.NewController(t)
|
|
defer mockCtl.Finish()
|
|
|
|
mockDNS := mocks.NewDNSClient(mockCtl)
|
|
mockDNS.EXPECT().LookupIP(gomock.Eq("example.com"), dns.IPOption{
|
|
IPv4Enable: true,
|
|
IPv6Enable: true,
|
|
FakeEnable: false,
|
|
}).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes()
|
|
|
|
r := new(Router)
|
|
common.Must(r.Init(context.TODO(), config, mockDNS, nil, nil))
|
|
|
|
ctx := session.ContextWithOutbounds(context.Background(), []*session.Outbound{{
|
|
Target: net.TCPDestination(net.DomainAddress("example.com"), 80),
|
|
}})
|
|
route, err := r.PickRoute(routing_session.AsRoutingContext(ctx))
|
|
common.Must(err)
|
|
if tag := route.GetOutboundTag(); tag != "test" {
|
|
t.Error("expect tag 'test', bug actually ", tag)
|
|
}
|
|
}
|
|
|
|
func TestIPIfNonMatchIP(t *testing.T) {
|
|
config := &Config{
|
|
DomainStrategy: Config_IpIfNonMatch,
|
|
Rule: []*RoutingRule{
|
|
{
|
|
TargetTag: &RoutingRule_Tag{
|
|
Tag: "test",
|
|
},
|
|
Cidr: []*CIDR{
|
|
{
|
|
Ip: []byte{127, 0, 0, 0},
|
|
Prefix: 8,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
mockCtl := gomock.NewController(t)
|
|
defer mockCtl.Finish()
|
|
|
|
mockDNS := mocks.NewDNSClient(mockCtl)
|
|
|
|
r := new(Router)
|
|
common.Must(r.Init(context.TODO(), config, mockDNS, nil, nil))
|
|
|
|
ctx := session.ContextWithOutbounds(context.Background(), []*session.Outbound{{
|
|
Target: net.TCPDestination(net.LocalHostIP, 80),
|
|
}})
|
|
route, err := r.PickRoute(routing_session.AsRoutingContext(ctx))
|
|
common.Must(err)
|
|
if tag := route.GetOutboundTag(); tag != "test" {
|
|
t.Error("expect tag 'test', bug actually ", tag)
|
|
}
|
|
}
|