189 lines
4.3 KiB
Go
189 lines
4.3 KiB
Go
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())
|
|
}
|
|
}
|