github.com/xtls/xray-core@v1.8.12-0.20240518155711-3168d27b0bdb/app/router/router_test.go (about) 1 package router_test 2 3 import ( 4 "context" 5 "testing" 6 7 "github.com/golang/mock/gomock" 8 . "github.com/xtls/xray-core/app/router" 9 "github.com/xtls/xray-core/common" 10 "github.com/xtls/xray-core/common/net" 11 "github.com/xtls/xray-core/common/session" 12 "github.com/xtls/xray-core/features/dns" 13 "github.com/xtls/xray-core/features/outbound" 14 routing_session "github.com/xtls/xray-core/features/routing/session" 15 "github.com/xtls/xray-core/testing/mocks" 16 ) 17 18 type mockOutboundManager struct { 19 outbound.Manager 20 outbound.HandlerSelector 21 } 22 23 func TestSimpleRouter(t *testing.T) { 24 config := &Config{ 25 Rule: []*RoutingRule{ 26 { 27 TargetTag: &RoutingRule_Tag{ 28 Tag: "test", 29 }, 30 Networks: []net.Network{net.Network_TCP}, 31 }, 32 }, 33 } 34 35 mockCtl := gomock.NewController(t) 36 defer mockCtl.Finish() 37 38 mockDNS := mocks.NewDNSClient(mockCtl) 39 mockOhm := mocks.NewOutboundManager(mockCtl) 40 mockHs := mocks.NewOutboundHandlerSelector(mockCtl) 41 42 r := new(Router) 43 common.Must(r.Init(context.TODO(), config, mockDNS, &mockOutboundManager{ 44 Manager: mockOhm, 45 HandlerSelector: mockHs, 46 }, nil)) 47 48 ctx := session.ContextWithOutbounds(context.Background(), []*session.Outbound{{ 49 Target: net.TCPDestination(net.DomainAddress("example.com"), 80), 50 }}) 51 route, err := r.PickRoute(routing_session.AsRoutingContext(ctx)) 52 common.Must(err) 53 if tag := route.GetOutboundTag(); tag != "test" { 54 t.Error("expect tag 'test', bug actually ", tag) 55 } 56 } 57 58 func TestSimpleBalancer(t *testing.T) { 59 config := &Config{ 60 Rule: []*RoutingRule{ 61 { 62 TargetTag: &RoutingRule_BalancingTag{ 63 BalancingTag: "balance", 64 }, 65 Networks: []net.Network{net.Network_TCP}, 66 }, 67 }, 68 BalancingRule: []*BalancingRule{ 69 { 70 Tag: "balance", 71 OutboundSelector: []string{"test-"}, 72 }, 73 }, 74 } 75 76 mockCtl := gomock.NewController(t) 77 defer mockCtl.Finish() 78 79 mockDNS := mocks.NewDNSClient(mockCtl) 80 mockOhm := mocks.NewOutboundManager(mockCtl) 81 mockHs := mocks.NewOutboundHandlerSelector(mockCtl) 82 83 mockHs.EXPECT().Select(gomock.Eq([]string{"test-"})).Return([]string{"test"}) 84 85 r := new(Router) 86 common.Must(r.Init(context.TODO(), config, mockDNS, &mockOutboundManager{ 87 Manager: mockOhm, 88 HandlerSelector: mockHs, 89 }, nil)) 90 91 ctx := session.ContextWithOutbounds(context.Background(), []*session.Outbound{{ 92 Target: net.TCPDestination(net.DomainAddress("example.com"), 80), 93 }}) 94 route, err := r.PickRoute(routing_session.AsRoutingContext(ctx)) 95 common.Must(err) 96 if tag := route.GetOutboundTag(); tag != "test" { 97 t.Error("expect tag 'test', bug actually ", tag) 98 } 99 } 100 101 /* 102 103 Do not work right now: need a full client setup 104 105 func TestLeastLoadBalancer(t *testing.T) { 106 config := &Config{ 107 Rule: []*RoutingRule{ 108 { 109 TargetTag: &RoutingRule_BalancingTag{ 110 BalancingTag: "balance", 111 }, 112 Networks: []net.Network{net.Network_TCP}, 113 }, 114 }, 115 BalancingRule: []*BalancingRule{ 116 { 117 Tag: "balance", 118 OutboundSelector: []string{"test-"}, 119 Strategy: "leastLoad", 120 StrategySettings: serial.ToTypedMessage(&StrategyLeastLoadConfig{ 121 Baselines: nil, 122 Expected: 1, 123 }), 124 }, 125 }, 126 } 127 128 mockCtl := gomock.NewController(t) 129 defer mockCtl.Finish() 130 131 mockDNS := mocks.NewDNSClient(mockCtl) 132 mockOhm := mocks.NewOutboundManager(mockCtl) 133 mockHs := mocks.NewOutboundHandlerSelector(mockCtl) 134 135 mockHs.EXPECT().Select(gomock.Eq([]string{"test-"})).Return([]string{"test1"}) 136 137 r := new(Router) 138 common.Must(r.Init(context.TODO(), config, mockDNS, &mockOutboundManager{ 139 Manager: mockOhm, 140 HandlerSelector: mockHs, 141 }, nil)) 142 ctx := session.ContextWithOutbound(context.Background(), &session.Outbound{Target: net.TCPDestination(net.DomainAddress("v2ray.com"), 80)}) 143 route, err := r.PickRoute(routing_session.AsRoutingContext(ctx)) 144 common.Must(err) 145 if tag := route.GetOutboundTag(); tag != "test1" { 146 t.Error("expect tag 'test1', bug actually ", tag) 147 } 148 }*/ 149 150 func TestIPOnDemand(t *testing.T) { 151 config := &Config{ 152 DomainStrategy: Config_IpOnDemand, 153 Rule: []*RoutingRule{ 154 { 155 TargetTag: &RoutingRule_Tag{ 156 Tag: "test", 157 }, 158 Cidr: []*CIDR{ 159 { 160 Ip: []byte{192, 168, 0, 0}, 161 Prefix: 16, 162 }, 163 }, 164 }, 165 }, 166 } 167 168 mockCtl := gomock.NewController(t) 169 defer mockCtl.Finish() 170 171 mockDNS := mocks.NewDNSClient(mockCtl) 172 mockDNS.EXPECT().LookupIP(gomock.Eq("example.com"), dns.IPOption{ 173 IPv4Enable: true, 174 IPv6Enable: true, 175 FakeEnable: false, 176 }).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes() 177 178 r := new(Router) 179 common.Must(r.Init(context.TODO(), config, mockDNS, nil, nil)) 180 181 ctx := session.ContextWithOutbounds(context.Background(), []*session.Outbound{{ 182 Target: net.TCPDestination(net.DomainAddress("example.com"), 80), 183 }}) 184 route, err := r.PickRoute(routing_session.AsRoutingContext(ctx)) 185 common.Must(err) 186 if tag := route.GetOutboundTag(); tag != "test" { 187 t.Error("expect tag 'test', bug actually ", tag) 188 } 189 } 190 191 func TestIPIfNonMatchDomain(t *testing.T) { 192 config := &Config{ 193 DomainStrategy: Config_IpIfNonMatch, 194 Rule: []*RoutingRule{ 195 { 196 TargetTag: &RoutingRule_Tag{ 197 Tag: "test", 198 }, 199 Cidr: []*CIDR{ 200 { 201 Ip: []byte{192, 168, 0, 0}, 202 Prefix: 16, 203 }, 204 }, 205 }, 206 }, 207 } 208 209 mockCtl := gomock.NewController(t) 210 defer mockCtl.Finish() 211 212 mockDNS := mocks.NewDNSClient(mockCtl) 213 mockDNS.EXPECT().LookupIP(gomock.Eq("example.com"), dns.IPOption{ 214 IPv4Enable: true, 215 IPv6Enable: true, 216 FakeEnable: false, 217 }).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes() 218 219 r := new(Router) 220 common.Must(r.Init(context.TODO(), config, mockDNS, nil, nil)) 221 222 ctx := session.ContextWithOutbounds(context.Background(), []*session.Outbound{{ 223 Target: net.TCPDestination(net.DomainAddress("example.com"), 80), 224 }}) 225 route, err := r.PickRoute(routing_session.AsRoutingContext(ctx)) 226 common.Must(err) 227 if tag := route.GetOutboundTag(); tag != "test" { 228 t.Error("expect tag 'test', bug actually ", tag) 229 } 230 } 231 232 func TestIPIfNonMatchIP(t *testing.T) { 233 config := &Config{ 234 DomainStrategy: Config_IpIfNonMatch, 235 Rule: []*RoutingRule{ 236 { 237 TargetTag: &RoutingRule_Tag{ 238 Tag: "test", 239 }, 240 Cidr: []*CIDR{ 241 { 242 Ip: []byte{127, 0, 0, 0}, 243 Prefix: 8, 244 }, 245 }, 246 }, 247 }, 248 } 249 250 mockCtl := gomock.NewController(t) 251 defer mockCtl.Finish() 252 253 mockDNS := mocks.NewDNSClient(mockCtl) 254 255 r := new(Router) 256 common.Must(r.Init(context.TODO(), config, mockDNS, nil, nil)) 257 258 ctx := session.ContextWithOutbounds(context.Background(), []*session.Outbound{{ 259 Target: net.TCPDestination(net.LocalHostIP, 80), 260 }}) 261 route, err := r.PickRoute(routing_session.AsRoutingContext(ctx)) 262 common.Must(err) 263 if tag := route.GetOutboundTag(); tag != "test" { 264 t.Error("expect tag 'test', bug actually ", tag) 265 } 266 }