github.com/cloudwego/kitex@v0.9.0/pkg/remote/trans/netpollmux/client_handler_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 netpollmux 18 19 import ( 20 "context" 21 "strings" 22 "testing" 23 "time" 24 25 "github.com/cloudwego/netpoll" 26 27 "github.com/cloudwego/kitex/internal/test" 28 "github.com/cloudwego/kitex/pkg/remote" 29 "github.com/cloudwego/kitex/pkg/remote/codec" 30 "github.com/cloudwego/kitex/pkg/remote/trans" 31 np "github.com/cloudwego/kitex/pkg/remote/trans/netpoll" 32 "github.com/cloudwego/kitex/pkg/rpcinfo" 33 "github.com/cloudwego/kitex/pkg/serviceinfo" 34 ) 35 36 func newTestRemoteClientOptionWithInStr(s string) *remote.ClientOption { 37 opt := &remote.ClientOption{ 38 Codec: &MockCodec{ 39 EncodeFunc: func(ctx context.Context, msg remote.Message, out remote.ByteBuffer) error { 40 r := mockHeader(msg.RPCInfo().Invocation().SeqID(), s) 41 _, err := out.WriteBinary(r.Bytes()) 42 return err 43 }, 44 DecodeFunc: func(ctx context.Context, msg remote.Message, in remote.ByteBuffer) error { 45 in.Skip(3 * codec.Size32) 46 _, err := in.ReadString(len(s)) 47 return err 48 }, 49 }, 50 ConnPool: NewMuxConnPool(1), 51 } 52 return opt 53 } 54 55 func TestNewCliTransHandler(t *testing.T) { 56 // check success 57 handler, err := NewCliTransHandlerFactory().NewTransHandler(&remote.ClientOption{ 58 ConnPool: &MuxPool{}, 59 }) 60 test.Assert(t, err == nil, err) 61 test.Assert(t, handler != nil) 62 // check fail 63 handler, err = NewCliTransHandlerFactory().NewTransHandler(&remote.ClientOption{}) 64 test.Assert(t, err != nil) 65 test.Assert(t, handler == nil) 66 } 67 68 func TestCliTransHandler(t *testing.T) { 69 s := "hello world" 70 opt := &remote.ClientOption{ 71 Codec: &MockCodec{ 72 EncodeFunc: func(ctx context.Context, msg remote.Message, out remote.ByteBuffer) error { 73 r := mockHeader(msg.RPCInfo().Invocation().SeqID(), s) 74 n, err := out.WriteBinary(r.Bytes()) 75 test.Assert(t, err == nil, err) 76 test.Assert(t, n == r.Len(), n, r.Len()) 77 return err 78 }, 79 DecodeFunc: func(ctx context.Context, msg remote.Message, in remote.ByteBuffer) error { 80 l := in.ReadableLen() 81 test.Assert(t, l == 3*codec.Size32+len(s)) 82 in.Skip(3 * codec.Size32) 83 got, err := in.ReadString(len(s)) 84 test.Assert(t, err == nil, err) 85 test.Assert(t, got == s, got, s) 86 return err 87 }, 88 }, 89 ConnPool: NewMuxConnPool(1), 90 } 91 92 handler, err := NewCliTransHandlerFactory().NewTransHandler(opt) 93 test.Assert(t, err == nil) 94 95 ctx := context.Background() 96 buf := netpoll.NewLinkBuffer(1024) 97 npconn := &MockNetpollConn{ 98 ReaderFunc: func() (r netpoll.Reader) { 99 return buf 100 }, 101 WriterFunc: func() (r netpoll.Writer) { 102 return buf 103 }, 104 } 105 conn := newMuxCliConn(npconn) 106 107 ri := newMockRPCInfo() 108 msg := &MockMessage{ 109 RPCInfoFunc: func() rpcinfo.RPCInfo { 110 return ri 111 }, 112 ServiceInfoFunc: func() *serviceinfo.ServiceInfo { 113 return &serviceinfo.ServiceInfo{ 114 Methods: map[string]serviceinfo.MethodInfo{ 115 "method": serviceinfo.NewMethodInfo(nil, nil, nil, false), 116 }, 117 } 118 }, 119 } 120 ctx, err = handler.Write(ctx, conn, msg) 121 test.Assert(t, ctx != nil, ctx) 122 test.Assert(t, err == nil, err) 123 124 time.Sleep(5 * time.Millisecond) 125 buf.Flush() 126 test.Assert(t, buf.Len() > len(s), buf.Len()) 127 128 err = conn.OnRequest(ctx, npconn) 129 test.Assert(t, err == nil, err) 130 131 ctx, err = handler.Read(ctx, conn, msg) 132 test.Assert(t, ctx != nil, ctx) 133 test.Assert(t, err == nil, err) 134 } 135 136 // TestWriteNoMethod test client_handler write return unknown method err 137 func TestWriteNoMethod(t *testing.T) { 138 // 1. prepare mock data 139 s := "hello world" 140 opt := newTestRemoteClientOptionWithInStr(s) 141 142 handler, err := NewCliTransHandlerFactory().NewTransHandler(opt) 143 test.Assert(t, err == nil) 144 145 ctx := context.Background() 146 147 var isWriteBufFlushed bool 148 149 buf := netpoll.NewLinkBuffer(1024) 150 npconn := &MockNetpollConn{ 151 ReaderFunc: func() (r netpoll.Reader) { 152 return buf 153 }, 154 WriterFunc: func() (r netpoll.Writer) { 155 isWriteBufFlushed = true 156 return buf 157 }, 158 } 159 conn := newMuxCliConn(npconn) 160 161 ri := newMockRPCInfo() 162 msg := &MockMessage{ 163 RPCInfoFunc: func() rpcinfo.RPCInfo { 164 return ri 165 }, 166 ServiceInfoFunc: func() *serviceinfo.ServiceInfo { 167 return &serviceinfo.ServiceInfo{} 168 }, 169 } 170 171 // 2. test 172 ctx, err = handler.Write(ctx, conn, msg) 173 // check ctx/err not nil 174 test.Assert(t, ctx != nil, ctx) 175 test.Assert(t, err != nil, err) 176 tErr, ok := err.(*remote.TransError) 177 test.Assert(t, ok) 178 test.Assert(t, tErr.TypeID() == remote.UnknownMethod) 179 test.Assert(t, !isWriteBufFlushed) 180 } 181 182 // TestWriteOneWayMethod test client_handler write oneway method 183 func TestWriteOneWayMethod(t *testing.T) { 184 // 1. prepare mock data 185 s := "hello world" 186 opt := newTestRemoteClientOptionWithInStr(s) 187 188 handler, err := NewCliTransHandlerFactory().NewTransHandler(opt) 189 test.Assert(t, err == nil) 190 191 ctx := context.Background() 192 ri := newMockRPCInfo() 193 194 buf := netpoll.NewLinkBuffer(2048) 195 var isWrite bool 196 var isRead bool 197 npconn := &MockNetpollConn{ 198 ReaderFunc: func() (r netpoll.Reader) { 199 isRead = true 200 return buf 201 }, 202 WriterFunc: func() (r netpoll.Writer) { 203 isWrite = true 204 return buf 205 }, 206 } 207 conn := newMuxCliConn(npconn) 208 209 oneWayMsg := &MockMessage{ 210 RPCInfoFunc: func() rpcinfo.RPCInfo { 211 return ri 212 }, 213 ServiceInfoFunc: func() *serviceinfo.ServiceInfo { 214 return &serviceinfo.ServiceInfo{ 215 Methods: map[string]serviceinfo.MethodInfo{ 216 "method": serviceinfo.NewMethodInfo(nil, nil, nil, true), 217 }, 218 } 219 }, 220 } 221 ctx, err = handler.Write(ctx, conn, oneWayMsg) 222 test.Assert(t, ctx != nil, ctx) 223 test.Assert(t, err == nil, err) 224 225 time.Sleep(5 * time.Millisecond) 226 buf.Flush() 227 test.Assert(t, isWrite) 228 test.Assert(t, buf.Len() > len(s), buf.Len()) 229 230 err = conn.OnRequest(ctx, npconn) 231 test.Assert(t, err == nil, err) 232 233 test.Assert(t, isRead) 234 } 235 236 // TestReadTimeout test client_handler read timeout because of no execute OnRequest 237 func TestReadTimeout(t *testing.T) { 238 s := "hello world" 239 opt := newTestRemoteClientOptionWithInStr(s) 240 241 handler, err := NewCliTransHandlerFactory().NewTransHandler(opt) 242 test.Assert(t, err == nil, err) 243 244 ctx := context.Background() 245 buf := netpoll.NewLinkBuffer(1024) 246 247 var isRead, isWrite bool 248 249 npconn := &MockNetpollConn{ 250 ReaderFunc: func() (r netpoll.Reader) { 251 isRead = true 252 return buf 253 }, 254 WriterFunc: func() (r netpoll.Writer) { 255 isWrite = true 256 return buf 257 }, 258 } 259 conn := newMuxCliConn(npconn) 260 261 cfg := rpcinfo.NewRPCConfig() 262 rwTimeout := 1 * time.Second 263 rpcinfo.AsMutableRPCConfig(cfg).SetRPCTimeout(rwTimeout) 264 265 method := "method" 266 c := rpcinfo.NewEndpointInfo("", method, nil, nil) 267 to := rpcinfo.NewEndpointInfo("", method, nil, nil) 268 ri := rpcinfo.NewRPCInfo(c, to, rpcinfo.NewInvocation("", method), cfg, rpcinfo.NewRPCStats()) 269 msg := &MockMessage{ 270 RPCInfoFunc: func() rpcinfo.RPCInfo { 271 return ri 272 }, 273 ServiceInfoFunc: func() *serviceinfo.ServiceInfo { 274 return &serviceinfo.ServiceInfo{ 275 Methods: map[string]serviceinfo.MethodInfo{ 276 "method": serviceinfo.NewMethodInfo(nil, nil, nil, false), 277 }, 278 } 279 }, 280 } 281 282 ctx, err = handler.Write(ctx, conn, msg) 283 test.Assert(t, ctx != nil, ctx) 284 test.Assert(t, err == nil, err) 285 286 time.Sleep(5 * time.Millisecond) 287 buf.Flush() 288 test.Assert(t, isWrite) 289 test.Assert(t, buf.Len() > len(s), buf.Len()) 290 291 ctx, err = handler.Read(ctx, conn, msg) 292 test.Assert(t, rwTimeout <= trans.GetReadTimeout(ri.Config())) 293 test.Assert(t, ctx != nil, ctx) 294 test.Assert(t, err != nil, err) 295 test.Assert(t, strings.Contains(err.Error(), "recv wait timeout")) 296 test.Assert(t, !isRead) 297 298 handler.OnError(ctx, err, conn) 299 } 300 301 // TestCallbackClose test asyncCallback Close 302 func TestCallbackClose(t *testing.T) { 303 buf := netpoll.NewLinkBuffer() 304 bufWriter := np.NewWriterByteBuffer(buf) 305 callback := newAsyncCallback(buf, bufWriter) 306 callback.Close() 307 }