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 }