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  }