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