trpc.group/trpc-go/trpc-go@v1.0.3/config/config_test.go (about) 1 // 2 // 3 // Tencent is pleased to support the open source community by making tRPC available. 4 // 5 // Copyright (C) 2023 THL A29 Limited, a Tencent company. 6 // All rights reserved. 7 // 8 // If you have downloaded a copy of the tRPC source code from Tencent, 9 // please note that tRPC source code is licensed under the Apache 2.0 License, 10 // A copy of the Apache 2.0 License is included in this file. 11 // 12 // 13 14 package config_test 15 16 import ( 17 "bytes" 18 "context" 19 "encoding/json" 20 "fmt" 21 "sync" 22 "testing" 23 24 "github.com/stretchr/testify/assert" 25 "github.com/stretchr/testify/require" 26 27 "trpc.group/trpc-go/trpc-go/client" 28 "trpc.group/trpc-go/trpc-go/config" 29 30 trpc "trpc.group/trpc-go/trpc-go" 31 ) 32 33 type mockResponse struct { 34 val string 35 } 36 37 func (r *mockResponse) Value() string { 38 return r.val 39 } 40 41 func (r *mockResponse) MetaData() map[string]string { 42 return nil 43 } 44 45 func (r *mockResponse) Event() config.EventType { 46 return config.EventTypeNull 47 } 48 49 type mockKV struct { 50 mu sync.RWMutex 51 db map[string]string 52 } 53 54 // Put mocks putting key and value into kv storage. 55 func (kv *mockKV) Put(ctx context.Context, key, val string, opts ...config.Option) error { 56 kv.mu.Lock() 57 kv.db[key] = val 58 kv.mu.Unlock() 59 return nil 60 } 61 62 // Get mocks getting value from kv storage by key. 63 func (kv *mockKV) Get(ctx context.Context, key string, opts ...config.Option) (config.Response, error) { 64 kv.mu.RLock() 65 defer kv.mu.RUnlock() 66 if val, ok := kv.db[key]; ok { 67 v := &mockResponse{val: val} 68 return v, nil 69 } 70 71 return nil, fmt.Errorf("invalid key") 72 } 73 74 // Watch makes mockKV satisfy the KV interface, this method 75 // is empty. 76 func (kv *mockKV) Watch(ctx context.Context, key string, opts ...config.Option) (<-chan config.Response, error) { 77 return nil, nil 78 } 79 80 func (kv *mockKV) Name() string { 81 return "mock" 82 } 83 84 // Del makes mockKV satisfy the KV interface, this method 85 // is empty. 86 func (kv *mockKV) Del(ctx context.Context, key string, opts ...config.Option) error { 87 return nil 88 } 89 90 type mockValue struct { 91 Age int 92 Name string 93 } 94 95 func TestGlobalKV(t *testing.T) { 96 kv := config.GlobalKV() 97 98 mock := "foo" 99 100 err := kv.Put(context.Background(), "mockString", mock) 101 assert.Nil(t, err) 102 103 val, err := kv.Get(context.Background(), "mockString") 104 assert.NotNil(t, err) 105 assert.Nil(t, val) 106 107 err = kv.Del(context.Background(), "mockString") 108 assert.Nil(t, err) 109 110 config.SetGlobalKV(&mockKV{}) 111 assert.NotNil(t, config.GlobalKV()) 112 } 113 114 func TestGetConfigInfo(t *testing.T) { 115 c := &mockKV{ 116 db: make(map[string]string), 117 } 118 config.SetGlobalKV(c) 119 config.Register(c) 120 121 { 122 tmp := ` 123 age: 20 124 name: 'foo' 125 ` 126 err := c.Put(context.Background(), "mockYAMLKey", tmp) 127 assert.Nil(t, err) 128 129 v := &mockValue{} 130 err = config.GetYAML("mockYAMLKey", v) 131 assert.Nil(t, err) 132 assert.Equal(t, 20, v.Age) 133 assert.Equal(t, "foo", v.Name) 134 err = config.GetYAMLWithProvider("mockYAMLKey", v, "mock") 135 assert.Nil(t, err) 136 assert.Equal(t, 20, v.Age) 137 assert.Equal(t, "foo", v.Name) 138 err = config.GetYAMLWithProvider("mockYAMLKey", v, "mockNotExist") 139 assert.NotNil(t, err) 140 } 141 142 // Test GetJson 143 { 144 tmp := &mockValue{ 145 Age: 20, 146 Name: "foo", 147 } 148 tmpStr, err := json.Marshal(tmp) 149 assert.Nil(t, err) 150 err = c.Put(context.Background(), "mockJsonKey", string(tmpStr)) 151 assert.Nil(t, err) 152 153 v := &mockValue{} 154 err = config.GetJSON("mockJsonKey", v) 155 assert.Nil(t, err) 156 assert.Equal(t, 20, v.Age) 157 assert.Equal(t, "foo", v.Name) 158 err = config.GetJSONWithProvider("mockJsonKey", v, "mock") 159 assert.Nil(t, err) 160 assert.Equal(t, 20, v.Age) 161 assert.Equal(t, "foo", v.Name) 162 err = config.GetJSONWithProvider("mockJsonKey", v, "mockNotExist") 163 assert.NotNil(t, err) 164 165 codec := &config.JSONCodec{} 166 out := make(map[string]string) 167 codec.Unmarshal(tmpStr, &out) 168 } 169 170 // Test GetWithUnmarshal 171 { 172 173 v := &mockValue{} 174 err := config.GetWithUnmarshal("mockJsonKey1", v, "json") 175 assert.NotNil(t, err) 176 } 177 178 // Test GetToml 179 { 180 tmp := ` 181 age = 20 182 name = "foo" 183 ` 184 err := c.Put(context.Background(), "mockTomlKey", tmp) 185 assert.Nil(t, err) 186 187 v := &mockValue{} 188 err = config.GetTOML("mockTomlKey", v) 189 assert.Nil(t, err) 190 assert.Equal(t, 20, v.Age) 191 assert.Equal(t, "foo", v.Name) 192 err = config.GetTOMLWithProvider("mockTomlKey", v, "mock") 193 assert.Nil(t, err) 194 assert.Equal(t, 20, v.Age) 195 assert.Equal(t, "foo", v.Name) 196 err = config.GetTOMLWithProvider("mockTomlKey", v, "mockNotExist") 197 assert.NotNil(t, err) 198 } 199 200 // Test GetString 201 { 202 mock := "foo" 203 c.Put(context.Background(), "mockString", mock) 204 val, err := config.GetString("mockString") 205 assert.Nil(t, err) 206 assert.Equal(t, mock, val) 207 _, err = config.GetString("mockString1") 208 assert.NotNil(t, err) 209 } 210 { 211 mock := 1 212 c.Put(context.Background(), "mockInt", fmt.Sprint(mock)) 213 val, err := config.GetInt("mockInt") 214 assert.Nil(t, err) 215 assert.Equal(t, mock, val) 216 _, err = config.GetInt("mockInt1") 217 assert.NotNil(t, err) 218 } 219 220 // Test Get 221 { 222 c := config.Get("mock") 223 assert.NotNil(t, c) 224 } 225 } 226 227 // TestGetConfigGetDefault tests getting default value when 228 // key is absent. 229 func TestGetConfigGetDefault(t *testing.T) { 230 c := &mockKV{ 231 db: make(map[string]string), 232 } 233 config.SetGlobalKV(c) 234 config.Register(c) 235 236 // Test GetStringWithDefault 237 { 238 // get key successfully. 239 mock := "foo" 240 c.Put(context.Background(), "mockString", mock) 241 val := config.GetStringWithDefault("mockString", "otherValue") 242 assert.Equal(t, mock, val) 243 244 // key is absent, get default value. 245 def := "myDefaultValue" 246 val = config.GetStringWithDefault("whatever", def) 247 assert.Equal(t, val, def) 248 } 249 // Test GetIntWithDefault 250 { 251 // get key successfully. 252 mockint := 555 253 c.Put(context.Background(), "mockInt", fmt.Sprint(mockint)) 254 val := config.GetIntWithDefault("mockInt", 123) 255 assert.Equal(t, mockint, val) 256 257 // key is absent, get default value. 258 def := 888 259 val = config.GetIntWithDefault("whatever", def) 260 assert.Equal(t, val, def) 261 262 // key exists, but fail to transfers to target type, 263 // get default value. 264 mockstr := "foo" 265 c.Put(context.Background(), "whatever", mockstr) 266 val = config.GetIntWithDefault("whatever", def) 267 assert.Equal(t, val, def) 268 } 269 } 270 271 func TestLoadYaml(t *testing.T) { 272 require := require.New(t) 273 err := config.Reload("../testdata/trpc_go.yaml", config.WithCodec("yaml")) 274 require.NotNil(err) 275 276 _, err = config.Load("../testdata/trpc_go.yaml.1", config.WithCodec("yaml")) 277 require.NotNil(err) 278 279 c, err := config.Load("../testdata/trpc_go.yaml", config.WithCodec("yaml")) 280 require.Nil(err, "failed to load config") 281 // out := &T{} 282 out := c.GetString("server.app", "") 283 t.Logf("return %+v", out) 284 require.Equal(out, "test", "app name is wrong") 285 286 buf := c.Bytes() 287 require.NotNil(buf) 288 bytes.Contains(buf, []byte("test")) 289 290 err = config.Reload("../testdata/trpc_go.yaml") 291 require.Nil(err) 292 293 require.Implements((*config.Config)(nil), c) 294 } 295 296 func TestLoadToml(t *testing.T) { 297 require := require.New(t) 298 rightPath := "../testdata/custom.toml" 299 wrongPath := "../testdata/custom.toml.1" 300 301 err := config.Reload(rightPath, config.WithCodec("toml")) 302 require.NotNil(err) 303 304 _, err = config.Load(wrongPath, config.WithCodec("toml")) 305 require.NotNil(err, "path not exist") 306 t.Logf("load with not exist path, err:%v", err) 307 308 c, err := config.Load(rightPath, config.WithCodec("toml")) 309 require.Nil(err, "failed to load config") 310 // out := &T{} 311 out := c.GetString("server.app", "") 312 t.Logf("return %s", out) 313 require.Equal(out, "test", "app name is wrong") 314 315 buf := c.Bytes() 316 require.NotNil(buf) 317 bytes.Contains(buf, []byte("test")) 318 319 obj := struct { 320 Server struct { 321 App string 322 P int `toml:"port"` 323 Protocol []string 324 } 325 }{} 326 327 err = c.Unmarshal(&obj) 328 require.Nil(err, "unmarshal should succ") 329 t.Logf("unmarshal struct:%+v", obj) 330 require.Equal(obj.Server.P, 1000) 331 require.Equal(len(obj.Server.Protocol), 2) 332 333 err = config.Reload("../testdata/custom.toml", config.WithCodec("toml")) 334 require.Nil(err) 335 336 require.Implements((*config.Config)(nil), c) 337 } 338 339 func TestLoadUnmarshal(t *testing.T) { 340 require := require.New(t) 341 config, err := config.Load("../testdata/trpc_go.yaml", config.WithCodec("yaml")) 342 require.Nil(err, "failed to load config") 343 344 out := &trpc.Config{} 345 err = config.Unmarshal(out) 346 347 require.Nil(err, "failed to load config") 348 t.Logf("return %+v", *out) 349 } 350 351 func TestLoadUnmarshalClient(t *testing.T) { 352 require := require.New(t) 353 config, err := config.Load("../testdata/client.yaml", config.WithCodec("yaml")) 354 require.Nil(err, "failed to load config") 355 356 out := client.DefaultClientConfig() 357 err = config.Unmarshal(&out) 358 t.Logf("return %+v %s", out["Test.HelloServer"], err) 359 require.Nil(err, "failed to load client config") 360 } 361 362 func TestGetString(t *testing.T) { 363 require := require.New(t) 364 c, err := config.Load("../testdata/trpc_go.yaml", config.WithCodec("yaml")) 365 require.Nil(err, "failed to load config") 366 367 out := c.GetString("server.app", "cc") 368 t.Logf("return %+v", out) 369 require.Equal("test", out, "app name is wrong") 370 371 out = c.GetString("server.app1", "cc") 372 t.Logf("return %+v", out) 373 require.Equal("cc", out, "app name is wrong") 374 375 out = c.GetString("server.admin.port", "cc") 376 t.Logf("return %+v", out) 377 require.Equal("9528", out, "app name is wrong") 378 379 out = c.GetString("server.admin", "cc") 380 t.Logf("return %+v", out) 381 require.Equal("cc", out, "app name is wrong") 382 } 383 384 func TestGetBool(t *testing.T) { 385 require := require.New(t) 386 c, err := config.Load("../testdata/trpc_go.yaml", config.WithCodec("yaml")) 387 require.Nil(err, "failed to load config") 388 389 out := c.GetBool("server.admin_port123", false) 390 t.Logf("return %+v", out) 391 require.Equal(false, out) 392 393 out = c.GetBool("server.app", false) 394 t.Logf("return %+v", out) 395 require.Equal(false, out) 396 } 397 398 func TestGet(t *testing.T) { 399 require := require.New(t) 400 c, err := config.Load("../testdata/trpc_go.yaml", config.WithCodec("yaml")) 401 require.Nil(err, "failed to load config") 402 403 out := c.Get("server.admin_port123", 10001) 404 t.Logf("return %+v", out) 405 require.Equal(10001, out) 406 } 407 408 func TestGetUint(t *testing.T) { 409 require := require.New(t) 410 c, err := config.Load("../testdata/trpc_go.yaml", config.WithCodec("yaml")) 411 require.Nil(err, "failed to load config") 412 413 { 414 actual := uint(9528) 415 dft := uint(10001) 416 417 out := c.GetUint("server.admin.port", dft) 418 t.Logf("return %+v", out) 419 require.Equal(actual, out) 420 421 out = c.GetUint("server.admin_port123", dft) 422 t.Logf("return %+v", out) 423 require.Equal(dft, out) 424 425 out = c.GetUint("server.app", dft) 426 t.Logf("return %+v", out) 427 require.Equal(dft, out) 428 } 429 430 { 431 actual := uint32(9528) 432 dft := uint32(10001) 433 434 out := c.GetUint32("server.admin.port", dft) 435 t.Logf("return %+v", out) 436 require.Equal(actual, out) 437 438 out = c.GetUint32("server.admin_port123", dft) 439 t.Logf("return %+v", out) 440 require.Equal(dft, out) 441 442 out = c.GetUint32("server.app", dft) 443 t.Logf("return %+v", out) 444 require.Equal(dft, out) 445 } 446 447 { 448 actual := uint64(9528) 449 dft := uint64(10001) 450 451 out := c.GetUint64("server.admin.port", dft) 452 t.Logf("return %+v", out) 453 require.Equal(actual, out) 454 455 out = c.GetUint64("server.admin_port123", dft) 456 t.Logf("return %+v", out) 457 require.Equal(dft, out) 458 459 out = c.GetUint64("server.app", dft) 460 t.Logf("return %+v", out) 461 require.Equal(dft, out) 462 } 463 464 } 465 466 func TestGetInt(t *testing.T) { 467 require := require.New(t) 468 c, err := config.Load("../testdata/trpc_go.yaml", config.WithCodec("yaml")) 469 require.Nil(err, "failed to load config") 470 471 { 472 actual := 9528 473 dft := 10001 474 475 out := c.GetInt("server.admin.port", dft) 476 t.Logf("return %+v", out) 477 require.Equal(actual, out) 478 479 out = c.GetInt("server.admin_port123", dft) 480 t.Logf("return %+v", out) 481 require.Equal(dft, out) 482 483 out = c.GetInt("server.app", dft) 484 t.Logf("return %+v", out) 485 require.Equal(dft, out) 486 } 487 488 { 489 actual := int32(9528) 490 dft := int32(10001) 491 492 out := c.GetInt32("server.admin.port", dft) 493 t.Logf("return %+v", out) 494 require.Equal(actual, out) 495 496 out = c.GetInt32("server.admin_port123", dft) 497 t.Logf("return %+v", out) 498 require.Equal(dft, out) 499 500 out = c.GetInt32("server.app", dft) 501 t.Logf("return %+v", out) 502 require.Equal(dft, out) 503 } 504 505 { 506 actual := int64(9528) 507 dft := int64(10001) 508 509 out := c.GetInt64("server.admin.port", dft) 510 t.Logf("return %+v", out) 511 require.Equal(actual, out) 512 513 out = c.GetInt64("server.admin_port123", dft) 514 t.Logf("return %+v", out) 515 require.Equal(dft, out) 516 517 out = c.GetInt64("server.app", dft) 518 t.Logf("return %+v", out) 519 require.Equal(dft, out) 520 } 521 522 } 523 524 func TestGetFloat(t *testing.T) { 525 require := require.New(t) 526 c, err := config.Load("../testdata/trpc_go.yaml", config.WithCodec("yaml")) 527 require.Nil(err, "failed to load config") 528 529 { 530 actual := float64(9528) 531 dft := float64(1.0) 532 533 out := c.GetFloat64("server.admin.port", dft) 534 t.Logf("return %+v", out) 535 require.Equal(actual, out) 536 537 out = c.GetFloat64("server.admin_port123", dft) 538 t.Logf("return %+v", out) 539 require.Equal(dft, out) 540 541 out = c.GetFloat64("server.app", dft) 542 t.Logf("return %+v", out) 543 require.Equal(dft, out) 544 545 } 546 547 { 548 actual := float32(9528) 549 dft := float32(1.0) 550 551 out := c.GetFloat32("server.admin.port", dft) 552 t.Logf("return %+v", out) 553 require.Equal(actual, out) 554 555 out = c.GetFloat32("server.admin_port123", dft) 556 t.Logf("return %+v", out) 557 require.Equal(dft, out) 558 559 out = c.GetFloat32("server.app", dft) 560 t.Logf("return %+v", out) 561 require.Equal(dft, out) 562 563 } 564 } 565 566 func TestIsSet(t *testing.T) { 567 require := require.New(t) 568 c, err := config.Load("../testdata/trpc_go.yaml", config.WithCodec("yaml")) 569 require.Nil(err, "failed to load config") 570 571 out := c.IsSet("server.admin.port") 572 require.Equal(true, out) 573 out = c.IsSet("server.admin_port1") 574 require.Equal(false, out) 575 } 576 577 func TestUnmarshal(t *testing.T) { 578 require := require.New(t) 579 c, err := config.Load("../testdata/trpc_go.yaml", config.WithCodec("yaml"), config.WithProvider("file")) 580 require.Nil(err, "failed to load config") 581 var b struct { 582 Server struct { 583 App string 584 } 585 } 586 err = c.Unmarshal(&b) 587 require.Nil(err) 588 require.Equal("test", b.Server.App, "failed to read item") 589 } 590 591 func TestLoad(t *testing.T) { 592 c, err := config.Load("../testdata/trpc_go.yaml2", config.WithCodec("yaml"), config.WithProvider("file")) 593 assert.NotNil(t, err) 594 assert.Nil(t, c) 595 596 c, err = config.Load("../testdata/trpc_go.yaml", config.WithCodec("yaml1")) 597 assert.NotNil(t, err) 598 assert.Nil(t, c) 599 600 c, err = config.Load("../testdata/trpc_go.yaml", config.WithProvider("etcd")) 601 assert.NotNil(t, err) 602 assert.Nil(t, c) 603 } 604 605 func TestProvider(t *testing.T) { 606 require := require.New(t) 607 p := &config.FileProvider{} 608 require.Equal("file", p.Name()) 609 config.RegisterProvider(p) 610 pp := config.GetProvider("file") 611 require.Equal(p, pp) 612 }