github.com/cloudwego/kitex@v0.9.0/pkg/remote/remotecli/conn_wrapper_test.go (about)

     1  /*
     2   * Copyright 2021 CloudWeGo Authors
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package remotecli
    18  
    19  import (
    20  	"context"
    21  	"errors"
    22  	"testing"
    23  	"time"
    24  
    25  	"github.com/golang/mock/gomock"
    26  
    27  	mocksnetpoll "github.com/cloudwego/kitex/internal/mocks/netpoll"
    28  	mocksremote "github.com/cloudwego/kitex/internal/mocks/remote"
    29  	"github.com/cloudwego/kitex/pkg/discovery"
    30  	"github.com/cloudwego/kitex/pkg/rpcinfo/remoteinfo"
    31  
    32  	"github.com/cloudwego/kitex/internal/test"
    33  	connpool2 "github.com/cloudwego/kitex/pkg/connpool"
    34  	"github.com/cloudwego/kitex/pkg/kerrors"
    35  	"github.com/cloudwego/kitex/pkg/remote/connpool"
    36  	"github.com/cloudwego/kitex/pkg/rpcinfo"
    37  	"github.com/cloudwego/kitex/pkg/utils"
    38  )
    39  
    40  var poolCfg = connpool2.IdleConfig{MaxIdlePerAddress: 100, MaxIdleGlobal: 100, MaxIdleTimeout: time.Second}
    41  
    42  func TestDialerMWNoAddr(t *testing.T) {
    43  	ctrl := gomock.NewController(t)
    44  	defer ctrl.Finish()
    45  
    46  	to := remoteinfo.NewRemoteInfo(&rpcinfo.EndpointBasicInfo{}, "")
    47  	conf := rpcinfo.NewRPCConfig()
    48  	ri := rpcinfo.NewRPCInfo(nil, to, rpcinfo.NewInvocation("", ""), conf, rpcinfo.NewRPCStats())
    49  	ctx := rpcinfo.NewCtxWithRPCInfo(context.Background(), ri)
    50  
    51  	connW := NewConnWrapper(connpool.NewLongPool("destService", poolCfg))
    52  	_, err := connW.GetConn(ctx, mocksremote.NewMockDialer(ctrl), ri)
    53  	test.Assert(t, err != nil)
    54  	test.Assert(t, errors.Is(err, kerrors.ErrNoDestAddress))
    55  }
    56  
    57  func TestGetConnDial(t *testing.T) {
    58  	ctrl := gomock.NewController(t)
    59  	defer ctrl.Finish()
    60  
    61  	addr := utils.NewNetAddr("tcp", "to")
    62  	conn := mocksnetpoll.NewMockConnection(ctrl)
    63  	dialer := mocksremote.NewMockDialer(ctrl)
    64  	dialer.EXPECT().DialTimeout(addr.Network(), addr.String(), gomock.Any()).Return(conn, nil)
    65  	from := rpcinfo.NewEndpointInfo("from", "method", nil, nil)
    66  	to := remoteinfo.NewRemoteInfo(&rpcinfo.EndpointBasicInfo{}, "")
    67  	to.SetInstance(discovery.NewInstance(addr.Network(), addr.String(), discovery.DefaultWeight, nil))
    68  	conf := rpcinfo.NewRPCConfig()
    69  	ri := rpcinfo.NewRPCInfo(from, to, rpcinfo.NewInvocation("", ""), conf, rpcinfo.NewRPCStats())
    70  
    71  	ctx := rpcinfo.NewCtxWithRPCInfo(context.Background(), ri)
    72  	connW := NewConnWrapper(nil)
    73  	conn2, err := connW.GetConn(ctx, dialer, ri)
    74  	test.Assert(t, err == nil, err)
    75  	test.Assert(t, conn == conn2)
    76  }
    77  
    78  func TestGetConnByPool(t *testing.T) {
    79  	ctrl := gomock.NewController(t)
    80  	defer ctrl.Finish()
    81  
    82  	addr := utils.NewNetAddr("tcp", "to")
    83  	conn := mocksnetpoll.NewMockConnection(ctrl)
    84  	conn.EXPECT().RemoteAddr().Return(addr).AnyTimes()
    85  	conn.EXPECT().IsActive().Return(true).AnyTimes()
    86  	conn.EXPECT().Close().AnyTimes()
    87  	dialer := mocksremote.NewMockDialer(ctrl)
    88  	dialer.EXPECT().DialTimeout(addr.Network(), addr.String(), gomock.Any()).Return(conn, nil).Times(1)
    89  	from := rpcinfo.NewEndpointInfo("from", "method", nil, nil)
    90  	to := remoteinfo.NewRemoteInfo(&rpcinfo.EndpointBasicInfo{}, "")
    91  	to.SetInstance(discovery.NewInstance(addr.Network(), addr.String(), discovery.DefaultWeight, nil))
    92  
    93  	conf := rpcinfo.NewRPCConfig()
    94  	ri := rpcinfo.NewRPCInfo(from, to, rpcinfo.NewInvocation("", ""), conf, rpcinfo.NewRPCStats())
    95  	connPool := connpool.NewLongPool("destService", poolCfg)
    96  	ctx := rpcinfo.NewCtxWithRPCInfo(context.Background(), ri)
    97  	// 释放连接, 连接复用
    98  	for i := 0; i < 10; i++ {
    99  		connW := NewConnWrapper(connPool)
   100  		conn2, err := connW.GetConn(ctx, dialer, ri)
   101  		test.Assert(t, err == nil, err)
   102  		test.Assert(t, conn == conn2)
   103  		connW.ReleaseConn(nil, ri)
   104  
   105  	}
   106  
   107  	dialer.EXPECT().DialTimeout(addr.Network(), addr.String(), gomock.Any()).Return(conn, nil).Times(10)
   108  	connPool.Clean(addr.Network(), addr.String())
   109  	// 未释放连接, 连接重建
   110  	for i := 0; i < 10; i++ {
   111  		connW := NewConnWrapper(connPool)
   112  		conn2, err := connW.GetConn(ctx, dialer, ri)
   113  		test.Assert(t, err == nil, err)
   114  		test.Assert(t, conn == conn2)
   115  	}
   116  }
   117  
   118  func BenchmarkGetConn(b *testing.B) {
   119  	ctrl := gomock.NewController(b)
   120  	defer ctrl.Finish()
   121  
   122  	addr := utils.NewNetAddr("tcp", "to")
   123  	conn := mocksnetpoll.NewMockConnection(ctrl)
   124  	conn.EXPECT().RemoteAddr().Return(addr).AnyTimes()
   125  	conn.EXPECT().IsActive().Return(true).AnyTimes()
   126  	conn.EXPECT().Close().AnyTimes()
   127  
   128  	shortConnDialer := mocksremote.NewMockDialer(ctrl)
   129  	shortConnDialer.EXPECT().DialTimeout(gomock.Any(), gomock.Any(), gomock.Any()).Return(conn, nil).Times(b.N)
   130  
   131  	longConnDialer := mocksremote.NewMockDialer(ctrl)
   132  	longConnDialer.EXPECT().DialTimeout(gomock.Any(), gomock.Any(), gomock.Any()).Return(conn, nil).Times(1)
   133  
   134  	from := rpcinfo.NewEndpointInfo("from", "method", nil, nil)
   135  	to := remoteinfo.NewRemoteInfo(&rpcinfo.EndpointBasicInfo{}, "")
   136  	to.SetInstance(discovery.NewInstance(addr.Network(), addr.String(), discovery.DefaultWeight, nil))
   137  
   138  	conf := rpcinfo.NewRPCConfig()
   139  	ri := rpcinfo.NewRPCInfo(from, to, rpcinfo.NewInvocation("", ""), conf, rpcinfo.NewRPCStats())
   140  	ctx := rpcinfo.NewCtxWithRPCInfo(context.Background(), ri)
   141  	connPool := connpool.NewLongPool("destService", poolCfg)
   142  
   143  	b.ResetTimer()
   144  	for i := 0; i < b.N; i++ {
   145  		connW := NewConnWrapper(connPool)
   146  		conn2, err := connW.GetConn(ctx, longConnDialer, ri)
   147  		test.Assert(b, err == nil, err)
   148  		test.Assert(b, conn == conn2)
   149  		connW.ReleaseConn(nil, ri)
   150  
   151  		connW2 := NewConnWrapper(nil)
   152  		conn2, err = connW2.GetConn(ctx, shortConnDialer, ri)
   153  		test.Assert(b, err == nil, err)
   154  		test.Assert(b, conn == conn2)
   155  		connW.ReleaseConn(nil, ri)
   156  	}
   157  }
   158  
   159  // TestReleaseConnUseNilConn test release conn without before GetConn
   160  func TestReleaseConnUseNilConn(t *testing.T) {
   161  	addr := utils.NewNetAddr("tcp", "to")
   162  	ri := newMockRPCInfo(addr)
   163  	connPool := connpool.NewLongPool("destService", poolCfg)
   164  	connW := NewConnWrapper(connPool)
   165  
   166  	connW.ReleaseConn(nil, ri)
   167  }
   168  
   169  // TestReleaseConn test release conn
   170  func TestReleaseConn(t *testing.T) {
   171  	ctrl := gomock.NewController(t)
   172  	defer ctrl.Finish()
   173  
   174  	addr := utils.NewNetAddr("tcp", "to")
   175  	ri := newMockRPCInfo(addr)
   176  
   177  	conn := mocksnetpoll.NewMockConnection(ctrl)
   178  	conn.EXPECT().RemoteAddr().Return(addr).AnyTimes()
   179  	conn.EXPECT().Close().Return(nil).MinTimes(1)
   180  
   181  	dialer := mocksremote.NewMockDialer(ctrl)
   182  	dialer.EXPECT().DialTimeout(addr.Network(), addr.String(), gomock.Any()).Return(conn, nil).AnyTimes()
   183  
   184  	ctx := rpcinfo.NewCtxWithRPCInfo(context.Background(), ri)
   185  
   186  	connW := NewConnWrapper(nil)
   187  	conn2, err := connW.GetConn(ctx, dialer, ri)
   188  	test.Assert(t, err == nil, err)
   189  	test.Assert(t, conn == conn2)
   190  	connW.ReleaseConn(nil, ri)
   191  }