github.com/unionj-cloud/go-doudou@v1.3.8-0.20221011095552-0088008e5b31/framework/registry/node_test.go (about) 1 package registry 2 3 import ( 4 "github.com/apolloconfig/agollo/v4" 5 "github.com/apolloconfig/agollo/v4/agcache/memory" 6 apolloConfig "github.com/apolloconfig/agollo/v4/env/config" 7 "github.com/apolloconfig/agollo/v4/storage" 8 "github.com/golang/mock/gomock" 9 "github.com/pkg/errors" 10 . "github.com/smartystreets/goconvey/convey" 11 "github.com/stretchr/testify/require" 12 "github.com/unionj-cloud/go-doudou/framework/buildinfo" 13 "github.com/unionj-cloud/go-doudou/framework/configmgr" 14 "github.com/unionj-cloud/go-doudou/framework/configmgr/mock" 15 "github.com/unionj-cloud/go-doudou/framework/internal/config" 16 "github.com/unionj-cloud/go-doudou/framework/memberlist" 17 memmock "github.com/unionj-cloud/go-doudou/framework/memberlist/mock" 18 "github.com/unionj-cloud/go-doudou/framework/registry/nacos" 19 nmock "github.com/unionj-cloud/go-doudou/framework/registry/nacos/mock" 20 "github.com/unionj-cloud/go-doudou/toolkit/maputils" 21 "github.com/wubin1989/nacos-sdk-go/clients/cache" 22 "github.com/wubin1989/nacos-sdk-go/clients/config_client" 23 "github.com/wubin1989/nacos-sdk-go/clients/naming_client" 24 "github.com/wubin1989/nacos-sdk-go/vo" 25 "os" 26 "reflect" 27 "testing" 28 "time" 29 ) 30 31 func setup() { 32 _ = config.GddMemSeed.Write("") 33 _ = config.GddServiceName.Write("seed") 34 _ = config.GddMemName.Write("seed") 35 _ = config.GddMemPort.Write("56199") 36 _ = config.GddMemWeight.Write("8") 37 _ = config.GddMemDeadTimeout.Write("8s") 38 _ = config.GddMemSyncInterval.Write("8s") 39 _ = config.GddMemReclaimTimeout.Write("8s") 40 _ = config.GddMemProbeInterval.Write("8s") 41 _ = config.GddMemProbeTimeout.Write("8s") 42 _ = config.GddMemSuspicionMult.Write("8") 43 _ = config.GddMemGossipNodes.Write("8") 44 _ = config.GddMemGossipInterval.Write("8s") 45 _ = config.GddMemWeightInterval.Write("8s") 46 _ = config.GddMemTCPTimeout.Write("8s") 47 _ = config.GddMemHost.Write("seed.seed-svc-headless.default.svc.cluster.local") 48 _ = config.GddMemIndirectChecks.Write("8") 49 _ = config.GddLogLevel.Write("debug") 50 _ = config.GddPort.Write("8088") 51 _ = config.GddRouteRootPath.Write("/v1") 52 _ = config.GddApolloAddr.Write("http://apollo-config-dev-svc:8080") 53 _ = config.GddNacosServerAddr.Write("http://localhost:8848") 54 } 55 56 func Test_seeds(t *testing.T) { 57 type args struct { 58 seedstr string 59 } 60 tests := []struct { 61 name string 62 args args 63 want []string 64 }{ 65 { 66 name: "", 67 args: args{ 68 seedstr: "seed-01,seed-02,seed-03", 69 }, 70 want: []string{"seed-01:7946", "seed-02:7946", "seed-03:7946"}, 71 }, 72 { 73 name: "", 74 args: args{ 75 seedstr: "", 76 }, 77 want: nil, 78 }, 79 { 80 name: "", 81 args: args{ 82 seedstr: "seed-01:56199,seed-02,seed-03:03,seed-04:abc", 83 }, 84 want: []string{"seed-01:56199", "seed-02:7946", "seed-03:3", "seed-04:7946"}, 85 }, 86 } 87 for _, tt := range tests { 88 t.Run(tt.name, func(t *testing.T) { 89 if got := seeds(tt.args.seedstr); !reflect.DeepEqual(got, tt.want) { 90 t.Errorf("seeds() = %v, want %v", got, tt.want) 91 } 92 }) 93 } 94 } 95 96 func Test_join_fail(t *testing.T) { 97 setup() 98 err := NewNode() 99 if err != nil { 100 panic(err) 101 } 102 defer Shutdown() 103 _ = config.GddMemSeed.Write("not exist seed") 104 _ = config.GddServiceName.Write("testsvc") 105 require.Error(t, join()) 106 } 107 108 func TestAllNodes(t *testing.T) { 109 setup() 110 err := NewNode() 111 if err != nil { 112 panic(err) 113 } 114 defer Shutdown() 115 Convey("There should be only one node", t, func() { 116 nodes, _ := AllNodes() 117 So(len(nodes), ShouldEqual, 1) 118 }) 119 } 120 121 func TestAllNodesError(t *testing.T) { 122 Convey("There should be only one node", t, func() { 123 _, err := AllNodes() 124 So(err.Error(), ShouldEqual, "mlist is nil") 125 }) 126 } 127 128 func TestInfo(t *testing.T) { 129 setup() 130 err := NewNode() 131 if err != nil { 132 panic(err) 133 } 134 defer Shutdown() 135 Convey("Should not zero value", t, func() { 136 info := Info(LocalNode()) 137 So(info, ShouldNotBeZeroValue) 138 }) 139 } 140 141 func TestMetaWeight(t *testing.T) { 142 setup() 143 err := NewNode() 144 if err != nil { 145 panic(err) 146 } 147 defer Shutdown() 148 Convey("Should not zero value", t, func() { 149 weight, _ := MetaWeight(LocalNode()) 150 So(weight, ShouldNotBeZeroValue) 151 }) 152 } 153 154 func TestSvcName(t *testing.T) { 155 setup() 156 err := NewNode() 157 if err != nil { 158 panic(err) 159 } 160 defer Shutdown() 161 Convey("Should be equal to seed", t, func() { 162 So(SvcName(LocalNode()), ShouldEqual, "seed") 163 }) 164 } 165 166 func TestRegisterServiceProvider(t *testing.T) { 167 setup() 168 err := NewNode() 169 if err != nil { 170 panic(err) 171 } 172 defer Shutdown() 173 Convey("", t, func() { 174 provider := newMockServiceProvider("TEST") 175 RegisterServiceProvider(provider) 176 So(len(events.ServiceProviders), ShouldEqual, 1) 177 So(len(provider.servers), ShouldEqual, 1) 178 }) 179 } 180 181 func Test_memConfigListener_OnChange(t *testing.T) { 182 Convey("Test OnChange callback", t, func() { 183 c := &memConfigListener{ 184 memConf: &memberlist.Config{}, 185 } 186 c.OnChange(&storage.ChangeEvent{ 187 Changes: map[string]*storage.ConfigChange{ 188 "gdd.mem.dead.timeout": { 189 OldValue: "60s", 190 NewValue: "30s", 191 ChangeType: storage.MODIFIED, 192 }, 193 }, 194 }) 195 Convey("Should equal to 8s", func() { 196 So(os.Getenv("GDD_MEM_DEAD_TIMEOUT"), ShouldEqual, "8s") 197 }) 198 199 c.OnChange(&storage.ChangeEvent{ 200 Changes: map[string]*storage.ConfigChange{ 201 "gdd.mem.dead.timeout": { 202 OldValue: "8s", 203 NewValue: "30s", 204 ChangeType: storage.MODIFIED, 205 }, 206 }, 207 }) 208 Convey("Should equal to 30s", func() { 209 So(os.Getenv("GDD_MEM_DEAD_TIMEOUT"), ShouldEqual, "30s") 210 So(c.memConf.GossipToTheDeadTime, ShouldEqual, 30*time.Second) 211 }) 212 213 c.OnChange(&storage.ChangeEvent{ 214 Changes: map[string]*storage.ConfigChange{ 215 "gdd.mem.dead.timeout": { 216 OldValue: "30s", 217 NewValue: "", 218 ChangeType: storage.DELETED, 219 }, 220 }, 221 }) 222 Convey("Should equal to 60s", func() { 223 So(os.Getenv("GDD_MEM_DEAD_TIMEOUT"), ShouldEqual, "") 224 So(c.memConf.GossipToTheDeadTime, ShouldEqual, 60*time.Second) 225 }) 226 227 }) 228 } 229 230 func TestNewNode_NacosConfigType(t *testing.T) { 231 Convey("Should not have error", t, func() { 232 setup() 233 _ = config.GddConfigRemoteType.Write("nacos") 234 ctrl := gomock.NewController(t) 235 defer ctrl.Finish() 236 dataId := ".env" 237 configClient := mock.NewMockIConfigClient(ctrl) 238 configClient. 239 EXPECT(). 240 GetConfig(vo.ConfigParam{ 241 DataId: dataId, 242 Group: config.DefaultGddNacosConfigGroup, 243 }). 244 AnyTimes(). 245 Return("GDD_READ_TIMEOUT=60s\nGDD_WRITE_TIMEOUT=60s\nGDD_IDLE_TIMEOUT=120s", nil) 246 247 configClient. 248 EXPECT(). 249 ListenConfig(gomock.Any()). 250 AnyTimes(). 251 Return(nil) 252 253 configmgr.NewConfigClient = func(param vo.NacosClientParam) (iClient config_client.IConfigClient, err error) { 254 return configClient, nil 255 } 256 257 if configmgr.NacosClient != nil { 258 configmgr.NacosClient = configmgr.NewNacosConfigMgr([]string{dataId}, 259 config.DefaultGddNacosConfigGroup, configmgr.DotenvConfigFormat, config.DefaultGddNacosNamespaceId, configClient, cache.NewConcurrentMap()) 260 } 261 262 err := configmgr.LoadFromNacos(config.GetNacosClientParam(), dataId, string(config.DefaultGddNacosConfigFormat), config.DefaultGddNacosConfigGroup) 263 So(err, ShouldBeNil) 264 So(NewNode(), ShouldBeNil) 265 defer Shutdown() 266 }) 267 } 268 269 func TestNewNode_ApolloConfigType(t *testing.T) { 270 Convey("Should not have error", t, func() { 271 setup() 272 _ = config.GddConfigRemoteType.Write("apollo") 273 ctrl := gomock.NewController(t) 274 defer ctrl.Finish() 275 configClient := mock.NewMockClient(ctrl) 276 factory := &memory.DefaultCacheFactory{} 277 cache := factory.Create() 278 cache.Set("gdd.retry.count", "3", 0) 279 cache.Set("gdd.weight", "5", 0) 280 configClient. 281 EXPECT(). 282 GetConfigCache(config.DefaultGddApolloNamespace). 283 AnyTimes(). 284 Return(cache) 285 286 configClient. 287 EXPECT(). 288 AddChangeListener(gomock.Any()). 289 AnyTimes(). 290 Return() 291 292 configmgr.StartWithConfig = func(loadAppConfig func() (*apolloConfig.AppConfig, error)) (agollo.Client, error) { 293 _, _ = loadAppConfig() 294 return configClient, nil 295 } 296 297 if configmgr.ApolloClient != nil { 298 configmgr.ApolloClient = configClient 299 } 300 301 apolloCluster := config.DefaultGddApolloCluster 302 apolloAddr := config.GddApolloAddr.Load() 303 apolloNamespace := config.DefaultGddApolloNamespace 304 apolloBackupPath := config.DefaultGddApolloBackupPath 305 c := &apolloConfig.AppConfig{ 306 AppID: config.GddServiceName.Load(), 307 Cluster: apolloCluster, 308 IP: apolloAddr, 309 NamespaceName: apolloNamespace, 310 IsBackupConfig: false, 311 BackupConfigPath: apolloBackupPath, 312 MustStart: false, 313 } 314 So(func() { 315 configmgr.LoadFromApollo(c) 316 }, ShouldNotPanic) 317 318 So(NewNode(), ShouldBeNil) 319 defer Shutdown() 320 }) 321 } 322 323 func TestNewNode_InvalidConfigType(t *testing.T) { 324 Convey("Should panic", t, func() { 325 setup() 326 _ = config.GddConfigRemoteType.Write("invalid") 327 defer Shutdown() 328 So(func() { 329 NewNode() 330 }, ShouldPanic) 331 }) 332 } 333 334 func TestNewNode_Nacos(t *testing.T) { 335 Convey("Should return nil", t, func() { 336 setup() 337 _ = config.GddServiceDiscoveryMode.Write("nacos") 338 ctrl := gomock.NewController(t) 339 defer ctrl.Finish() 340 defer Shutdown() 341 342 namingClient := nmock.NewMockINamingClient(ctrl) 343 namingClient. 344 EXPECT(). 345 RegisterInstance(gomock.Any()). 346 AnyTimes(). 347 Return(true, nil) 348 349 namingClient. 350 EXPECT(). 351 DeregisterInstance(gomock.Any()). 352 AnyTimes(). 353 Return(true, nil) 354 355 nacos.NewNamingClient = func(param vo.NacosClientParam) (iClient naming_client.INamingClient, err error) { 356 return namingClient, nil 357 } 358 359 if nacos.NamingClient == nil { 360 nacos.NamingClient = namingClient 361 } 362 363 So(NewNode(), ShouldBeNil) 364 }) 365 } 366 367 func TestNewNode_InvalidServiceDiscoveryMode(t *testing.T) { 368 Convey("Should return nil", t, func() { 369 setup() 370 _ = config.GddServiceDiscoveryMode.Write("invalid") 371 So(NewNode(), ShouldBeNil) 372 }) 373 } 374 375 func TestCallbackOnChange(t *testing.T) { 376 Convey("Should equal to 30s", t, func() { 377 listener := &memConfigListener{ 378 memConf: &memberlist.Config{}, 379 } 380 CallbackOnChange(listener)(&configmgr.NacosChangeEvent{ 381 Namespace: config.DefaultGddNacosNamespaceId, 382 Group: config.DefaultGddNacosConfigGroup, 383 DataId: ".env", 384 Changes: map[string]maputils.Change{ 385 "gdd.mem.dead.timeout": { 386 OldValue: "8s", 387 NewValue: "30s", 388 ChangeType: maputils.MODIFIED, 389 }, 390 }, 391 }) 392 CallbackOnChange(listener)(&configmgr.NacosChangeEvent{ 393 Namespace: config.DefaultGddNacosNamespaceId, 394 Group: config.DefaultGddNacosConfigGroup, 395 DataId: ".env", 396 Changes: map[string]maputils.Change{ 397 "gdd.mem.dead.timeout": { 398 OldValue: "8s", 399 NewValue: "30s", 400 ChangeType: maputils.MODIFIED, 401 }, 402 }, 403 }) 404 So(os.Getenv("GDD_MEM_DEAD_TIMEOUT"), ShouldEqual, "30s") 405 So(listener.memConf.GossipToTheDeadTime, ShouldEqual, 30*time.Second) 406 }) 407 } 408 409 func Test_join_fail1(t *testing.T) { 410 mlist = nil 411 require.Error(t, join()) 412 } 413 414 func Test_join(t *testing.T) { 415 Convey("Join should be successful", t, func() { 416 ctrl := gomock.NewController(t) 417 defer ctrl.Finish() 418 mem := memmock.NewMockIMemberlist(ctrl) 419 mlist = mem 420 seedAddr := "seed:7946" 421 config.GddMemSeed.Write(seedAddr) 422 mem. 423 EXPECT(). 424 Join([]string{seedAddr}). 425 AnyTimes(). 426 Return(0, nil) 427 428 mem. 429 EXPECT(). 430 LocalNode(). 431 AnyTimes(). 432 Return(&memberlist.Node{ 433 Name: "", 434 Addr: "test", 435 Port: 7946, 436 }) 437 438 So(join(), ShouldBeNil) 439 }) 440 } 441 442 func Test_newMeta(t *testing.T) { 443 Convey("Should panic", t, func() { 444 So(func() { 445 newMeta(&memberlist.Node{ 446 Meta: []byte("fake meta"), 447 }) 448 }, ShouldPanic) 449 }) 450 } 451 452 func Test_newConf_GddMemCIDRsAllowed(t *testing.T) { 453 config.GddMemCIDRsAllowed.Write("172.28.0.0/16") 454 newConf() 455 } 456 457 func Test_newConf_GddMemCIDRsAllowed_error(t *testing.T) { 458 config.GddMemCIDRsAllowed.Write("invalid") 459 newConf() 460 } 461 462 func Test_newConf(t *testing.T) { 463 defer os.Clearenv() 464 config.GddLogLevel.Write("ERROR") 465 newConf() 466 467 config.GddLogLevel.Write("WARNING") 468 newConf() 469 470 config.GddMemLogDisable.Write("true") 471 newConf() 472 473 config.GddWeight.Write("5") 474 newConf() 475 476 config.GddWeight.Write("0") 477 newConf() 478 479 config.GddWeight.Write("0") 480 config.GddMemWeightInterval.Write("200") 481 newConf() 482 483 config.GddMemTCPTimeout.Write("10") 484 newConf() 485 486 config.GddMemHost.Write(".seed-headless") 487 newConf() 488 } 489 490 func Test_newNode(t *testing.T) { 491 Convey("Test newNode", t, func() { 492 Convey("Should return error as service name not set", func() { 493 So(newNode().Error(), ShouldEqual, "NewNode() error: No env variable GDD_SERVICE_NAME found") 494 }) 495 496 Convey("Should return error as join failed", func() { 497 setup() 498 buildinfo.BuildTime = "Mon Jan 2 15:04:05 MST 2006" 499 config.GddWeight.Write("8") 500 config.GddMemSeed.Write("invalid seed") 501 502 Convey("Should return error as join failed", func() { 503 So(newNode(map[string]interface{}{ 504 "foo": "bar", 505 }), ShouldNotBeNil) 506 }) 507 508 Convey("Should return error as memberlist create failed", func() { 509 defer func() { 510 createMemberlist = memberlist.Create 511 }() 512 createMemberlist = func(conf *memberlist.Config) (*memberlist.Memberlist, error) { 513 return nil, errors.New("mock test error") 514 } 515 So(newNode(), ShouldNotBeNil) 516 }) 517 }) 518 519 Convey("Should return nil", func() { 520 setup() 521 So(newNode(), ShouldBeNil) 522 So(numNodes(), ShouldEqual, 1) 523 So(retransmitMultGetter(), ShouldEqual, 4) 524 }) 525 }) 526 } 527 528 func Test_numNodes(t *testing.T) { 529 Convey("Should return 0", t, func() { 530 mlist = nil 531 So(numNodes(), ShouldEqual, 0) 532 }) 533 } 534 535 func TestShutdown(t *testing.T) { 536 config.GddServiceDiscoveryMode.Write("invalid") 537 Shutdown() 538 } 539 540 func TestLeave(t *testing.T) { 541 Convey("Should leave", t, func() { 542 ctrl := gomock.NewController(t) 543 defer ctrl.Finish() 544 mem := memmock.NewMockIMemberlist(ctrl) 545 mlist = mem 546 mem. 547 EXPECT(). 548 Leave(10 * time.Second). 549 AnyTimes(). 550 Return(nil) 551 552 Leave(10 * time.Second) 553 }) 554 }