status_test.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. package status
  2. import (
  3. "errors"
  4. "fmt"
  5. "testing"
  6. "time"
  7. "github.com/golang/protobuf/ptypes"
  8. "github.com/golang/protobuf/ptypes/timestamp"
  9. pkgerr "github.com/pkg/errors"
  10. "github.com/stretchr/testify/assert"
  11. "google.golang.org/grpc/codes"
  12. "google.golang.org/grpc/status"
  13. "go-common/library/ecode"
  14. "go-common/library/ecode/pb"
  15. )
  16. func TestCodeConvert(t *testing.T) {
  17. var table = map[codes.Code]ecode.Code{
  18. codes.OK: ecode.OK,
  19. // codes.Canceled
  20. codes.Unknown: ecode.ServerErr,
  21. codes.InvalidArgument: ecode.RequestErr,
  22. codes.DeadlineExceeded: ecode.Deadline,
  23. codes.NotFound: ecode.NothingFound,
  24. // codes.AlreadyExists
  25. codes.PermissionDenied: ecode.AccessDenied,
  26. codes.ResourceExhausted: ecode.LimitExceed,
  27. // codes.FailedPrecondition
  28. // codes.Aborted
  29. // codes.OutOfRange
  30. codes.Unimplemented: ecode.MethodNotAllowed,
  31. codes.Unavailable: ecode.ServiceUnavailable,
  32. // codes.DataLoss
  33. codes.Unauthenticated: ecode.Unauthorized,
  34. }
  35. for k, v := range table {
  36. assert.Equal(t, toECode(status.New(k, "-500")), v)
  37. }
  38. for k, v := range table {
  39. assert.Equal(t, togRPCCode(v), k, fmt.Sprintf("togRPC code error: %d -> %d", v, k))
  40. }
  41. }
  42. func TestNoDetailsConvert(t *testing.T) {
  43. gst := status.New(codes.Unknown, "-2233")
  44. assert.Equal(t, toECode(gst).Code(), -2233)
  45. gst = status.New(codes.Internal, "")
  46. assert.Equal(t, toECode(gst).Code(), -500)
  47. }
  48. func TestFromError(t *testing.T) {
  49. t.Run("input general error", func(t *testing.T) {
  50. err := errors.New("general error")
  51. gst := FromError(err)
  52. assert.Equal(t, codes.Unknown, gst.Code())
  53. assert.Contains(t, gst.Message(), "general")
  54. })
  55. t.Run("input wrap error", func(t *testing.T) {
  56. err := pkgerr.Wrap(ecode.RequestErr, "hh")
  57. gst := FromError(err)
  58. assert.Equal(t, "-400", gst.Message())
  59. })
  60. t.Run("input ecode.Code", func(t *testing.T) {
  61. err := ecode.RequestErr
  62. gst := FromError(err)
  63. //assert.Equal(t, codes.InvalidArgument, gst.Code())
  64. // NOTE: set all grpc.status as Unkown when error is ecode.Codes for compatible
  65. assert.Equal(t, codes.Unknown, gst.Code())
  66. // NOTE: gst.Message == str(ecode.Code) for compatible php leagcy code
  67. assert.Equal(t, err.Message(), gst.Message())
  68. })
  69. t.Run("input pb.Error", func(t *testing.T) {
  70. m := &timestamp.Timestamp{Seconds: time.Now().Unix()}
  71. detail, _ := ptypes.MarshalAny(m)
  72. err := &pb.Error{ErrCode: 2233, ErrMessage: "message", ErrDetail: detail}
  73. gst := FromError(err)
  74. assert.Equal(t, codes.Unknown, gst.Code())
  75. assert.Len(t, gst.Details(), 1)
  76. assert.Equal(t, "2233", gst.Message())
  77. })
  78. t.Run("input ecode.Status", func(t *testing.T) {
  79. m := &timestamp.Timestamp{Seconds: time.Now().Unix()}
  80. err, _ := ecode.Error(ecode.Unauthorized, "unauthorized").WithDetails(m)
  81. gst := FromError(err)
  82. //assert.Equal(t, codes.Unauthenticated, gst.Code())
  83. // NOTE: set all grpc.status as Unkown when error is ecode.Codes for compatible
  84. assert.Equal(t, codes.Unknown, gst.Code())
  85. assert.Len(t, gst.Details(), 2)
  86. details := gst.Details()
  87. assert.IsType(t, &pb.Error{}, details[0])
  88. assert.IsType(t, err.Proto(), details[1])
  89. })
  90. }
  91. func TestToEcode(t *testing.T) {
  92. t.Run("input general grpc.Status", func(t *testing.T) {
  93. gst := status.New(codes.Unknown, "unknown")
  94. ec := ToEcode(gst)
  95. assert.Equal(t, int(ecode.ServerErr), ec.Code())
  96. assert.Equal(t, "-500", ec.Message())
  97. assert.Len(t, ec.Details(), 0)
  98. })
  99. t.Run("input pb.Error", func(t *testing.T) {
  100. m := &timestamp.Timestamp{Seconds: time.Now().Unix()}
  101. detail, _ := ptypes.MarshalAny(m)
  102. gst := status.New(codes.InvalidArgument, "requesterr")
  103. gst, _ = gst.WithDetails(&pb.Error{ErrCode: 1122, ErrMessage: "message", ErrDetail: detail})
  104. ec := ToEcode(gst)
  105. assert.Equal(t, 1122, ec.Code())
  106. assert.Equal(t, "message", ec.Message())
  107. assert.Len(t, ec.Details(), 1)
  108. assert.IsType(t, m, ec.Details()[0])
  109. })
  110. t.Run("input pb.Error and ecode.Status", func(t *testing.T) {
  111. gst := status.New(codes.InvalidArgument, "requesterr")
  112. gst, _ = gst.WithDetails(
  113. &pb.Error{ErrCode: 1122, ErrMessage: "message"},
  114. ecode.Errorf(ecode.AccessKeyErr, "AccessKeyErr").Proto(),
  115. )
  116. ec := ToEcode(gst)
  117. assert.Equal(t, int(ecode.AccessKeyErr), ec.Code())
  118. assert.Equal(t, "AccessKeyErr", ec.Message())
  119. })
  120. t.Run("input encode.Status", func(t *testing.T) {
  121. m := &timestamp.Timestamp{Seconds: time.Now().Unix()}
  122. st, _ := ecode.Errorf(ecode.AccessKeyErr, "AccessKeyErr").WithDetails(m)
  123. gst := status.New(codes.InvalidArgument, "requesterr")
  124. gst, _ = gst.WithDetails(st.Proto())
  125. ec := ToEcode(gst)
  126. assert.Equal(t, int(ecode.AccessKeyErr), ec.Code())
  127. assert.Equal(t, "AccessKeyErr", ec.Message())
  128. assert.Len(t, ec.Details(), 1)
  129. assert.IsType(t, m, ec.Details()[0])
  130. })
  131. }