p2c_test.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. package p2c
  2. import (
  3. "context"
  4. "fmt"
  5. "runtime"
  6. "strconv"
  7. "sync"
  8. "testing"
  9. "github.com/stretchr/testify/assert"
  10. "github.com/tal-tech/go-zero/core/logx"
  11. "github.com/tal-tech/go-zero/core/mathx"
  12. "google.golang.org/grpc/balancer"
  13. "google.golang.org/grpc/balancer/base"
  14. "google.golang.org/grpc/codes"
  15. "google.golang.org/grpc/resolver"
  16. "google.golang.org/grpc/status"
  17. )
  18. func init() {
  19. logx.Disable()
  20. }
  21. func TestP2cPicker_PickNil(t *testing.T) {
  22. builder := new(p2cPickerBuilder)
  23. picker := builder.Build(base.PickerBuildInfo{})
  24. _, err := picker.Pick(balancer.PickInfo{
  25. FullMethodName: "/",
  26. Ctx: context.Background(),
  27. })
  28. assert.NotNil(t, err)
  29. }
  30. func TestP2cPicker_Pick(t *testing.T) {
  31. tests := []struct {
  32. name string
  33. candidates int
  34. threshold float64
  35. }{
  36. {
  37. name: "single",
  38. candidates: 1,
  39. threshold: 0.9,
  40. },
  41. {
  42. name: "two",
  43. candidates: 2,
  44. threshold: 0.5,
  45. },
  46. {
  47. name: "multiple",
  48. candidates: 100,
  49. threshold: 0.95,
  50. },
  51. }
  52. for _, test := range tests {
  53. test := test
  54. t.Run(test.name, func(t *testing.T) {
  55. t.Parallel()
  56. const total = 10000
  57. builder := new(p2cPickerBuilder)
  58. ready := make(map[balancer.SubConn]base.SubConnInfo)
  59. for i := 0; i < test.candidates; i++ {
  60. ready[new(mockClientConn)] = base.SubConnInfo{
  61. Address: resolver.Address{
  62. Addr: strconv.Itoa(i),
  63. },
  64. }
  65. }
  66. picker := builder.Build(base.PickerBuildInfo{
  67. ReadySCs: ready,
  68. })
  69. var wg sync.WaitGroup
  70. wg.Add(total)
  71. for i := 0; i < total; i++ {
  72. result, err := picker.Pick(balancer.PickInfo{
  73. FullMethodName: "/",
  74. Ctx: context.Background(),
  75. })
  76. assert.Nil(t, err)
  77. if i%100 == 0 {
  78. err = status.Error(codes.DeadlineExceeded, "deadline")
  79. }
  80. go func() {
  81. runtime.Gosched()
  82. result.Done(balancer.DoneInfo{
  83. Err: err,
  84. })
  85. wg.Done()
  86. }()
  87. }
  88. wg.Wait()
  89. dist := make(map[interface{}]int)
  90. conns := picker.(*p2cPicker).conns
  91. for _, conn := range conns {
  92. dist[conn.addr.Addr] = int(conn.requests)
  93. }
  94. entropy := mathx.CalcEntropy(dist)
  95. assert.True(t, entropy > test.threshold, fmt.Sprintf("entropy is %f, less than %f",
  96. entropy, test.threshold))
  97. })
  98. }
  99. }
  100. type mockClientConn struct{}
  101. func (m mockClientConn) UpdateAddresses(addresses []resolver.Address) {
  102. }
  103. func (m mockClientConn) Connect() {
  104. }