github.com/cloudwego/kitex@v0.9.0/server/option_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 server 18 19 import ( 20 "context" 21 "math/rand" 22 "net" 23 "testing" 24 "time" 25 26 "github.com/cloudwego/kitex/internal/mocks" 27 "github.com/cloudwego/kitex/internal/test" 28 "github.com/cloudwego/kitex/pkg/diagnosis" 29 "github.com/cloudwego/kitex/pkg/endpoint" 30 "github.com/cloudwego/kitex/pkg/remote" 31 "github.com/cloudwego/kitex/pkg/remote/codec/protobuf" 32 "github.com/cloudwego/kitex/pkg/remote/trans/detection" 33 "github.com/cloudwego/kitex/pkg/remote/trans/netpoll" 34 "github.com/cloudwego/kitex/pkg/remote/trans/netpollmux" 35 "github.com/cloudwego/kitex/pkg/remote/trans/nphttp2" 36 "github.com/cloudwego/kitex/pkg/remote/trans/nphttp2/grpc" 37 "github.com/cloudwego/kitex/pkg/rpcinfo" 38 "github.com/cloudwego/kitex/pkg/serviceinfo" 39 "github.com/cloudwego/kitex/pkg/stats" 40 "github.com/cloudwego/kitex/pkg/utils" 41 ) 42 43 // TestOptionDebugInfo tests the creation of a server with DebugService option 44 func TestOptionDebugInfo(t *testing.T) { 45 var opts []Option 46 md := newMockDiagnosis() 47 opts = append(opts, WithDiagnosisService(md)) 48 buildMw := 0 49 opts = append(opts, WithMiddleware(func(next endpoint.Endpoint) endpoint.Endpoint { 50 buildMw++ 51 return func(ctx context.Context, req, resp interface{}) (err error) { 52 return next(ctx, req, resp) 53 } 54 })) 55 opts = append(opts, WithMiddlewareBuilder(func(ctx context.Context) endpoint.Middleware { 56 return func(next endpoint.Endpoint) endpoint.Endpoint { 57 buildMw++ 58 return next 59 } 60 })) 61 62 svr := NewServer(opts...) 63 // check middleware build 64 test.Assert(t, buildMw == 2) 65 66 // check probe result 67 pp := md.ProbePairs() 68 test.Assert(t, pp != nil) 69 70 optFunc := pp[diagnosis.OptionsKey] 71 test.Assert(t, optFunc != nil) 72 73 is := svr.(*server) 74 debugInfo := is.opt.DebugInfo 75 optDebugInfo := optFunc().(utils.Slice) 76 test.Assert(t, len(debugInfo) == len(optDebugInfo)) 77 test.Assert(t, len(debugInfo) == 3) 78 79 for i := range debugInfo { 80 test.Assert(t, debugInfo[i] == optDebugInfo[i]) 81 } 82 } 83 84 // TestProxyOption tests the creation of a server with Proxy option 85 func TestProxyOption(t *testing.T) { 86 var opts []Option 87 addr, err := net.ResolveTCPAddr("tcp", ":8888") 88 test.Assert(t, err == nil, err) 89 opts = append(opts, WithServiceAddr(addr)) 90 opts = append(opts, WithProxy(&proxyMock{})) 91 svr := NewServer(opts...) 92 time.AfterFunc(100*time.Millisecond, func() { 93 err := svr.Stop() 94 test.Assert(t, err == nil, err) 95 }) 96 97 err = svr.RegisterService(mocks.ServiceInfo(), mocks.MyServiceHandler()) 98 test.Assert(t, err == nil) 99 100 err = svr.Run() 101 test.Assert(t, err == nil, err) 102 iSvr := svr.(*server) 103 test.Assert(t, iSvr.opt.RemoteOpt.Address.String() == "mock", iSvr.opt.RemoteOpt.Address.Network()) 104 } 105 106 type proxyMock struct{} 107 108 func (p *proxyMock) Replace(addr net.Addr) (nAddr net.Addr, err error) { 109 if nAddr, err = net.ResolveUnixAddr("unix", "mock"); err == nil { 110 return nAddr, err 111 } 112 return 113 } 114 115 func newMockDiagnosis() *mockDiagnosis { 116 return &mockDiagnosis{probes: make(map[diagnosis.ProbeName]diagnosis.ProbeFunc)} 117 } 118 119 type mockDiagnosis struct { 120 probes map[diagnosis.ProbeName]diagnosis.ProbeFunc 121 } 122 123 func (m *mockDiagnosis) RegisterProbeFunc(name diagnosis.ProbeName, probeFunc diagnosis.ProbeFunc) { 124 m.probes[name] = probeFunc 125 } 126 127 func (m *mockDiagnosis) ProbePairs() map[diagnosis.ProbeName]diagnosis.ProbeFunc { 128 return m.probes 129 } 130 131 // TestExitWaitTimeOption tests the creation of a server with RemoteOpt.ExitWaitTime option 132 func TestExitWaitTimeOption(t *testing.T) { 133 // random timeout value 134 testTimeOut := time.Duration(time.Now().Unix()) * time.Microsecond 135 svr := NewServer(WithExitWaitTime(testTimeOut)) 136 err := svr.RegisterService(mocks.ServiceInfo(), mocks.MyServiceHandler()) 137 test.Assert(t, err == nil, err) 138 time.AfterFunc(100*time.Millisecond, func() { 139 err := svr.Stop() 140 test.Assert(t, err == nil, err) 141 }) 142 err = svr.Run() 143 test.Assert(t, err == nil, err) 144 iSvr := svr.(*server) 145 test.Assert(t, iSvr.opt.RemoteOpt.ExitWaitTime == testTimeOut) 146 } 147 148 // TestMaxConnIdleTimeOption tests the creation of a server with RemoteOpt.MaxConnectionIdleTime option 149 func TestMaxConnIdleTimeOption(t *testing.T) { 150 // random timeout value 151 testTimeOut := time.Duration(time.Now().Unix()) 152 svr := NewServer(WithMaxConnIdleTime(testTimeOut)) 153 err := svr.RegisterService(mocks.ServiceInfo(), mocks.MyServiceHandler()) 154 test.Assert(t, err == nil, err) 155 time.AfterFunc(100*time.Millisecond, func() { 156 err := svr.Stop() 157 test.Assert(t, err == nil, err) 158 }) 159 err = svr.Run() 160 test.Assert(t, err == nil, err) 161 iSvr := svr.(*server) 162 test.Assert(t, iSvr.opt.RemoteOpt.MaxConnectionIdleTime == testTimeOut) 163 } 164 165 type myTracer struct{} 166 167 func (t *myTracer) Start(ctx context.Context) context.Context { 168 return nil 169 } 170 171 func (t *myTracer) Finish(ctx context.Context) { 172 } 173 174 // TestTracerOption tests the creation of a server with TracerCtl option 175 func TestTracerOption(t *testing.T) { 176 svr1 := NewServer() 177 err := svr1.RegisterService(mocks.ServiceInfo(), mocks.MyServiceHandler()) 178 test.Assert(t, err == nil, err) 179 time.AfterFunc(100*time.Millisecond, func() { 180 err := svr1.Stop() 181 test.Assert(t, err == nil, err) 182 }) 183 err = svr1.Run() 184 test.Assert(t, err == nil, err) 185 iSvr1 := svr1.(*server) 186 test.Assert(t, iSvr1.opt.TracerCtl != nil) 187 test.Assert(t, iSvr1.opt.TracerCtl.HasTracer() != true) 188 189 tracer := &myTracer{} 190 svr2 := NewServer(WithTracer(tracer)) 191 err = svr2.RegisterService(mocks.ServiceInfo(), mocks.MyServiceHandler()) 192 test.Assert(t, err == nil, err) 193 time.AfterFunc(100*time.Millisecond, func() { 194 err := svr2.Stop() 195 test.Assert(t, err == nil, err) 196 }) 197 err = svr2.Run() 198 test.Assert(t, err == nil, err) 199 iSvr2 := svr2.(*server) 200 test.Assert(t, iSvr2.opt.TracerCtl != nil) 201 test.Assert(t, iSvr2.opt.TracerCtl.HasTracer()) 202 } 203 204 // TestStatsLevelOption tests the creation of a server with StatsLevel option 205 func TestStatsLevelOption(t *testing.T) { 206 svr1 := NewServer() 207 err := svr1.RegisterService(mocks.ServiceInfo(), mocks.MyServiceHandler()) 208 test.Assert(t, err == nil, err) 209 time.AfterFunc(100*time.Millisecond, func() { 210 err := svr1.Stop() 211 test.Assert(t, err == nil, err) 212 }) 213 err = svr1.Run() 214 test.Assert(t, err == nil, err) 215 iSvr1 := svr1.(*server) 216 test.Assert(t, iSvr1.opt.StatsLevel != nil) 217 test.Assert(t, *iSvr1.opt.StatsLevel == stats.LevelDisabled) 218 219 svr2 := NewServer(WithStatsLevel(stats.LevelDetailed)) 220 err = svr2.RegisterService(mocks.ServiceInfo(), mocks.MyServiceHandler()) 221 test.Assert(t, err == nil, err) 222 time.AfterFunc(100*time.Millisecond, func() { 223 err := svr2.Stop() 224 test.Assert(t, err == nil, err) 225 }) 226 err = svr2.Run() 227 test.Assert(t, err == nil, err) 228 iSvr2 := svr2.(*server) 229 test.Assert(t, *iSvr2.opt.StatsLevel == stats.LevelDetailed) 230 } 231 232 type mySuiteOption struct { 233 myOpts []Option 234 } 235 236 func (s *mySuiteOption) Options() []Option { 237 return s.myOpts 238 } 239 240 // TestSuiteOption tests the creation of a server with SuiteOption option 241 func TestSuiteOption(t *testing.T) { 242 svr1 := NewServer() 243 time.AfterFunc(100*time.Millisecond, func() { 244 err := svr1.Stop() 245 test.Assert(t, err == nil, err) 246 }) 247 err := svr1.RegisterService(mocks.ServiceInfo(), mocks.MyServiceHandler()) 248 test.Assert(t, err == nil, err) 249 err = svr1.Run() 250 test.Assert(t, err == nil, err) 251 iSvr1 := svr1.(*server) 252 defaultExitWaitTime := iSvr1.opt.RemoteOpt.ExitWaitTime 253 defaultConnectionIdleTime := iSvr1.opt.RemoteOpt.MaxConnectionIdleTime 254 test.Assert(t, defaultExitWaitTime != 0) 255 test.Assert(t, defaultConnectionIdleTime != 0) 256 257 tmpWaitTime := defaultExitWaitTime*2 + time.Duration(rand.Intn(20)) 258 tmpConnIdleTime := defaultConnectionIdleTime*2 + time.Duration(rand.Intn(20)) 259 suiteOpt := &mySuiteOption{myOpts: []Option{ 260 WithExitWaitTime(tmpWaitTime), 261 WithMaxConnIdleTime(tmpConnIdleTime), 262 }} 263 svr2 := NewServer(WithSuite(suiteOpt)) 264 time.AfterFunc(100*time.Millisecond, func() { 265 err := svr2.Stop() 266 test.Assert(t, err == nil, err) 267 }) 268 err = svr2.RegisterService(mocks.ServiceInfo(), mocks.MyServiceHandler()) 269 test.Assert(t, err == nil, err) 270 err = svr2.Run() 271 test.Assert(t, err == nil, err) 272 iSvr2 := svr2.(*server) 273 test.Assert(t, iSvr2.opt.RemoteOpt.ExitWaitTime != defaultExitWaitTime, iSvr2.opt.RemoteOpt.ExitWaitTime) 274 test.Assert(t, iSvr2.opt.RemoteOpt.MaxConnectionIdleTime != defaultConnectionIdleTime, iSvr2.opt.RemoteOpt.ExitWaitTime) 275 276 test.Assert(t, iSvr2.opt.RemoteOpt.ExitWaitTime == tmpWaitTime, iSvr2.opt.RemoteOpt.ExitWaitTime) 277 test.Assert(t, iSvr2.opt.RemoteOpt.MaxConnectionIdleTime == tmpConnIdleTime, iSvr2.opt.RemoteOpt.MaxConnectionIdleTime) 278 } 279 280 // TestMuxTransportOption tests the creation of a server,with netpollmux remote.ServerTransHandlerFactory option, 281 func TestMuxTransportOption(t *testing.T) { 282 svr1 := NewServer() 283 time.AfterFunc(100*time.Millisecond, func() { 284 err := svr1.Stop() 285 test.Assert(t, err == nil, err) 286 }) 287 err := svr1.RegisterService(mocks.ServiceInfo(), mocks.MyServiceHandler()) 288 test.Assert(t, err == nil, err) 289 err = svr1.Run() 290 test.Assert(t, err == nil, err) 291 iSvr1 := svr1.(*server) 292 test.DeepEqual(t, iSvr1.opt.RemoteOpt.SvrHandlerFactory, detection.NewSvrTransHandlerFactory(netpoll.NewSvrTransHandlerFactory(), nphttp2.NewSvrTransHandlerFactory())) 293 294 svr2 := NewServer(WithMuxTransport()) 295 time.AfterFunc(100*time.Millisecond, func() { 296 err := svr2.Stop() 297 test.Assert(t, err == nil, err) 298 }) 299 err = svr2.RegisterService(mocks.ServiceInfo(), mocks.MyServiceHandler()) 300 test.Assert(t, err == nil, err) 301 err = svr2.Run() 302 test.Assert(t, err == nil, err) 303 iSvr2 := svr2.(*server) 304 handlerFactory := iSvr2.opt.RemoteOpt.SvrHandlerFactory 305 test.DeepEqual(t, handlerFactory, netpollmux.NewSvrTransHandlerFactory()) 306 } 307 308 // TestPayloadCodecOption tests the creation of a server with RemoteOpt.PayloadCodec option 309 func TestPayloadCodecOption(t *testing.T) { 310 svr1 := NewServer() 311 time.AfterFunc(100*time.Millisecond, func() { 312 err := svr1.Stop() 313 test.Assert(t, err == nil, err) 314 }) 315 err := svr1.RegisterService(mocks.ServiceInfo(), mocks.MyServiceHandler()) 316 test.Assert(t, err == nil, err) 317 err = svr1.Run() 318 test.Assert(t, err == nil, err) 319 iSvr1 := svr1.(*server) 320 test.Assert(t, iSvr1.opt.RemoteOpt.PayloadCodec == nil) 321 322 svr2 := NewServer(WithPayloadCodec(protobuf.NewProtobufCodec())) 323 time.AfterFunc(100*time.Millisecond, func() { 324 err := svr2.Stop() 325 test.Assert(t, err == nil, err) 326 }) 327 err = svr2.RegisterService(mocks.ServiceInfo(), mocks.MyServiceHandler()) 328 test.Assert(t, err == nil, err) 329 err = svr2.Run() 330 test.Assert(t, err == nil, err) 331 iSvr2 := svr2.(*server) 332 test.Assert(t, iSvr2.opt.RemoteOpt.PayloadCodec != nil) 333 test.DeepEqual(t, iSvr2.opt.RemoteOpt.PayloadCodec, protobuf.NewProtobufCodec()) 334 } 335 336 // TestRemoteOptGRPCCfgUintValueOption tests the creation of a server with RemoteOpt.GRPCCfg option 337 // and the value of the option is uint32 338 func TestRemoteOptGRPCCfgUintValueOption(t *testing.T) { 339 // random value between 1 and 100 340 randUint1 := uint32(rand.Int31n(100)) + 1 341 randUint2 := uint32(rand.Int31n(100)) + 1 342 randUint3 := uint32(rand.Int31n(100)) + 1 343 randUint4 := uint32(rand.Int31n(100)) + 1 344 345 svr1 := NewServer( 346 WithGRPCInitialWindowSize(randUint1), 347 WithGRPCInitialConnWindowSize(randUint2), 348 WithGRPCMaxConcurrentStreams(randUint3), 349 WithGRPCMaxHeaderListSize(randUint4), 350 ) 351 352 time.AfterFunc(100*time.Millisecond, func() { 353 err := svr1.Stop() 354 test.Assert(t, err == nil, err) 355 }) 356 err := svr1.RegisterService(mocks.ServiceInfo(), mocks.MyServiceHandler()) 357 test.Assert(t, err == nil, err) 358 err = svr1.Run() 359 test.Assert(t, err == nil, err) 360 iSvr1 := svr1.(*server) 361 362 test.Assert(t, iSvr1.opt.RemoteOpt.GRPCCfg.InitialWindowSize == randUint1) 363 test.Assert(t, iSvr1.opt.RemoteOpt.GRPCCfg.InitialConnWindowSize == randUint2) 364 test.Assert(t, iSvr1.opt.RemoteOpt.GRPCCfg.MaxStreams == randUint3) 365 test.Assert(t, *iSvr1.opt.RemoteOpt.GRPCCfg.MaxHeaderListSize == randUint4) 366 } 367 368 // TestGRPCKeepaliveEnforcementPolicyOption tests the creation of a server with RemoteOpt.GRPCCfg.KeepaliveEnforcementPolicy option 369 func TestGRPCKeepaliveEnforcementPolicyOption(t *testing.T) { 370 // random value between 1 and 100 371 randInt := rand.Int31n(100) + 1 372 kep := grpc.EnforcementPolicy{ 373 MinTime: time.Duration(randInt) * time.Second, 374 PermitWithoutStream: true, 375 } 376 svr1 := NewServer( 377 WithGRPCKeepaliveEnforcementPolicy(kep), 378 ) 379 380 time.AfterFunc(100*time.Millisecond, func() { 381 err := svr1.Stop() 382 test.Assert(t, err == nil, err) 383 }) 384 err := svr1.RegisterService(mocks.ServiceInfo(), mocks.MyServiceHandler()) 385 test.Assert(t, err == nil, err) 386 err = svr1.Run() 387 test.Assert(t, err == nil, err) 388 iSvr1 := svr1.(*server) 389 test.DeepEqual(t, iSvr1.opt.RemoteOpt.GRPCCfg.KeepaliveEnforcementPolicy, kep) 390 } 391 392 // TestGRPCKeepaliveParamsOption tests the creation of a server with RemoteOpt.GRPCCfg.KeepaliveParams option 393 func TestGRPCKeepaliveParamsOption(t *testing.T) { 394 randTimeDuration1 := time.Duration(rand.Int31n(100)+1) * time.Second 395 randTimeDuration2 := time.Duration(rand.Int31n(100)+1) * time.Second 396 randTimeDuration3 := time.Duration(rand.Int31n(100)+1) * time.Second 397 randTimeDuration4 := time.Duration(rand.Int31n(10)+1) * time.Hour 398 randTimeDuration5 := time.Duration(rand.Int31n(100)+1) * time.Second 399 400 kp := grpc.ServerKeepalive{ 401 MaxConnectionIdle: randTimeDuration1, 402 MaxConnectionAge: randTimeDuration2, 403 MaxConnectionAgeGrace: randTimeDuration3, 404 Time: randTimeDuration4, 405 Timeout: randTimeDuration5, 406 } 407 svr1 := NewServer( 408 WithGRPCKeepaliveParams(kp), 409 ) 410 411 time.AfterFunc(100*time.Millisecond, func() { 412 err := svr1.Stop() 413 test.Assert(t, err == nil, err) 414 }) 415 err := svr1.RegisterService(mocks.ServiceInfo(), mocks.MyServiceHandler()) 416 test.Assert(t, err == nil, err) 417 err = svr1.Run() 418 test.Assert(t, err == nil, err) 419 iSvr1 := svr1.(*server) 420 test.DeepEqual(t, iSvr1.opt.RemoteOpt.GRPCCfg.KeepaliveParams, kp) 421 } 422 423 func TestWithProfilerMessageTagging(t *testing.T) { 424 var msgTagging1 remote.MessageTagging = func(ctx context.Context, msg remote.Message) (context.Context, []string) { 425 return context.WithValue(ctx, "ctx1", 1), []string{"a", "1", "b", "1"} 426 } 427 var msgTagging2 remote.MessageTagging = func(ctx context.Context, msg remote.Message) (context.Context, []string) { 428 return context.WithValue(ctx, "ctx2", 2), []string{"b", "2", "c", "2"} 429 } 430 svr := NewServer(WithProfilerMessageTagging(msgTagging1), WithProfilerMessageTagging(msgTagging2)) 431 err := svr.RegisterService(mocks.ServiceInfo(), mocks.MyServiceHandler()) 432 test.Assert(t, err == nil, err) 433 time.AfterFunc(100*time.Millisecond, func() { 434 err := svr.Stop() 435 test.Assert(t, err == nil, err) 436 }) 437 err = svr.Run() 438 test.Assert(t, err == nil, err) 439 iSvr := svr.(*server) 440 from := rpcinfo.NewEndpointInfo("caller", "", nil, nil) 441 to := rpcinfo.NewEndpointInfo("callee", "method", nil, nil) 442 ri := rpcinfo.NewRPCInfo(from, to, nil, nil, nil) 443 ctx := rpcinfo.NewCtxWithRPCInfo(context.Background(), ri) 444 svcInfo := mocks.ServiceInfo() 445 svcSearchMap := map[string]*serviceinfo.ServiceInfo{ 446 remote.BuildMultiServiceKey(mocks.MockServiceName, mocks.MockMethod): svcInfo, 447 remote.BuildMultiServiceKey(mocks.MockServiceName, mocks.MockExceptionMethod): svcInfo, 448 remote.BuildMultiServiceKey(mocks.MockServiceName, mocks.MockErrorMethod): svcInfo, 449 remote.BuildMultiServiceKey(mocks.MockServiceName, mocks.MockOnewayMethod): svcInfo, 450 mocks.MockMethod: svcInfo, 451 mocks.MockExceptionMethod: svcInfo, 452 mocks.MockErrorMethod: svcInfo, 453 mocks.MockOnewayMethod: svcInfo, 454 } 455 msg := remote.NewMessageWithNewer(svcInfo, svcSearchMap, ri, remote.Call, remote.Server, false) 456 457 newCtx, tags := iSvr.opt.RemoteOpt.ProfilerMessageTagging(ctx, msg) 458 test.Assert(t, len(tags) == 8) 459 test.DeepEqual(t, tags, []string{"b", "2", "c", "2", "a", "1", "b", "1"}) 460 test.Assert(t, newCtx.Value("ctx1").(int) == 1) 461 test.Assert(t, newCtx.Value("ctx2").(int) == 2) 462 } 463 464 func TestRefuseTrafficWithoutServiceNamOption(t *testing.T) { 465 svr := NewServer(WithRefuseTrafficWithoutServiceName()) 466 err := svr.RegisterService(mocks.ServiceInfo(), mocks.MyServiceHandler()) 467 test.Assert(t, err == nil, err) 468 time.AfterFunc(100*time.Millisecond, func() { 469 err := svr.Stop() 470 test.Assert(t, err == nil, err) 471 }) 472 err = svr.Run() 473 test.Assert(t, err == nil, err) 474 iSvr := svr.(*server) 475 test.Assert(t, iSvr.opt.RefuseTrafficWithoutServiceName) 476 }