backend/pkg/library/errors/from_errors_test.go

116 lines
3.6 KiB
Go
Raw Normal View History

2025-11-04 09:47:36 +00:00
package errs
import (
"errors"
"fmt"
"testing"
"backend/pkg/library/errors/code"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
func TestNewBuiltinGRPCErr(t *testing.T) {
tests := []struct {
name string
scope uint32
detail uint32
msg string
wantCat uint32
wantScope uint32
wantDet uint32
wantMsg string
}{
{"basic", 10, 3, "test", uint32(code.CatGRPC), 10, 3, "test"},
{"zero", 0, 0, "", uint32(code.CatGRPC), 0, 0, ""},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
e := newBuiltinGRPCErr(tt.scope, tt.detail, tt.msg)
if e.Category() != tt.wantCat || e.Scope() != tt.wantScope || e.Detail() != tt.wantDet || e.Error() != tt.wantMsg {
t.Errorf("newBuiltinGRPCErr = cat=%d scope=%d det=%d msg=%q, want %d %d %d %q",
e.Category(), e.Scope(), e.Detail(), e.Error(), tt.wantCat, tt.wantScope, tt.wantDet, tt.wantMsg)
}
})
}
}
func TestFromError(t *testing.T) {
base := New(10, uint32(code.DBError), 0, "base")
// but actually use fmt.Errorf("%w", base) for proper wrapping
tests := []struct {
name string
in error
want *Error
}{
{"nil", nil, nil},
{"not Error", errors.New("std"), nil},
{"direct Error", base, base},
{"wrapped Error", fmt.Errorf("wrap: %w", base), base},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := FromError(tt.in)
if (got == nil) != (tt.want == nil) {
t.Errorf("FromError = %v, want nil=%v", got, tt.want == nil)
}
if got != nil && (got.Category() != tt.want.Category() || got.Detail() != tt.want.Detail()) {
t.Errorf("FromError = cat=%d det=%d, want %d %d", got.Category(), got.Detail(), tt.want.Category(), tt.want.Detail())
}
})
}
}
func TestFromCode(t *testing.T) {
tests := []struct {
name string
code uint32
wantScope uint32
wantCat uint32
wantDet uint32
}{
{"basic", 10201123, 10, 201, 123},
{"zero", 0, 0, 0, 0},
{"max", 99999999, 99, 999, 999},
{"overflow code", 100000000, 100, 0, 0}, // Parses as scope=100, but uint32 limits
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
e := FromCode(tt.code)
if e.Scope() != tt.wantScope || e.Category() != tt.wantCat || e.Detail() != tt.wantDet {
t.Errorf("FromCode = scope=%d cat=%d det=%d, want %d %d %d", e.Scope(), e.Category(), e.Detail(), tt.wantScope, tt.wantCat, tt.wantDet)
}
})
}
}
func TestFromGRPCError(t *testing.T) {
Scope = code.Gateway
tests := []struct {
name string
in error
wantScope uint32
wantCat uint32
wantDet uint32
wantMsg string
}{
{"nil", nil, 0, 0, 0, ""},
{"builtin OK", status.New(codes.OK, "").Err(), 0, 0, 0, ""},
{"builtin InvalidArgument", status.New(codes.InvalidArgument, "bad").Err(), uint32(code.Gateway), uint32(code.CatGRPC), uint32(codes.InvalidArgument), "bad"},
{"custom code", status.New(codes.Code(10201123), "custom").Err(), 10, 201, 123, "custom"},
{"unset scope with builtin", status.New(codes.NotFound, "not found").Err(), uint32(code.Gateway), uint32(code.CatGRPC), uint32(codes.NotFound), "not found"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
e := FromGRPCError(tt.in)
if e == nil && (tt.wantScope != 0 || tt.wantCat != 0 || tt.wantDet != 0) {
t.Errorf("got nil, want non-nil")
}
if e != nil && (e.Scope() != tt.wantScope || e.Category() != tt.wantCat || e.Detail() != tt.wantDet || e.Error() != tt.wantMsg) {
t.Errorf("FromGRPCError = scope=%d cat=%d det=%d msg=%q, want %d %d %d %q",
e.Scope(), e.Category(), e.Detail(), e.Error(), tt.wantScope, tt.wantCat, tt.wantDet, tt.wantMsg)
}
})
}
}