package errors import ( "fmt" "testing" "google.golang.org/grpc/codes" ) func TestToGRPCCode_Nil(t *testing.T) { if got := ToGRPCCode(nil); got != codes.OK { t.Errorf("ToGRPCCode(nil) = %v, want %v (OK=0)", got, codes.OK) } } func TestToGRPCCode_NotFound(t *testing.T) { cases := []error{ ErrUserNotFound, ErrFanProfileNotFound, ErrStarNotFound, ErrFriendRequestNotFound, ErrAssetNotFound, ErrMintOrderNotFound, ErrActivityNotFound, ErrActivityItemNotFound, ErrCollectionAssetNotFound, ErrActivityAssetNotFound, ErrAssetRegistryNotFound, } for _, e := range cases { if got := ToGRPCCode(e); got != codes.NotFound { t.Errorf("ToGRPCCode(%v) = %v, want NotFound (5)", e, got) } } } func TestToGRPCCode_InvalidArgument(t *testing.T) { cases := []error{ ErrUserAlreadyExists, ErrFanProfileAlreadyExists, ErrNicknameAlreadyExists, ErrInvalidMobile, ErrPasswordTooShort, ErrInvalidOldPassword, ErrSameAsOldPassword, ErrInvalidVerifyToken, ErrInvalidStarID, ErrInvalidUserID, ErrMaxIdentitiesReached, ErrInvalidNickname, ErrCannotAddSelf, ErrCannotSearchSelf, ErrNotFanOfStar, ErrAlreadyFriends, ErrRequestAlreadyPending, ErrInvalidFriendUserID, ErrCannotProcessOwnRequest, ErrRequestAlreadyProcessed, ErrRequestExpired, ErrInvalidAction, ErrNotFriends, ErrInsufficientCrystal, ErrInsufficientMintTimes, ErrInvalidAssetStatus, ErrInvalidMintOrderStatus, ErrInvalidAssetType, } for _, e := range cases { if got := ToGRPCCode(e); got != codes.InvalidArgument { t.Errorf("ToGRPCCode(%v) = %v, want InvalidArgument (3)", e, got) } } } func TestToGRPCCode_Unauthenticated(t *testing.T) { cases := []error{ ErrInvalidPassword, ErrInvalidToken, ErrTokenExpired, ErrTokenMismatch, } for _, e := range cases { if got := ToGRPCCode(e); got != codes.Unauthenticated { t.Errorf("ToGRPCCode(%v) = %v, want Unauthenticated (16)", e, got) } } } func TestToGRPCCode_PermissionDenied(t *testing.T) { cases := []error{ ErrAccountFrozen, ErrAccountBanned, ErrUserInactive, ErrAssetAccessDenied, ErrMintOrderAccessDenied, } for _, e := range cases { if got := ToGRPCCode(e); got != codes.PermissionDenied { t.Errorf("ToGRPCCode(%v) = %v, want PermissionDenied (7)", e, got) } } } func TestToGRPCCode_ResourceExhausted(t *testing.T) { if got := ToGRPCCode(ErrRequestInCooldown); got != codes.ResourceExhausted { t.Errorf("ToGRPCCode(ErrRequestInCooldown) = %v, want ResourceExhausted (8)", got) } } func TestToGRPCCode_Internal_Unknown(t *testing.T) { unknown := fmt.Errorf("some unknown error") if got := ToGRPCCode(unknown); got != codes.Internal { t.Errorf("ToGRPCCode(unknown) = %v, want Internal (13)", got) } } func TestToGRPCCode_WrappedError(t *testing.T) { // fmt.Errorf("%w: extra context", ErrXxx) should still be recognized wrapped := fmt.Errorf("%w: extra context", ErrInvalidPassword) if got := ToGRPCCode(wrapped); got != codes.Unauthenticated { t.Errorf("ToGRPCCode(wrapped ErrInvalidPassword) = %v, want Unauthenticated (16)", got) } wrappedBanned := fmt.Errorf("%w: bad behavior", ErrAccountBanned) if got := ToGRPCCode(wrappedBanned); got != codes.PermissionDenied { t.Errorf("ToGRPCCode(wrapped ErrAccountBanned) = %v, want PermissionDenied (7)", got) } } func TestToGRPCCode_NewAccountBannedError(t *testing.T) { // NewAccountBannedError should still be detectable as ErrAccountBanned err := NewAccountBannedError("违规内容") if got := ToGRPCCode(err); got != codes.PermissionDenied { t.Errorf("ToGRPCCode(NewAccountBannedError) = %v, want PermissionDenied (7)", got) } } func TestToGRPCCode_NewAccountFrozenError(t *testing.T) { err := NewAccountFrozenError("可疑登录", nil) if got := ToGRPCCode(err); got != codes.PermissionDenied { t.Errorf("ToGRPCCode(NewAccountFrozenError) = %v, want PermissionDenied (7)", got) } } func TestFormatErrorResponse(t *testing.T) { resp := FormatErrorResponse(ErrInvalidPassword) if resp == nil { t.Fatal("FormatErrorResponse returned nil") } if resp.Code != uint32(codes.Unauthenticated) { t.Errorf("Code = %d, want %d (Unauthenticated)", resp.Code, codes.Unauthenticated) } if resp.Message != ErrInvalidPassword.Error() { t.Errorf("Message = %q, want %q", resp.Message, ErrInvalidPassword.Error()) } if resp.Timestamp <= 0 { t.Errorf("Timestamp = %d, want > 0", resp.Timestamp) } } func TestFormatErrorResponse_Nil(t *testing.T) { resp := FormatErrorResponse(nil) if resp == nil { t.Fatal("FormatErrorResponse(nil) returned nil") } if resp.Code != uint32(codes.OK) { t.Errorf("Code = %d, want %d (OK)", resp.Code, codes.OK) } } func TestFormatSuccessResponse(t *testing.T) { resp := FormatSuccessResponse() if resp == nil { t.Fatal("FormatSuccessResponse returned nil") } if resp.Code != uint32(codes.OK) { t.Errorf("Code = %d, want %d (OK)", resp.Code, codes.OK) } if resp.Message != "" { t.Errorf("Message = %q, want empty", resp.Message) } if resp.Timestamp <= 0 { t.Errorf("Timestamp = %d, want > 0", resp.Timestamp) } } func TestBuildBaseResponseWithMessage(t *testing.T) { resp := BuildBaseResponseWithMessage(codes.InvalidArgument, "test message") if resp == nil { t.Fatal("BuildBaseResponseWithMessage returned nil") } if resp.Code != uint32(codes.InvalidArgument) { t.Errorf("Code = %d, want %d", resp.Code, codes.InvalidArgument) } if resp.Message != "test message" { t.Errorf("Message = %q, want %q", resp.Message, "test message") } } func TestNewError(t *testing.T) { err := NewError(codes.Unauthenticated, "token 过期") if err == nil { t.Fatal("NewError returned nil") } if err.Error() == "" { t.Error("NewError returned error with empty message") } } func TestNewRequestInCooldownError(t *testing.T) { err := NewRequestInCooldownError(3) if err == nil { t.Fatal("NewRequestInCooldownError returned nil") } // Should be recognized as ErrRequestInCooldown if got := ToGRPCCode(err); got != codes.ResourceExhausted { t.Errorf("ToGRPCCode(NewRequestInCooldownError) = %v, want ResourceExhausted (8)", got) } }