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 *" 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" 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(), ` '' - 'id' - '' -- '' --- 'MyClass' --- '*' `) 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" tp2 = NewTypeFromString(str,"MyClass") chk(tp.BaseType(),tp) str = "id*" 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`) }