github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/cdc/kv/sharedconn/conn_and_client_test.go (about) 1 // Copyright 2023 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package sharedconn 15 16 import ( 17 "context" 18 "net" 19 "sync" 20 "testing" 21 "time" 22 23 "github.com/pingcap/kvproto/pkg/cdcpb" 24 "github.com/pingcap/tiflow/pkg/security" 25 "github.com/stretchr/testify/require" 26 "google.golang.org/grpc" 27 "google.golang.org/grpc/codes" 28 grpccodes "google.golang.org/grpc/codes" 29 "google.golang.org/grpc/keepalive" 30 "google.golang.org/grpc/status" 31 grpcstatus "google.golang.org/grpc/status" 32 ) 33 34 func TestConnAndClientPool(t *testing.T) { 35 service := make(chan *grpc.Server, 1) 36 var addr string 37 38 var wg sync.WaitGroup 39 defer wg.Wait() 40 wg.Add(1) 41 go func() { 42 defer wg.Done() 43 require.Nil(t, runGrpcService(&srv{}, &addr, service)) 44 }() 45 46 svc := <-service 47 require.NotNil(t, svc) 48 defer svc.GracefulStop() 49 50 pool := newConnAndClientPool(&security.Credential{}, nil, 2) 51 cc1, err := pool.Connect(context.Background(), addr) 52 require.Nil(t, err) 53 require.NotNil(t, cc1) 54 require.Equal(t, 1, len(cc1.array.conns)) 55 require.Equal(t, 1, cc1.conn.streams) 56 require.False(t, cc1.Multiplexing()) 57 58 cc2, err := pool.Connect(context.Background(), addr) 59 require.Nil(t, err) 60 require.NotNil(t, cc2) 61 require.Equal(t, 1, len(cc2.array.conns)) 62 require.Equal(t, 2, cc2.conn.streams) 63 require.False(t, cc2.Multiplexing()) 64 65 cc3, err := pool.Connect(context.Background(), addr) 66 require.Nil(t, err) 67 require.NotNil(t, cc3) 68 require.Equal(t, 2, len(cc3.array.conns)) 69 require.Equal(t, 1, cc3.conn.streams) 70 require.False(t, cc3.Multiplexing()) 71 72 cc1.Release() 73 cc1.Release() 74 cc2.Release() 75 require.Equal(t, 1, len(cc3.array.conns)) 76 require.Equal(t, 1, cc3.conn.streams) 77 78 cc3.Release() 79 require.Equal(t, 0, len(pool.stores)) 80 } 81 82 func TestConnAndClientPoolForV2(t *testing.T) { 83 service := make(chan *grpc.Server, 1) 84 var addr string 85 86 var wg sync.WaitGroup 87 defer wg.Wait() 88 wg.Add(1) 89 go func() { 90 defer wg.Done() 91 require.Nil(t, runGrpcService(&srv{v2: true}, &addr, service)) 92 }() 93 94 svc := <-service 95 require.NotNil(t, svc) 96 defer svc.GracefulStop() 97 98 pool := newConnAndClientPool(&security.Credential{}, nil, 2) 99 cc1, err := pool.Connect(context.Background(), addr) 100 require.Nil(t, err) 101 require.NotNil(t, cc1) 102 require.True(t, cc1.Multiplexing()) 103 104 cc1.Release() 105 require.Equal(t, 0, len(pool.stores)) 106 } 107 108 func TestConnectToUnavailable(t *testing.T) { 109 pool := newConnAndClientPool(&security.Credential{}, nil, 1) 110 111 targets := []string{"127.0.0.1:9999", "2.2.2.2:9999"} 112 for _, target := range targets { 113 ctx := context.Background() 114 conn, err := pool.connect(ctx, target) 115 require.NotNil(t, conn) 116 require.Nil(t, err) 117 118 rpc := cdcpb.NewChangeDataClient(conn) 119 _, err = rpc.EventFeedV2(ctx) 120 require.NotNil(t, err) 121 122 require.Nil(t, conn.Close()) 123 } 124 125 service := make(chan *grpc.Server, 1) 126 var addr string 127 128 var wg sync.WaitGroup 129 defer wg.Wait() 130 wg.Add(1) 131 go func() { 132 defer wg.Done() 133 require.Nil(t, runGrpcService(&srv{}, &addr, service)) 134 }() 135 136 svc := <-service 137 require.NotNil(t, svc) 138 defer svc.GracefulStop() 139 140 conn, err := pool.connect(context.Background(), addr) 141 require.NotNil(t, conn) 142 require.Nil(t, err) 143 144 rpc := cdcpb.NewChangeDataClient(conn) 145 client, err := rpc.EventFeedV2(context.Background()) 146 require.Nil(t, err) 147 _ = client.CloseSend() 148 149 _, err = client.Recv() 150 require.Equal(t, codes.Unimplemented, status.Code(err)) 151 152 require.Nil(t, conn.Close()) 153 } 154 155 func TestCancelStream(t *testing.T) { 156 service := make(chan *grpc.Server, 1) 157 var addr string 158 var wg sync.WaitGroup 159 defer wg.Wait() 160 wg.Add(1) 161 go func() { 162 defer wg.Done() 163 require.Nil(t, runGrpcService(&srv{}, &addr, service)) 164 }() 165 166 svc := <-service 167 require.NotNil(t, svc) 168 defer svc.GracefulStop() 169 170 connCtx, connCancel := context.WithCancel(context.Background()) 171 defer connCancel() 172 173 pool := newConnAndClientPool(&security.Credential{}, nil, 1) 174 conn, err := pool.connect(connCtx, addr) 175 require.NotNil(t, conn) 176 require.Nil(t, err) 177 178 rpcCtx, rpcCancel := context.WithCancel(context.Background()) 179 rpc := cdcpb.NewChangeDataClient(conn) 180 client, err := rpc.EventFeed(rpcCtx) 181 require.Nil(t, err) 182 183 rpcCancel() 184 _, err = client.Recv() 185 require.Equal(t, grpccodes.Canceled, grpcstatus.Code(err)) 186 require.Nil(t, conn.Close()) 187 } 188 189 func runGrpcService(srv cdcpb.ChangeDataServer, addr *string, service chan<- *grpc.Server) error { 190 defer close(service) 191 lis, err := net.Listen("tcp", "127.0.0.1:0") 192 if err != nil { 193 return err 194 } 195 defer lis.Close() 196 197 kaep := keepalive.EnforcementPolicy{ 198 MinTime: 3 * time.Second, 199 PermitWithoutStream: true, 200 } 201 kasp := keepalive.ServerParameters{ 202 MaxConnectionIdle: 10 * time.Second, 203 MaxConnectionAge: 10 * time.Second, 204 MaxConnectionAgeGrace: 5 * time.Second, 205 Time: 3 * time.Second, 206 Timeout: 1 * time.Second, 207 } 208 grpcServer := grpc.NewServer(grpc.KeepaliveEnforcementPolicy(kaep), grpc.KeepaliveParams(kasp)) 209 cdcpb.RegisterChangeDataServer(grpcServer, srv) 210 *addr = lis.Addr().String() 211 service <- grpcServer 212 return grpcServer.Serve(lis) 213 } 214 215 type srv struct { 216 v2 bool 217 } 218 219 func (s *srv) EventFeed(server cdcpb.ChangeData_EventFeedServer) error { 220 for { 221 if _, err := server.Recv(); err != nil { 222 return err 223 } 224 } 225 } 226 227 func (s *srv) EventFeedV2(server cdcpb.ChangeData_EventFeedV2Server) error { 228 if !s.v2 { 229 return grpcstatus.Error(grpccodes.Unimplemented, "srv") 230 } 231 for { 232 if _, err := server.Recv(); err != nil { 233 return err 234 } 235 } 236 }