1011 lines
26 KiB
Go
1011 lines
26 KiB
Go
package error
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"member/internal/lib/error/code"
|
|
"reflect"
|
|
"strconv"
|
|
"testing"
|
|
|
|
"github.com/golang/mock/gomock"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/zeromicro/go-zero/core/logx"
|
|
"google.golang.org/grpc/codes"
|
|
"google.golang.org/grpc/status"
|
|
)
|
|
|
|
func TestFromGRPCError_GivenStatusWithCodeAndMessage_ShouldReturnErr(t *testing.T) {
|
|
// setup
|
|
s := status.Error(codes.Code(102399), "FAKE ERROR")
|
|
|
|
// act
|
|
e := FromGRPCError(s)
|
|
|
|
// assert
|
|
assert.Equal(t, uint32(10), e.Scope())
|
|
assert.Equal(t, uint32(2300), e.Category())
|
|
assert.Equal(t, uint32(2399), e.Code())
|
|
assert.Equal(t, "FAKE ERROR", e.Error())
|
|
}
|
|
|
|
func TestFromGRPCError_GivenNilError_ShouldReturnErr_Scope0_Cat0_Detail0(t *testing.T) {
|
|
// setup
|
|
var nilError error = nil
|
|
|
|
// act
|
|
e := FromGRPCError(nilError)
|
|
|
|
// assert
|
|
assert.Equal(t, uint32(0), e.Scope())
|
|
assert.Equal(t, uint32(0), e.Category())
|
|
assert.Equal(t, uint32(0), e.Code())
|
|
assert.Equal(t, "", e.Error())
|
|
}
|
|
|
|
func TestFromGRPCError_GivenGRPCNativeError_ShouldReturnErr_Scope0_CatGRPC_DetailGRPCUnavailable(t *testing.T) {
|
|
// setup
|
|
msg := "GRPC Unavailable ERROR"
|
|
s := status.Error(codes.Code(codes.Unavailable), msg)
|
|
|
|
// act
|
|
e := FromGRPCError(s)
|
|
|
|
// assert
|
|
assert.Equal(t, code.Unset, e.Scope())
|
|
assert.Equal(t, code.CatGRPC, e.Category())
|
|
assert.Equal(t, uint32(codes.Unavailable), e.Code())
|
|
assert.Equal(t, msg, e.Error())
|
|
}
|
|
|
|
func TestFromGRPCError_GivenGeneralError_ShouldReturnErr_Scope0_CatGRPC_DetailGRPCUnknown(t *testing.T) {
|
|
// setup
|
|
generalErr := errors.New("general error")
|
|
|
|
// act
|
|
e := FromGRPCError(generalErr)
|
|
|
|
// assert
|
|
assert.Equal(t, code.Unset, e.Scope())
|
|
assert.Equal(t, code.CatGRPC, e.Category())
|
|
assert.Equal(t, uint32(codes.Unknown), e.Code())
|
|
}
|
|
|
|
func TestToGRPCError_GivenErr_StatusShouldHave_Code112233(t *testing.T) {
|
|
// setup
|
|
e := Err{scope: 11, code: 2233, msg: "FAKE MSG"}
|
|
|
|
// act
|
|
err := ToGRPCError(&e)
|
|
s, _ := status.FromError(err)
|
|
|
|
// assert
|
|
assert.Equal(t, 112233, int(s.Code()))
|
|
assert.Equal(t, "FAKE MSG", s.Message())
|
|
}
|
|
|
|
func TestInvalidFormat_WithStrings_ShouldHasCatInputAndDetailCode(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() {
|
|
Scope = code.Unset
|
|
}()
|
|
|
|
// act
|
|
e := InvalidFormat("field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatInput, e.Category())
|
|
assert.Equal(t, code.InvalidFormat, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Equal(t, e.Error(), "invalid format: field A Error description")
|
|
}
|
|
|
|
func TestInvalidFormatL_WithStrings_ShouldHasCatInputAndDetailCode(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() { Scope = code.Unset }()
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
ctx := context.Background()
|
|
// act
|
|
e := InvalidFormatL(logx.WithContext(ctx), "field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatInput, e.Category())
|
|
assert.Equal(t, code.InvalidFormat, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
}
|
|
|
|
func TestInvalidRange_WithStrings_ShouldHasCatInputAndDetailCode(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() {
|
|
Scope = code.Unset
|
|
}()
|
|
|
|
// act
|
|
e := InvalidRange("field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatInput, e.Category())
|
|
assert.Equal(t, code.InvalidRange, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Equal(t, e.Error(), "invalid range: field A Error description")
|
|
}
|
|
|
|
func TestInvalidRangeL_WithStrings_ShouldHasCatInputAndDetailCode(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() { Scope = code.Unset }()
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
ctx := context.Background()
|
|
// act
|
|
e := InvalidRangeL(logx.WithContext(ctx), "field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatInput, e.Category())
|
|
assert.Equal(t, code.InvalidRange, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
}
|
|
|
|
func TestNotValidImplementation_WithStrings_ShouldHasCatInputAndDetailCode(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() {
|
|
Scope = code.Unset
|
|
}()
|
|
|
|
// act
|
|
e := NotValidImplementation("field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatInput, e.Category())
|
|
assert.Equal(t, code.NotValidImplementation, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Equal(t, e.Error(), "not valid implementation: field A Error description")
|
|
}
|
|
|
|
func TestNotValidImplementationL_WithStrings_ShouldHasCatInputAndDetailCode(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() { Scope = code.Unset }()
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
l := logx.WithContext(context.Background())
|
|
// act
|
|
e := NotValidImplementationL(l, "field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatInput, e.Category())
|
|
assert.Equal(t, code.NotValidImplementation, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
}
|
|
|
|
func TestDBError_WithStrings_ShouldHasCatDBAndDetailCodeDBError(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() {
|
|
Scope = code.Unset
|
|
}()
|
|
|
|
// act
|
|
e := DBError("field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatDB, e.Category())
|
|
assert.Equal(t, code.DBError, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
}
|
|
|
|
func TestDBDataConvert_WithStrings_ShouldHasCatDBAndDetailCodeDBDataConvert(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() {
|
|
Scope = code.Unset
|
|
}()
|
|
|
|
// act
|
|
e := DBDataConvert("field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatDB, e.Category())
|
|
assert.Equal(t, code.DBDataConvert, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
}
|
|
|
|
func TestResourceNotFound_WithStrings_ShouldHasCatResource_DetailCodeResourceNotFound(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() {
|
|
Scope = code.Unset
|
|
}()
|
|
|
|
// act
|
|
e := ResourceNotFound("field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatResource, e.Category())
|
|
assert.Equal(t, code.ResourceNotFound, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
}
|
|
|
|
func TestInvalidResourceFormat_WithStrings_ShouldHasCatResource_DetailCodeInvalidResourceFormat(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() {
|
|
Scope = code.Unset
|
|
}()
|
|
|
|
// act
|
|
e := InvalidResourceFormat("field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatResource, e.Category())
|
|
assert.Equal(t, code.InvalidResourceFormat, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
}
|
|
|
|
func TestInvalidResourceState_OK(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() {
|
|
Scope = code.Unset
|
|
}()
|
|
|
|
// act
|
|
e := InvalidResourceState("field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatResource, e.Category())
|
|
assert.Equal(t, code.InvalidResourceState, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.EqualError(t, e, "invalid resource state: field A Error description")
|
|
}
|
|
|
|
func TestInvalidResourceStateL_LogError(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() { Scope = code.Unset }()
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
l := logx.WithContext(context.Background())
|
|
|
|
// act
|
|
e := InvalidResourceStateL(l, "field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatResource, e.Category())
|
|
assert.Equal(t, code.InvalidResourceState, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.EqualError(t, e, "invalid resource state: field A Error description")
|
|
}
|
|
|
|
func TestAuthExpired_OK(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() {
|
|
Scope = code.Unset
|
|
}()
|
|
|
|
// act
|
|
e := AuthExpired("field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatAuth, e.Category())
|
|
assert.Equal(t, code.AuthExpired, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
}
|
|
|
|
func TestUnauthorized_WithStrings_ShouldHasCatAuth_DetailCodeUnauthorized(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() {
|
|
Scope = code.Unset
|
|
}()
|
|
|
|
// act
|
|
e := Unauthorized("field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatAuth, e.Category())
|
|
assert.Equal(t, code.Unauthorized, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
}
|
|
|
|
func TestInvalidPosixTime_WithStrings_ShouldHasCatAuth_DetailCodeInvalidPosixTime(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() {
|
|
Scope = code.Unset
|
|
}()
|
|
|
|
// act
|
|
e := InvalidPosixTime("field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatAuth, e.Category())
|
|
assert.Equal(t, code.InvalidPosixTime, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
}
|
|
|
|
func TestSigAndPayloadNotMatched_WithStrings_ShouldHasCatAuth_DetailCodeSigAndPayloadNotMatched(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() {
|
|
Scope = code.Unset
|
|
}()
|
|
|
|
// act
|
|
e := SigAndPayloadNotMatched("field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatAuth, e.Category())
|
|
assert.Equal(t, code.SigAndPayloadNotMatched, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
}
|
|
|
|
func TestForbidden_WithStrings_ShouldHasCatAuth_DetailCodeForbidden(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() {
|
|
Scope = code.Unset
|
|
}()
|
|
|
|
// act
|
|
e := Forbidden("field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatAuth, e.Category())
|
|
assert.Equal(t, code.Forbidden, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
}
|
|
|
|
func TestXBCInternal_WithStrings_ShouldHasCatResource_DetailCodeXBCInternal(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() {
|
|
Scope = code.Unset
|
|
}()
|
|
|
|
// act
|
|
e := XBCInternal("field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatArk, e.Category())
|
|
assert.Equal(t, code.ArkInternal, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
}
|
|
|
|
func TestGeneralInternalError_WithStrings_DetailInternalError(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() {
|
|
Scope = code.Unset
|
|
}()
|
|
|
|
// act
|
|
e := SystemInternalError("field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatSystem, e.Category())
|
|
assert.Equal(t, code.SystemInternalError, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
}
|
|
|
|
func TestGeneralInternalErrorL_WithStrings_DetailInternalError(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() { Scope = code.Unset }()
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
l := logx.WithContext(context.Background())
|
|
|
|
// act
|
|
e := SystemInternalErrorL(l, "field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatSystem, e.Category())
|
|
assert.Equal(t, code.SystemInternalError, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
}
|
|
|
|
func TestSystemMaintainError_WithStrings_DetailSystemMaintainError(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() { Scope = code.Unset }()
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
l := logx.WithContext(context.Background())
|
|
|
|
// act
|
|
e := SystemMaintainErrorL(l, "field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatSystem, e.Category())
|
|
assert.Equal(t, code.SystemMaintainError, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
}
|
|
|
|
func TestResourceAlreadyExist_WithStrings_DetailInternalError(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() {
|
|
Scope = code.Unset
|
|
}()
|
|
|
|
// act
|
|
e := ResourceAlreadyExist("field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatResource, e.Category())
|
|
assert.Equal(t, code.ResourceAlreadyExist, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
}
|
|
|
|
func TestResourceAlreadyExistL_WithStrings_DetailInternalError(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() { Scope = code.Unset }()
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
l := logx.WithContext(context.Background())
|
|
|
|
// act
|
|
e := ResourceAlreadyExistL(l, "field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatResource, e.Category())
|
|
assert.Equal(t, code.ResourceAlreadyExist, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
}
|
|
|
|
func TestResourceInsufficient_WithStrings_DetailInternalError(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() {
|
|
Scope = code.Unset
|
|
}()
|
|
|
|
// act
|
|
e := ResourceInsufficient("field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatResource, e.Category())
|
|
assert.Equal(t, code.ResourceInsufficient, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
}
|
|
|
|
func TestResourceInsufficientL_WithStrings_DetailInternalError(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() { Scope = code.Unset }()
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
l := logx.WithContext(context.Background())
|
|
|
|
// act
|
|
e := ResourceInsufficientL(l, "field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatResource, e.Category())
|
|
assert.Equal(t, code.ResourceInsufficient, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
}
|
|
|
|
func TestInsufficientPermission_WithStrings_DetailInternalError(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() {
|
|
Scope = code.Unset
|
|
}()
|
|
|
|
// act
|
|
e := InsufficientPermission("field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatResource, e.Category())
|
|
assert.Equal(t, code.InsufficientPermission, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
}
|
|
|
|
func TestInsufficientPermissionL_WithStrings_DetailInternalError(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() { Scope = code.Unset }()
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
l := logx.WithContext(context.Background())
|
|
|
|
// act
|
|
e := InsufficientPermissionL(l, "field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatResource, e.Category())
|
|
assert.Equal(t, code.InsufficientPermission, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
}
|
|
|
|
func TestInvalidMeasurementID_WithErrorStrings_ShouldReturnCorrectCodeAndErrorString(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() {
|
|
Scope = code.Unset
|
|
}()
|
|
|
|
// act
|
|
e := InvalidMeasurementID("field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatResource, e.Category())
|
|
assert.Equal(t, code.InvalidMeasurementID, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
}
|
|
|
|
func TestInvalidMeasurementIDL_WithErrorStrings_ShouldReturnCorrectCodeAndErrorStringAndCallLogger(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() { Scope = code.Unset }()
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
l := logx.WithContext(context.Background())
|
|
|
|
// act
|
|
e := InvalidMeasurementIDL(l, "field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatResource, e.Category())
|
|
assert.Equal(t, code.InvalidMeasurementID, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
}
|
|
|
|
func TestResourceExpired_OK(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() {
|
|
Scope = code.Unset
|
|
}()
|
|
|
|
// act
|
|
e := ResourceExpired("field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatResource, e.Category())
|
|
assert.Equal(t, code.ResourceExpired, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
}
|
|
|
|
func TestResourceExpiredL_LogError(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() { Scope = code.Unset }()
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
l := logx.WithContext(context.Background())
|
|
|
|
// act
|
|
e := ResourceExpiredL(l, "field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatResource, e.Category())
|
|
assert.Equal(t, code.ResourceExpired, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
}
|
|
|
|
func TestResourceMigrated_OK(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() {
|
|
Scope = code.Unset
|
|
}()
|
|
|
|
// act
|
|
e := ResourceMigrated("field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatResource, e.Category())
|
|
assert.Equal(t, code.ResourceMigrated, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
}
|
|
|
|
func TestResourceMigratedL_LogError(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() { Scope = code.Unset }()
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
l := logx.WithContext(context.Background())
|
|
|
|
// act
|
|
e := ResourceMigratedL(l, "field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatResource, e.Category())
|
|
assert.Equal(t, code.ResourceMigrated, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
}
|
|
|
|
func TestInsufficientQuota_OK(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() {
|
|
Scope = code.Unset
|
|
}()
|
|
|
|
// act
|
|
e := InsufficientQuota("field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatResource, e.Category())
|
|
assert.Equal(t, code.InsufficientQuota, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
}
|
|
|
|
func TestInsufficientQuotaL_LogError(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() { Scope = code.Unset }()
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
l := logx.WithContext(context.Background())
|
|
|
|
// act
|
|
e := InsufficientQuotaL(l, "field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatResource, e.Category())
|
|
assert.Equal(t, code.InsufficientQuota, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
}
|
|
|
|
func TestPublish_WithErrorStrings_ShouldReturnCorrectCodeAndErrorString(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() {
|
|
Scope = code.Unset
|
|
}()
|
|
|
|
// act
|
|
e := Publish("field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatPubSub, e.Category())
|
|
assert.Equal(t, code.Publish, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
}
|
|
|
|
func TestPublishL_WithErrorStrings_ShouldReturnCorrectCodeAndErrorStringAndCallLogger(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() { Scope = code.Unset }()
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
l := logx.WithContext(context.Background())
|
|
|
|
// act
|
|
e := PublishL(l, "field A", "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatPubSub, e.Category())
|
|
assert.Equal(t, code.Publish, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
}
|
|
|
|
func TestMsgSizeTooLarge_WithErrorStrings_ShouldReturnCorrectCodeAndErrorString(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() {
|
|
Scope = code.Unset
|
|
}()
|
|
|
|
// act
|
|
e := MsgSizeTooLarge("Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatPubSub, e.Category())
|
|
assert.Equal(t, code.MsgSizeTooLarge, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "kafka error: Error description")
|
|
}
|
|
|
|
func TestMsgSizeTooLargeL_WithErrorStrings_ShouldReturnCorrectCodeAndErrorStringAndCallLogger(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() { Scope = code.Unset }()
|
|
ctrl := gomock.NewController(t)
|
|
defer ctrl.Finish()
|
|
|
|
l := logx.WithContext(context.Background())
|
|
|
|
// act
|
|
e := MsgSizeTooLargeL(l, "Error description")
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatPubSub, e.Category())
|
|
assert.Equal(t, code.MsgSizeTooLarge, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "kafka error: Error description")
|
|
}
|
|
|
|
func TestStructErr_WithInternalErr_ShouldIsFuncReportCorrectly(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() { Scope = code.Unset }()
|
|
// arrange 2 layers err
|
|
layer1Err := fmt.Errorf("layer 1 error")
|
|
layer2Err := fmt.Errorf("layer 2: %w", layer1Err)
|
|
|
|
// act with error chain: InvalidFormat -> layer 2 err -> layer 1 err
|
|
e := InvalidFormat("field A", "Error description")
|
|
e.Wrap(layer2Err)
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatInput, e.Category())
|
|
assert.Equal(t, code.InvalidFormat, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
|
|
// errors.Is should report correctly
|
|
assert.True(t, errors.Is(e, layer1Err))
|
|
assert.True(t, errors.Is(e, layer2Err))
|
|
}
|
|
|
|
func TestStructErr_WithInternalErr_ShouldErrorOutputChainErrMessage(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() { Scope = code.Unset }()
|
|
|
|
// arrange 2 layers err
|
|
layer1Err := fmt.Errorf("layer 1 error")
|
|
// act with error chain: InvalidFormat -> layer 1 err
|
|
e := InvalidFormat("field A", "Error description")
|
|
e.Wrap(layer1Err)
|
|
|
|
// assert
|
|
assert.Equal(t, "invalid format: field A Error description: layer 1 error", e.Error())
|
|
}
|
|
|
|
// arrange a specific err type just for UT
|
|
type testErr struct {
|
|
code int
|
|
}
|
|
|
|
func (e *testErr) Error() string {
|
|
return strconv.Itoa(e.code)
|
|
}
|
|
|
|
func TestStructErr_WithInternalErr_ShouldAsFuncReportCorrectly(t *testing.T) {
|
|
// setup
|
|
Scope = 99
|
|
defer func() { Scope = code.Unset }()
|
|
|
|
testE := &testErr{code: 123}
|
|
layer2Err := fmt.Errorf("layer 2: %w", testE)
|
|
|
|
// act with error chain: InvalidFormat -> layer 2 err -> testErr
|
|
e := InvalidFormat("field A", "Error description")
|
|
e.Wrap(layer2Err)
|
|
|
|
// assert
|
|
assert.Equal(t, code.CatInput, e.Category())
|
|
assert.Equal(t, code.InvalidFormat, e.Code())
|
|
assert.Equal(t, uint32(99), e.Scope())
|
|
assert.Contains(t, e.Error(), "field A")
|
|
assert.Contains(t, e.Error(), "Error description")
|
|
|
|
// errors.As should report correctly
|
|
var internalErr *testErr
|
|
assert.True(t, errors.As(e, &internalErr))
|
|
assert.Equal(t, testE, internalErr)
|
|
}
|
|
|
|
/*
|
|
benchmark run for 1 second:
|
|
Benchmark_ErrorsIs_OneLayerError-4 148281332 8.68 ns/op 0 B/op 0 allocs/op
|
|
Benchmark_ErrorsIs_TwoLayerError-4 35048202 32.4 ns/op 0 B/op 0 allocs/op
|
|
Benchmark_ErrorsIs_FourLayerError-4 15309349 81.7 ns/op 0 B/op 0 allocs/op
|
|
|
|
Benchmark_ErrorsAs_OneLayerError-4 16893205 70.4 ns/op 0 B/op 0 allocs/op
|
|
Benchmark_ErrorsAs_TwoLayerError-4 10568083 112 ns/op 0 B/op 0 allocs/op
|
|
Benchmark_ErrorsAs_FourLayerError-4 6307729 188 ns/op 0 B/op 0 allocs/op
|
|
*/
|
|
func Benchmark_ErrorsIs_OneLayerError(b *testing.B) {
|
|
layer1Err := &testErr{code: 123}
|
|
var err error = layer1Err
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
errors.Is(err, layer1Err)
|
|
}
|
|
}
|
|
|
|
func Benchmark_ErrorsIs_TwoLayerError(b *testing.B) {
|
|
layer1Err := &testErr{code: 123}
|
|
|
|
// act with error chain: InvalidFormat(layer 2) -> testErr(layer 1)
|
|
layer2Err := InvalidFormat("field A", "Error description")
|
|
layer2Err.Wrap(layer1Err)
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
errors.Is(layer2Err, layer1Err)
|
|
}
|
|
}
|
|
|
|
func Benchmark_ErrorsIs_FourLayerError(b *testing.B) {
|
|
layer1Err := &testErr{code: 123}
|
|
layer2Err := fmt.Errorf("layer 2: %w", layer1Err)
|
|
layer3Err := fmt.Errorf("layer 3: %w", layer2Err)
|
|
// act with error chain: InvalidFormat(layer 4) -> Error(layer 3) -> Error(layer 2) -> testErr(layer 1)
|
|
layer4Err := InvalidFormat("field A", "Error description")
|
|
layer4Err.Wrap(layer3Err)
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
errors.Is(layer4Err, layer1Err)
|
|
}
|
|
}
|
|
|
|
func Benchmark_ErrorsAs_OneLayerError(b *testing.B) {
|
|
layer1Err := &testErr{code: 123}
|
|
var err error = layer1Err
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
var internalErr *testErr
|
|
for i := 0; i < b.N; i++ {
|
|
errors.As(err, &internalErr)
|
|
}
|
|
}
|
|
|
|
func Benchmark_ErrorsAs_TwoLayerError(b *testing.B) {
|
|
layer1Err := &testErr{code: 123}
|
|
|
|
// act with error chain: InvalidFormat(layer 2) -> testErr(layer 1)
|
|
layer2Err := InvalidFormat("field A", "Error description")
|
|
layer2Err.Wrap(layer1Err)
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
var internalErr *testErr
|
|
for i := 0; i < b.N; i++ {
|
|
errors.As(layer2Err, &internalErr)
|
|
}
|
|
}
|
|
|
|
func Benchmark_ErrorsAs_FourLayerError(b *testing.B) {
|
|
layer1Err := &testErr{code: 123}
|
|
layer2Err := fmt.Errorf("layer 2: %w", layer1Err)
|
|
layer3Err := fmt.Errorf("layer 3: %w", layer2Err)
|
|
// act with error chain: InvalidFormat(layer 4) -> Error(layer 3) -> Error(layer 2) -> testErr(layer 1)
|
|
layer4Err := InvalidFormat("field A", "Error description")
|
|
layer4Err.Wrap(layer3Err)
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
var internalErr *testErr
|
|
for i := 0; i < b.N; i++ {
|
|
errors.As(layer4Err, &internalErr)
|
|
}
|
|
}
|
|
|
|
func TestFromError(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
givenError error
|
|
want *Err
|
|
}{
|
|
{
|
|
"given nil error should return nil",
|
|
nil,
|
|
nil,
|
|
},
|
|
{
|
|
"given normal error should return nil",
|
|
errors.New("normal error"),
|
|
nil,
|
|
},
|
|
{
|
|
"given Err should return Err",
|
|
ResourceNotFound("fake error"),
|
|
ResourceNotFound("fake error"),
|
|
},
|
|
{
|
|
"given error wraps Err should return Err",
|
|
fmt.Errorf("outter error wraps %w", ResourceNotFound("fake error")),
|
|
ResourceNotFound("fake error"),
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := FromError(tt.givenError); !reflect.DeepEqual(got, tt.want) {
|
|
t.Errorf("FromError() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|