[🤖] Add Unit-Tests
Build Docker and Deploy / Run goext test-suite (push) Successful in 1m34s

This commit is contained in:
2026-04-27 10:46:08 +02:00
parent dad0e3240d
commit 02d6894ec6
116 changed files with 18795 additions and 1 deletions
+188
View File
@@ -0,0 +1,188 @@
package reflectext
import (
"reflect"
"testing"
)
type aliasInt int
type aliasString string
type aliasFloat float64
type aliasBool bool
type aliasIntSlice []int
type aliasStringMap map[string]int
type aliasArr [3]int
type aliasIntPtr *int
type myStruct struct {
A int
B string
}
func TestUnderlying_Primitives(t *testing.T) {
cases := []struct {
in reflect.Type
want reflect.Kind
}{
{reflect.TypeFor[aliasInt](), reflect.Int},
{reflect.TypeFor[aliasString](), reflect.String},
{reflect.TypeFor[aliasFloat](), reflect.Float64},
{reflect.TypeFor[aliasBool](), reflect.Bool},
}
for _, c := range cases {
got := Underlying(c.in)
if got.Kind() != c.want {
t.Errorf("Underlying(%v).Kind() = %v, want %v", c.in, got.Kind(), c.want)
}
if got.Name() != "" && got != reflectBasicTypes[c.want] {
t.Errorf("Underlying(%v) was not the basic type", c.in)
}
}
}
func TestUnderlying_UnnamedReturnsSelf(t *testing.T) {
t1 := reflect.TypeFor[[]int]()
got := Underlying(t1)
if got != t1 {
t.Errorf("Underlying of unnamed slice should be itself")
}
}
func TestUnderlying_Slice(t *testing.T) {
t1 := reflect.TypeFor[aliasIntSlice]()
got := Underlying(t1)
if got.Kind() != reflect.Slice {
t.Errorf("expected slice kind, got %v", got.Kind())
}
if got.Elem().Kind() != reflect.Int {
t.Errorf("expected element of int, got %v", got.Elem().Kind())
}
if got.Name() != "" {
t.Errorf("underlying type should be unnamed, got name %q", got.Name())
}
}
func TestUnderlying_Map(t *testing.T) {
t1 := reflect.TypeFor[aliasStringMap]()
got := Underlying(t1)
if got.Kind() != reflect.Map {
t.Errorf("expected map kind, got %v", got.Kind())
}
}
func TestUnderlying_Array(t *testing.T) {
t1 := reflect.TypeFor[aliasArr]()
got := Underlying(t1)
if got.Kind() != reflect.Array {
t.Errorf("expected array kind, got %v", got.Kind())
}
if got.Len() != 3 {
t.Errorf("expected array len 3, got %d", got.Len())
}
}
func TestUnderlying_Pointer(t *testing.T) {
t1 := reflect.TypeFor[aliasIntPtr]()
got := Underlying(t1)
if got.Kind() != reflect.Pointer {
t.Errorf("expected pointer kind, got %v", got.Kind())
}
if got.Elem().Kind() != reflect.Int {
t.Errorf("expected element kind int, got %v", got.Elem().Kind())
}
}
func TestUnderlying_Func(t *testing.T) {
type fnType func(a int, b string) (bool, error)
t1 := reflect.TypeFor[fnType]()
got := Underlying(t1)
if got.Kind() != reflect.Func {
t.Errorf("expected func kind, got %v", got.Kind())
}
if got.NumIn() != 2 || got.NumOut() != 2 {
t.Errorf("unexpected in/out count: %d/%d", got.NumIn(), got.NumOut())
}
}
func TestTryCast_AliasToBase(t *testing.T) {
v := aliasInt(42)
got, ok := TryCast[int](v)
if !ok {
t.Errorf("expected ok cast")
}
if got != 42 {
t.Errorf("expected 42, got %v", got)
}
}
func TestTryCast_SameType(t *testing.T) {
got, ok := TryCast[int](42)
if !ok {
t.Errorf("expected ok cast")
}
if got != 42 {
t.Errorf("expected 42, got %v", got)
}
}
func TestTryCast_StringSameType(t *testing.T) {
got, ok := TryCast[string]("hello")
if !ok {
t.Errorf("expected ok cast")
}
if got != "hello" {
t.Errorf("expected hello, got %v", got)
}
}
func TestTryCast_IncompatibleTypes(t *testing.T) {
_, ok := TryCast[string](aliasInt(42))
if ok {
t.Errorf("expected fail cast int->string")
}
_, ok = TryCast[int](aliasString("foo"))
if ok {
t.Errorf("expected fail cast string->int")
}
}
func TestTryCastType_AliasToBase(t *testing.T) {
v := aliasInt(42)
res, ok := TryCastType(v, reflect.TypeFor[int]())
if !ok {
t.Errorf("expected ok cast")
}
if i, isInt := res.(int); !isInt || i != 42 {
t.Errorf("expected int(42), got %T:%v", res, res)
}
}
func TestTryCastType_BaseToAlias(t *testing.T) {
res, ok := TryCastType(42, reflect.TypeFor[aliasInt]())
if !ok {
t.Errorf("expected ok cast")
}
if i, isAlias := res.(aliasInt); !isAlias || i != aliasInt(42) {
t.Errorf("expected aliasInt(42), got %T:%v", res, res)
}
}
func TestTryCastType_Incompatible(t *testing.T) {
_, ok := TryCastType("hello", reflect.TypeFor[int]())
if ok {
t.Errorf("expected fail cast string->int")
}
}
func TestUnderlying_Struct(t *testing.T) {
t1 := reflect.TypeFor[myStruct]()
got := Underlying(t1)
if got.Kind() != reflect.Struct {
t.Errorf("expected struct kind, got %v", got.Kind())
}
if got.NumField() != 2 {
t.Errorf("expected 2 fields, got %d", got.NumField())
}
}
@@ -0,0 +1,367 @@
package reflectext
import (
"reflect"
"testing"
"time"
"go.mongodb.org/mongo-driver/v2/bson"
)
func TestPSS_String(t *testing.T) {
pss := PrimitiveStringSerializer{}
s, err := pss.ValueToString("hello")
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if s != "hello" {
t.Errorf("expected hello, got %q", s)
}
v, err := pss.ValueFromString("world", reflect.TypeFor[string]())
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if v.(string) != "world" {
t.Errorf("expected world, got %v", v)
}
}
func TestPSS_Int(t *testing.T) {
pss := PrimitiveStringSerializer{}
s, err := pss.ValueToString(42)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if s != "42" {
t.Errorf("expected 42, got %q", s)
}
v, err := pss.ValueFromString("42", reflect.TypeFor[int]())
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if v.(int) != 42 {
t.Errorf("expected 42, got %v", v)
}
}
func TestPSS_Int64(t *testing.T) {
pss := PrimitiveStringSerializer{}
s, err := pss.ValueToString(int64(-100))
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if s != "-100" {
t.Errorf("expected -100, got %q", s)
}
v, err := pss.ValueFromString("-100", reflect.TypeFor[int64]())
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if v.(int64) != -100 {
t.Errorf("expected -100, got %v", v)
}
}
func TestPSS_Uint(t *testing.T) {
pss := PrimitiveStringSerializer{}
s, err := pss.ValueToString(uint(123))
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if s != "123" {
t.Errorf("expected 123, got %q", s)
}
v, err := pss.ValueFromString("123", reflect.TypeFor[uint]())
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if v.(uint) != 123 {
t.Errorf("expected 123, got %v", v)
}
}
func TestPSS_Float(t *testing.T) {
pss := PrimitiveStringSerializer{}
s, err := pss.ValueToString(3.14)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if s != "3.14" {
t.Errorf("expected 3.14, got %q", s)
}
v, err := pss.ValueFromString("3.14", reflect.TypeFor[float64]())
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if v.(float64) != 3.14 {
t.Errorf("expected 3.14, got %v", v)
}
}
func TestPSS_Float32(t *testing.T) {
pss := PrimitiveStringSerializer{}
v, err := pss.ValueFromString("1.5", reflect.TypeFor[float32]())
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if v.(float32) != 1.5 {
t.Errorf("expected 1.5, got %v", v)
}
}
func TestPSS_Bool(t *testing.T) {
pss := PrimitiveStringSerializer{}
s, err := pss.ValueToString(true)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if s != "true" {
t.Errorf("expected true, got %q", s)
}
s, err = pss.ValueToString(false)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if s != "false" {
t.Errorf("expected false, got %q", s)
}
v, err := pss.ValueFromString("true", reflect.TypeFor[bool]())
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if v.(bool) != true {
t.Errorf("expected true, got %v", v)
}
}
func TestPSS_BoolInvalid(t *testing.T) {
pss := PrimitiveStringSerializer{}
_, err := pss.ValueFromString("notabool", reflect.TypeFor[bool]())
if err == nil {
t.Errorf("expected error for invalid bool")
}
}
func TestPSS_IntInvalid(t *testing.T) {
pss := PrimitiveStringSerializer{}
_, err := pss.ValueFromString("notanint", reflect.TypeFor[int]())
if err == nil {
t.Errorf("expected error for invalid int")
}
}
func TestPSS_FloatInvalid(t *testing.T) {
pss := PrimitiveStringSerializer{}
_, err := pss.ValueFromString("notafloat", reflect.TypeFor[float64]())
if err == nil {
t.Errorf("expected error for invalid float")
}
}
func TestPSS_Time(t *testing.T) {
pss := PrimitiveStringSerializer{}
tm := time.Date(2023, 4, 5, 12, 30, 45, 0, time.UTC)
s, err := pss.ValueToString(tm)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
v, err := pss.ValueFromString(s, reflect.TypeFor[time.Time]())
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if !v.(time.Time).Equal(tm) {
t.Errorf("expected %v, got %v", tm, v)
}
}
func TestPSS_TimeInvalid(t *testing.T) {
pss := PrimitiveStringSerializer{}
_, err := pss.ValueFromString("not-a-time", reflect.TypeFor[time.Time]())
if err == nil {
t.Errorf("expected error for invalid time")
}
}
func TestPSS_ObjectID(t *testing.T) {
pss := PrimitiveStringSerializer{}
oid := bson.NewObjectID()
s, err := pss.ValueToString(oid)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if s != oid.Hex() {
t.Errorf("expected %v, got %v", oid.Hex(), s)
}
v, err := pss.ValueFromString(oid.Hex(), reflect.TypeFor[bson.ObjectID]())
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if v.(bson.ObjectID) != oid {
t.Errorf("expected %v, got %v", oid, v)
}
}
func TestPSS_ObjectIDInvalid(t *testing.T) {
pss := PrimitiveStringSerializer{}
_, err := pss.ValueFromString("not-a-hex-id", reflect.TypeFor[bson.ObjectID]())
if err == nil {
t.Errorf("expected error for invalid object id")
}
}
func TestPSS_PointerNil(t *testing.T) {
pss := PrimitiveStringSerializer{}
var p *int
s, err := pss.ValueToString(p)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if s != "" {
t.Errorf("expected empty string, got %q", s)
}
}
func TestPSS_PointerSet(t *testing.T) {
pss := PrimitiveStringSerializer{}
x := 99
p := &x
s, err := pss.ValueToString(p)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if s != "99" {
t.Errorf("expected 99, got %q", s)
}
}
func TestPSS_FromStringEmptyToPointer(t *testing.T) {
pss := PrimitiveStringSerializer{}
v, err := pss.ValueFromString("", reflect.TypeFor[*int]())
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
pInt, ok := v.(*int)
if !ok {
t.Fatalf("expected *int, got %T", v)
}
if pInt != nil {
t.Errorf("expected nil pointer, got %v", *pInt)
}
}
func TestPSS_FromStringPointer(t *testing.T) {
pss := PrimitiveStringSerializer{}
v, err := pss.ValueFromString("55", reflect.TypeFor[*int]())
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
pInt, ok := v.(*int)
if !ok {
t.Fatalf("expected *int, got %T", v)
}
if pInt == nil || *pInt != 55 {
t.Errorf("expected pointer to 55, got %v", pInt)
}
}
func TestPSS_FromStringEmptyToInt(t *testing.T) {
pss := PrimitiveStringSerializer{}
v, err := pss.ValueFromString("", reflect.TypeFor[int]())
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if v.(int) != 0 {
t.Errorf("expected 0, got %v", v)
}
}
type psAliasInt int
type psAliasString string
func TestPSS_AliasToString(t *testing.T) {
pss := PrimitiveStringSerializer{}
v := psAliasInt(77)
s, err := pss.ValueToString(v)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if s != "77" {
t.Errorf("expected 77, got %q", s)
}
}
func TestPSS_AliasFromString(t *testing.T) {
pss := PrimitiveStringSerializer{}
v, err := pss.ValueFromString("77", reflect.TypeFor[psAliasInt]())
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if v.(psAliasInt) != psAliasInt(77) {
t.Errorf("expected 77, got %v", v)
}
}
func TestPSS_AliasStringToString(t *testing.T) {
pss := PrimitiveStringSerializer{}
v := psAliasString("hello")
s, err := pss.ValueToString(v)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if s != "hello" {
t.Errorf("expected hello, got %q", s)
}
}
func TestPSS_AliasStringFromString(t *testing.T) {
pss := PrimitiveStringSerializer{}
v, err := pss.ValueFromString("hello", reflect.TypeFor[psAliasString]())
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if v.(psAliasString) != psAliasString("hello") {
t.Errorf("expected hello, got %v", v)
}
}
func TestPSS_UnknownTypeToString(t *testing.T) {
pss := PrimitiveStringSerializer{}
type unknownStruct struct{ X int }
_, err := pss.ValueToString(unknownStruct{X: 1})
if err == nil {
t.Errorf("expected error for unknown type")
}
}