@@ -3,6 +3,7 @@ package reflect_test
33import (
44 "bytes"
55 "encoding/base64"
6+ "fmt"
67 . "reflect"
78 "slices"
89 "sort"
@@ -869,3 +870,73 @@ func equal[T comparable](a, b []T) bool {
869870 }
870871 return true
871872}
873+
874+ func TestTypeAssert (t * testing.T ) {
875+ testTypeAssert (t , int (123456789 ), int (123456789 ), true )
876+ testTypeAssert (t , int (- 123456789 ), int (- 123456789 ), true )
877+ testTypeAssert (t , int32 (123456789 ), int32 (123456789 ), true )
878+ testTypeAssert (t , int8 (- 123 ), int8 (- 123 ), true )
879+ testTypeAssert (t , [2 ]int {1234 , - 5678 }, [2 ]int {1234 , - 5678 }, true )
880+ testTypeAssert (t , "test value" , "test value" , true )
881+ testTypeAssert (t , any ("test value" ), any ("test value" ), true )
882+
883+ v := 123456789
884+ testTypeAssert (t , & v , & v , true )
885+
886+ testTypeAssert (t , int (123 ), uint (0 ), false )
887+
888+ testTypeAssert [any ](t , 1 , 1 , true )
889+ testTypeAssert [fmt.Stringer ](t , 1 , nil , false )
890+
891+ vv := testTypeWithMethod {"test" }
892+ testTypeAssert [any ](t , vv , vv , true )
893+ testTypeAssert [any ](t , & vv , & vv , true )
894+ testTypeAssert [fmt.Stringer ](t , vv , vv , true )
895+ testTypeAssert [fmt.Stringer ](t , & vv , & vv , true )
896+ testTypeAssert [interface { A () }](t , vv , nil , false )
897+ testTypeAssert [interface { A () }](t , & vv , nil , false )
898+ testTypeAssert (t , any (vv ), any (vv ), true )
899+ testTypeAssert (t , fmt .Stringer (vv ), fmt .Stringer (vv ), true )
900+
901+ testTypeAssert (t , fmt .Stringer (vv ), any (vv ), true )
902+ testTypeAssert (t , any (vv ), fmt .Stringer (vv ), true )
903+ testTypeAssert (t , fmt .Stringer (vv ), interface { M () }(vv ), true )
904+ testTypeAssert (t , interface { M () }(vv ), fmt .Stringer (vv ), true )
905+
906+ testTypeAssert (t , any (int (1 )), int (1 ), true )
907+ testTypeAssert (t , any (int (1 )), byte (0 ), false )
908+ testTypeAssert (t , fmt .Stringer (vv ), vv , true )
909+ }
910+
911+ func testTypeAssert [T comparable , V any ](t * testing.T , val V , wantVal T , wantOk bool ) {
912+ t .Helper ()
913+
914+ v , ok := TypeAssert [T ](ValueOf (& val ).Elem ())
915+ if v != wantVal || ok != wantOk {
916+ t .Errorf ("TypeAssert[%v](%#v) = (%#v, %v); want = (%#v, %v)" , TypeFor [T ](), val , v , ok , wantVal , wantOk )
917+ }
918+
919+ // Additionally make sure that TypeAssert[T](v) behaves in the same way as v.Interface().(T).
920+ v2 , ok2 := ValueOf (& val ).Elem ().Interface ().(T )
921+ if v != v2 || ok != ok2 {
922+ t .Errorf ("reflect.ValueOf(%#v).Interface().(%v) = (%#v, %v); want = (%#v, %v)" , val , TypeFor [T ](), v2 , ok2 , v , ok )
923+ }
924+ }
925+
926+ type testTypeWithMethod struct { val string }
927+
928+ func (v testTypeWithMethod ) String () string { return v .val }
929+ func (v testTypeWithMethod ) M () {}
930+
931+ func TestTypeAssertPanic (t * testing.T ) {
932+ t .Run ("zero val" , func (t * testing.T ) {
933+ defer func () { recover () }()
934+ TypeAssert [int ](Value {})
935+ t .Fatalf ("TypeAssert did not panic" )
936+ })
937+ t .Run ("read only" , func (t * testing.T ) {
938+ defer func () { recover () }()
939+ TypeAssert [int ](ValueOf (& testTypeWithMethod {}).FieldByName ("val" ))
940+ t .Fatalf ("TypeAssert did not panic" )
941+ })
942+ }
0 commit comments