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