nswrap/types/convert_test.go

325 lines
7.2 KiB
Go

package types
import (
"fmt"
"reflect"
"testing"
)
func isNil(x interface{}) bool {
return x == nil ||
(reflect.ValueOf(x).Kind() == reflect.Ptr &&
reflect.ValueOf(x).IsNil())
}
func TestType(t *testing.T) {
i := 1
var str string
var n *Node
var tp *Type
chk := func(actual, expected interface{}) {
t.Run(fmt.Sprintf("TestType%d",i),func(t *testing.T) {
if isNil(actual) && isNil(expected) { return }
if !reflect.DeepEqual(actual,expected) {
t.Errorf("Test failed for %s\n",str)
fmt.Println("Actual:\n",actual)
fmt.Println("Expected:\n",expected)
}
})
}
chk_newtype := func() {
tp = NewTypeFromString(str,"")
chk(tp,&Type{ Node: n, Class: "" })
}
//tests on nil Type pointers:
chk(tp.BaseType(),nil)
chk(tp.CType(),"")
chk(tp.IsFunction(),false)
chk(tp.IsPointer(),false)
chk(tp.IsFunctionPtr(),false)
chk(tp.IsValist(),false)
str = "int"
n = &Node{ "TypeName", "", []*Node{
&Node{ "TypeSpecifier", "int", []*Node{} } } }
chk_newtype()
tint := tp
str = "NSObject"
n = &Node{ "TypeName", "", []*Node{
&Node{ "TypedefName", "NSObject", []*Node{} } } }
chk_newtype()
nso := tp
str = "NSString"
n = &Node{ "TypeName", "", []*Node{
&Node{ "TypedefName", "NSString", []*Node{} } } }
chk_newtype()
nst := tp
str = "NSString*"
n = &Node{ "TypeName", "", []*Node{
&Node{ "TypedefName", "NSString", []*Node{} },
&Node{ "Pointer", "*", []*Node{} } } }
chk_newtype()
chk(tp.IsPointer(),true)
chk(tp.Typedef(),nil)
tpNSString := tp
str = "myTypedef"
AddTypedef("myTypedef",tp)
n = &Node { "TypeName", "", []*Node{
&Node{ "TypedefName", "myTypedef", []*Node{} }}}
chk_newtype()
chk(tp.Typedef(),tpNSString)
str = "const NSArray <ObjectType * _Nonnull> *"
n = &Node{ "TypeName", "", []*Node{
&Node{ "TypeQualifier", "const", []*Node{} },
&Node{ "TypedefName", "NSArray", []*Node{} },
&Node{ "GenericList", "", []*Node{
&Node{ "Generic", "", []*Node{
&Node{ "TypedefName", "ObjectType", []*Node{} },
&Node{ "Pointer", "*", []*Node{} },
&Node{ "NullableAnnotation", "_Nonnull", []*Node{} } } } } },
&Node{ "Pointer", "*", []*Node{} } } }
chk_newtype()
chk(tp.CType(),"NSArray*")
chk(tp.CTypeAttrib(),"const NSArray*")
chk(tp.CGoType(),"*C.NSArray")
chk(tp.GoType(),"*NSArray")
SetTypeParam("MyClass","ObjectType","MyClass")
str = "id<ObjectType *>"
n = &Node{ "TypeName", "", []*Node{
&Node{ "TypedefName", "id", []*Node{} },
&Node{ "GenericList", "", []*Node{
&Node{ "Generic", "", []*Node{
&Node{ "TypedefName", "ObjectType", []*Node{} },
&Node{ "Pointer", "*", []*Node{} } } } } } } }
chk_newtype()
tp = NewType(n,"MyClass")
chk(tp.CType(),"NSObject*")
chk(tp.String(),
`<TypeName> ''
-<TypedefName> 'id'
-<GenericList> ''
--<Generic> ''
---<TypedefName> 'MyClass'
---<Pointer> '*'
`)
x,_ := clean(nil,"MyClass")
chk(x,nil)
SetSuper("NSString","NSObject")
chk(Super("NSString"),"NSObject")
tp2 := tp.CloneToClass("NSObject")
chk(tp2.Class,"NSObject")
str = "you can't parse this"
tp = NewTypeFromString(str,"")
tp2 = &Type{}
chk(tp,tp2)
str = "id<ObjectType *>"
tp2 = NewTypeFromString(str,"MyClass")
chk(tp.BaseType(),tp)
str = "id<ObjectType *>*"
tp = NewTypeFromString(str,"MyClass")
chk(tp.BaseType(),tp2)
chk(tp.PointsTo(),tp2)
AddTypedef("myTypedef",tp)
str = "myTypedef"
n = &Node{ "TypeName", "", []*Node{
&Node{ "TypedefName", "myTypedef", []*Node{} } } }
chk_newtype()
chk(tp.PointsTo(),tp2)
chk(tp2.PointsTo(),nil)
chk(tp.GoTypeDecl(),`
type MyTypedef **C.NSObject
`)
chk(tp2.GoTypeDecl(),"")
chk(nst.GoTypeDecl(),`
type NSString C.NSString
`)
str = "void"
n = &Node{ "TypeName", "", []*Node{
&Node{ "TypeSpecifier", "void", []*Node{} } } }
chk_newtype()
chk(tp.GoTypeDecl(),"")
void := tp
str = "BOOL"
n,_ = Parse(str)
chk_newtype()
bl := tp
str = "void**"
n,_ = Parse(str)
chk_newtype()
chk(tp.GoType(),"*unsafe.Pointer")
chk(tp.CToGo("var"),"(*unsafe.Pointer)(unsafe.Pointer(var))")
voidpp := tp
Wrap("NSObject")
str = "NSObject*"
n,_ = Parse(str)
chk_newtype()
chk(tp.GoType(),"NSObject")
Wrap("NSString")
chk(nso.GoTypeDecl(),`
type NSObject interface {
Ptr() unsafe.Pointer
}
`)
chk(nso.GoType(),"NSObject")
chk(nst.GoTypeDecl(),`
type NSString struct { Id }
func (o NSString) Ptr() unsafe.Pointer { return o.ptr }
func (o Id) NSString() NSString {
ret := NSString{}
ret.ptr = o.ptr
return ret
}
`)
str = "int(void)"
n,_ = Parse(str)
chk_newtype()
chk(tp.IsFunction(),true)
chk(tp.IsFunctionPtr(),false)
chk(tp.ReturnType().CType(),"int")
str = "int *(void)"
n,_ = Parse(str)
chk_newtype()
chk(tp.IsFunction(),true)
chk(tp.ReturnType().CType(),"int*")
chk(tp.ReturnType().GoType(),"*Int")
fn := tp
AddTypedef("myTypedef",fn)
str = "myTypedef"
n,_ = Parse(str)
chk_newtype()
chk(tp.IsFunction(),true)
chk(tp.IsFunctionPtr(),false)
chk(tp.ReturnType().CType(),"int*")
str = "int (*)(void)"
n,_ = Parse(str)
chk_newtype()
chk(tp.IsFunction(),false)
chk(tp.IsPointer(),true)
chk(tp.IsFunctionPtr(),true)
chk(tp.ReturnType(),nil)
fnptr := tp
AddTypedef("myTypedef",fnptr)
str = "myTypedef"
n,_ = Parse(str)
chk_newtype()
chk(tp.IsFunction(),false)
chk(tp.IsPointer(),true)
chk(tp.IsFunctionPtr(),true)
chk(tp.ReturnType(),nil)
chk(tp.IsValist(),false)
str = "__va_list_tag"
n,_ = Parse(str)
chk_newtype()
chk(tp.IsValist(),true)
str = "GoToC"
var rtype *Type
ptypes := []*Type{ nst, nso, tint, voidpp }
pnames := []string{"p1","p2","p3", "p4"}
snames := []string{"","","",""}
chk_gotoc := func(expected string) {
chk(GoToC("myFun",pnames,snames,rtype,ptypes,false),expected)
}
chk_gotoc("")
rtype = void
chk_gotoc(`C.myFun(p1.Ptr(), p2.Ptr(), (C.int)(p3), unsafe.Pointer(p4))`)
rtype = bl
chk_gotoc(
`ret := (C.myFun(p1.Ptr(), p2.Ptr(), (C.int)(p3), unsafe.Pointer(p4))) != 0
return ret`)
rtype = voidpp
chk_gotoc(
`ret := (*unsafe.Pointer)(unsafe.Pointer(C.myFun(p1.Ptr(), p2.Ptr(), (C.int)(p3), unsafe.Pointer(p4))))
return ret`)
rtype = nst
chk_gotoc(
`ret := NSString{}
ret.ptr = C.myFun(p1.Ptr(), p2.Ptr(), (C.int)(p3), unsafe.Pointer(p4))
return ret`)
rtype = nso
chk_gotoc(
`ret := Id{}
ret.ptr = C.myFun(p1.Ptr(), p2.Ptr(), (C.int)(p3), unsafe.Pointer(p4))
return ret`)
ptypes[1].Variadic = true
chk_gotoc(
`ret := Id{}
ret.ptr = C.myFun(p1.Ptr(), unsafe.Pointer(&p2), (C.int)(p3), unsafe.Pointer(p4))
return ret`)
ptypes[1].Variadic = false
snames[1] = "p2p"
chk_gotoc(
`ret := Id{}
ret.ptr = C.myFun(p1.Ptr(), p2.Ptr(), (C.int)(p3), unsafe.Pointer(p4))
(*p2) = (*p2)[:cap(*p2)]
for i := 0; i < len(*p2); i++ {
if p2p[i] == nil {
(*p2) = (*p2)[:i]
break
}
(*p2)[i].ptr = p2p[i]
}
return ret`)
snames[1] = ""
snames[2] = "p3p"
chk_gotoc(
`ret := Id{}
ret.ptr = C.myFun(p1.Ptr(), p2.Ptr(), unsafe.Pointer(&p3p[0]), unsafe.Pointer(p4))
(*p3) = (*p3)[:cap(*p3)]
for i := 0; i < len(*p3); i++ {
if p3p[i] == nil {
(*p3) = (*p3)[:i]
break
}
(*p3)[i].ptr = p3p[i]
}
return ret`)
chk(GoToC("myFun",pnames,snames,rtype,ptypes,true),
`ret := Id{}
ret.ptr = C.myFun(p1.Ptr(), p2.Ptr(), unsafe.Pointer(&p3p[0]), (**C.void)(p4))
(*p3) = (*p3)[:cap(*p3)]
for i := 0; i < len(*p3); i++ {
if p3p[i] == nil {
(*p3) = (*p3)[:i]
break
}
(*p3)[i].ptr = p3p[i]
}
return ret`)
}