options_test.go 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. package retry
  2. import (
  3. "context"
  4. "errors"
  5. "testing"
  6. "time"
  7. "github.com/stretchr/testify/assert"
  8. "github.com/tal-tech/go-zero/core/logx"
  9. "google.golang.org/grpc"
  10. "google.golang.org/grpc/codes"
  11. "google.golang.org/grpc/metadata"
  12. "google.golang.org/grpc/status"
  13. )
  14. func TestRetryWithDisable(t *testing.T) {
  15. opt := &options{}
  16. assert.EqualValues(t, &options{}, parseRetryCallOptions(opt, WithDisable()))
  17. }
  18. func TestRetryWithMax(t *testing.T) {
  19. n := 5
  20. for i := 0; i < n; i++ {
  21. opt := &options{}
  22. assert.EqualValues(t, &options{max: i}, parseRetryCallOptions(opt, WithMax(i)))
  23. }
  24. }
  25. func TestRetryWithBackoff(t *testing.T) {
  26. opt := &options{}
  27. retryCallOptions := parseRetryCallOptions(opt, WithBackoff(func(attempt int) time.Duration {
  28. return time.Millisecond
  29. }))
  30. assert.EqualValues(t, time.Millisecond, retryCallOptions.backoffFunc(1))
  31. }
  32. func TestRetryWithCodes(t *testing.T) {
  33. opt := &options{}
  34. c := []codes.Code{codes.Unknown, codes.NotFound}
  35. options := parseRetryCallOptions(opt, WithCodes(c...))
  36. assert.EqualValues(t, c, options.codes)
  37. }
  38. func TestRetryWithPerRetryTimeout(t *testing.T) {
  39. opt := &options{}
  40. options := parseRetryCallOptions(opt, WithPerRetryTimeout(time.Millisecond))
  41. assert.EqualValues(t, time.Millisecond, options.perCallTimeout)
  42. }
  43. func Test_waitRetryBackoff(t *testing.T) {
  44. opt := &options{perCallTimeout: time.Second, backoffFunc: func(attempt int) time.Duration {
  45. return time.Second
  46. }}
  47. logger := logx.WithContext(context.Background())
  48. err := waitRetryBackoff(logger, 1, context.Background(), opt)
  49. assert.NoError(t, err)
  50. ctx, cancelFunc := context.WithTimeout(context.Background(), time.Millisecond)
  51. defer cancelFunc()
  52. err = waitRetryBackoff(logger, 1, ctx, opt)
  53. assert.ErrorIs(t, err, status.FromContextError(context.DeadlineExceeded).Err())
  54. }
  55. func Test_isRetriable(t *testing.T) {
  56. assert.False(t, isRetriable(status.FromContextError(context.DeadlineExceeded).Err(), &options{codes: DefaultRetriableCodes}))
  57. assert.True(t, isRetriable(status.Error(codes.ResourceExhausted, ""), &options{codes: DefaultRetriableCodes}))
  58. assert.False(t, isRetriable(errors.New("error"), &options{}))
  59. }
  60. func Test_perCallContext(t *testing.T) {
  61. opt := &options{perCallTimeout: time.Second, includeRetryHeader: true}
  62. ctx := metadata.NewIncomingContext(context.Background(), map[string][]string{"1": {"1"}})
  63. callContext := perCallContext(ctx, opt, 1)
  64. md, ok := metadata.FromOutgoingContext(callContext)
  65. assert.True(t, ok)
  66. assert.EqualValues(t, metadata.MD{"1": {"1"}, AttemptMetadataKey: {"1"}}, md)
  67. }
  68. func Test_filterCallOptions(t *testing.T) {
  69. grpcEmptyCallOpt := &grpc.EmptyCallOption{}
  70. retryCallOpt := &CallOption{}
  71. options, retryCallOptions := filterCallOptions([]grpc.CallOption{
  72. grpcEmptyCallOpt,
  73. retryCallOpt,
  74. })
  75. assert.EqualValues(t, []grpc.CallOption{grpcEmptyCallOpt}, options)
  76. assert.EqualValues(t, []*CallOption{retryCallOpt}, retryCallOptions)
  77. }