topfans/backend/pkg/errors/errors_test.go
2026-06-15 16:28:35 +08:00

220 lines
6.0 KiB
Go

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)
}
}