nswrap/types/main_test.go

621 lines
14 KiB
Go

package types
import (
"fmt"
"reflect"
"testing"
)
func TestParse(t *testing.T) {
i := 1
chk := func(input string, n *Node, expected string) {
t.Run(fmt.Sprintf("Parse%d", i), func(t *testing.T) {
if n.String() != expected {
t.Errorf("Mismatch parsing %s -- Got:\n%s\nExpected:\n%s\n", input, n.String(), expected)
}
})
i++
}
runParseTest := func(input, expected string) {
n, err := Parse(input)
if err != nil {
t.Errorf("Parse error parsing %s\n", input)
}
chk(input, n, expected)
}
runSigTest := func(input, expected string) {
rem, n := MethodSignature(input, NewNode("AST"))
if rem != "" {
t.Errorf("Parse error parsing %s. Remainder = %s\n", input, rem)
}
chk(input, n, expected)
}
runParseTest(`int`,
`<TypeName> ''
-<TypeSpecifier> 'int'
`)
runParseTest(`int`,
`<TypeName> ''
-<TypeSpecifier> 'int'
`)
runParseTest(`char*`,
`<TypeName> ''
-<TypeSpecifier> 'char'
-<Pointer> '*'
`)
runParseTest(`struct Str`,
`<TypeName> ''
-<Struct> 'struct'
--<Identifier> 'Str'
`)
runParseTest(`uint`,
`<TypeName> ''
-<TypedefName> 'uint'
`)
runParseTest(`uind`,
`<TypeName> ''
-<TypedefName> 'uind'
`)
runParseTest(`void ()`,
`<TypeName> ''
-<TypeSpecifier> 'void'
-<Function> ''
`)
runParseTest(`void (*)(struct NSRange)`,
`<TypeName> ''
-<TypeSpecifier> 'void'
-<Parenthesized> ''
--<Pointer> '*'
-<Function> ''
--<ParameterDeclaration> ''
---<Struct> 'struct'
----<Identifier> 'NSRange'
`)
runParseTest(`void (* _Nullable)(int)`,
`<TypeName> ''
-<TypeSpecifier> 'void'
-<Parenthesized> ''
--<Pointer> '*'
--<NullableAnnotation> '_Nullable'
-<Function> ''
--<ParameterDeclaration> ''
---<TypeSpecifier> 'int'
`)
runParseTest(`NSRange[3]`,
`<TypeName> ''
-<TypedefName> 'NSRange'
-<Array> ''
--<Length> '3'
`)
runParseTest(`struct _NSRange[3]`,
`<TypeName> ''
-<Struct> 'struct'
--<Identifier> '_NSRange'
-<Array> ''
--<Length> '3'
`)
runParseTest(`struct _NSRange (*)(int, char[])`,
`<TypeName> ''
-<Struct> 'struct'
--<Identifier> '_NSRange'
-<Parenthesized> ''
--<Pointer> '*'
-<Function> ''
--<ParameterDeclaration> ''
---<TypeSpecifier> 'int'
--<ParameterDeclaration> ''
---<TypeSpecifier> 'char'
---<Array> ''
`)
runParseTest(`struct _NSRange (*)(int, char[],NSRange)`,
`<TypeName> ''
-<Struct> 'struct'
--<Identifier> '_NSRange'
-<Parenthesized> ''
--<Pointer> '*'
-<Function> ''
--<ParameterDeclaration> ''
---<TypeSpecifier> 'int'
--<ParameterDeclaration> ''
---<TypeSpecifier> 'char'
---<Array> ''
--<ParameterDeclaration> ''
---<TypedefName> 'NSRange'
`)
runParseTest(`struct _NSRange (*)(int, char[],struct _NSRange)`,
`<TypeName> ''
-<Struct> 'struct'
--<Identifier> '_NSRange'
-<Parenthesized> ''
--<Pointer> '*'
-<Function> ''
--<ParameterDeclaration> ''
---<TypeSpecifier> 'int'
--<ParameterDeclaration> ''
---<TypeSpecifier> 'char'
---<Array> ''
--<ParameterDeclaration> ''
---<Struct> 'struct'
----<Identifier> '_NSRange'
`)
runParseTest(`mytype`,
`<TypeName> ''
-<TypedefName> 'mytype'
`)
runParseTest(`const int`,
`<TypeName> ''
-<TypeQualifier> 'const'
-<TypeSpecifier> 'int'
`)
runParseTest(`int[*]`,
`<TypeName> ''
-<TypeSpecifier> 'int'
-<Array> ''
--<Length> '*'
`)
runParseTest(`int[3][5]`,
`<TypeName> ''
-<TypeSpecifier> 'int'
-<Array> ''
--<Length> '3'
-<Array> ''
--<Length> '5'
`)
runParseTest(`int *`,
`<TypeName> ''
-<TypeSpecifier> 'int'
-<Pointer> '*'
`)
runParseTest(`int * _Nonnull`,
`<TypeName> ''
-<TypeSpecifier> 'int'
-<Pointer> '*'
-<NullableAnnotation> '_Nonnull'
`)
runParseTest(`int **`,
`<TypeName> ''
-<TypeSpecifier> 'int'
-<Pointer> '*'
-<Pointer> '*'
`)
runParseTest(`int *[3]`,
`<TypeName> ''
-<TypeSpecifier> 'int'
-<Pointer> '*'
-<Array> ''
--<Length> '3'
`)
runParseTest(`int (*)[3]`,
`<TypeName> ''
-<TypeSpecifier> 'int'
-<Parenthesized> ''
--<Pointer> '*'
-<Array> ''
--<Length> '3'
`)
runParseTest(`int (*)[*]`,
`<TypeName> ''
-<TypeSpecifier> 'int'
-<Parenthesized> ''
--<Pointer> '*'
-<Array> ''
--<Length> '*'
`)
runParseTest(`int *()`,
`<TypeName> ''
-<TypeSpecifier> 'int'
-<Pointer> '*'
-<Function> ''
`)
runParseTest(`int *(char*)`,
`<TypeName> ''
-<TypeSpecifier> 'int'
-<Pointer> '*'
-<Function> ''
--<ParameterDeclaration> ''
---<TypeSpecifier> 'char'
---<Pointer> '*'
`)
runParseTest(`RANGE *(char*)`,
`<TypeName> ''
-<TypedefName> 'RANGE'
-<Pointer> '*'
-<Function> ''
--<ParameterDeclaration> ''
---<TypeSpecifier> 'char'
---<Pointer> '*'
`)
runParseTest(`int (*)(void)`,
`<TypeName> ''
-<TypeSpecifier> 'int'
-<Parenthesized> ''
--<Pointer> '*'
-<Function> ''
--<ParameterDeclaration> ''
---<TypeSpecifier> 'void'
`)
runParseTest(`int (*)(int, unsigned int)`,
`<TypeName> ''
-<TypeSpecifier> 'int'
-<Parenthesized> ''
--<Pointer> '*'
-<Function> ''
--<ParameterDeclaration> ''
---<TypeSpecifier> 'int'
--<ParameterDeclaration> ''
---<TypeSpecifier> 'unsigned'
---<TypeSpecifier> 'int'
`)
runParseTest(`int (* _Nullable)(int, unsigned int)`,
`<TypeName> ''
-<TypeSpecifier> 'int'
-<Parenthesized> ''
--<Pointer> '*'
--<NullableAnnotation> '_Nullable'
-<Function> ''
--<ParameterDeclaration> ''
---<TypeSpecifier> 'int'
--<ParameterDeclaration> ''
---<TypeSpecifier> 'unsigned'
---<TypeSpecifier> 'int'
`)
runParseTest(`int (*const [])(unsigned int, ...)`,
`<TypeName> ''
-<TypeSpecifier> 'int'
-<Parenthesized> ''
--<Pointer> '*'
--<TypeQualifier> 'const'
--<Array> ''
-<Function> ''
--<ParameterDeclaration> ''
---<TypeSpecifier> 'unsigned'
---<TypeSpecifier> 'int'
--<ParameterDeclaration> ''
---<Ellipsis> '...'
`)
runParseTest(`BOOL (* _Nullable)()`,
`<TypeName> ''
-<TypedefName> 'BOOL'
-<Parenthesized> ''
--<Pointer> '*'
--<NullableAnnotation> '_Nullable'
-<Function> ''
`)
runParseTest(`BOOL (* _Nullable)(const void * _Nonnull, const void * _Nonnull)`,
`<TypeName> ''
-<TypedefName> 'BOOL'
-<Parenthesized> ''
--<Pointer> '*'
--<NullableAnnotation> '_Nullable'
-<Function> ''
--<ParameterDeclaration> ''
---<TypeQualifier> 'const'
---<TypeSpecifier> 'void'
---<Pointer> '*'
---<NullableAnnotation> '_Nonnull'
--<ParameterDeclaration> ''
---<TypeQualifier> 'const'
---<TypeSpecifier> 'void'
---<Pointer> '*'
---<NullableAnnotation> '_Nonnull'
`)
runParseTest(`BOOL (* _Nullable)(const void * _Nonnull, const void * _Nonnull, int (* _Nullable)(const void * _Nonnull))`,
`<TypeName> ''
-<TypedefName> 'BOOL'
-<Parenthesized> ''
--<Pointer> '*'
--<NullableAnnotation> '_Nullable'
-<Function> ''
--<ParameterDeclaration> ''
---<TypeQualifier> 'const'
---<TypeSpecifier> 'void'
---<Pointer> '*'
---<NullableAnnotation> '_Nonnull'
--<ParameterDeclaration> ''
---<TypeQualifier> 'const'
---<TypeSpecifier> 'void'
---<Pointer> '*'
---<NullableAnnotation> '_Nonnull'
--<ParameterDeclaration> ''
---<TypeSpecifier> 'int'
---<Parenthesized> ''
----<Pointer> '*'
----<NullableAnnotation> '_Nullable'
---<Function> ''
----<ParameterDeclaration> ''
-----<TypeQualifier> 'const'
-----<TypeSpecifier> 'void'
-----<Pointer> '*'
-----<NullableAnnotation> '_Nonnull'
`)
runParseTest(`BOOL (* _Nullable)(const void * _Nonnull, const void * _Nonnull, NSUInteger (* _Nullable)(const void * _Nonnull))`,
`<TypeName> ''
-<TypedefName> 'BOOL'
-<Parenthesized> ''
--<Pointer> '*'
--<NullableAnnotation> '_Nullable'
-<Function> ''
--<ParameterDeclaration> ''
---<TypeQualifier> 'const'
---<TypeSpecifier> 'void'
---<Pointer> '*'
---<NullableAnnotation> '_Nonnull'
--<ParameterDeclaration> ''
---<TypeQualifier> 'const'
---<TypeSpecifier> 'void'
---<Pointer> '*'
---<NullableAnnotation> '_Nonnull'
--<ParameterDeclaration> ''
---<TypedefName> 'NSUInteger'
---<Parenthesized> ''
----<Pointer> '*'
----<NullableAnnotation> '_Nullable'
---<Function> ''
----<ParameterDeclaration> ''
-----<TypeQualifier> 'const'
-----<TypeSpecifier> 'void'
-----<Pointer> '*'
-----<NullableAnnotation> '_Nonnull'
`)
runParseTest(`NSEnumerator<ObjectType> * _Nonnull`,
`<TypeName> ''
-<TypedefName> 'NSEnumerator'
-<GenericList> ''
--<Generic> ''
---<TypedefName> 'ObjectType'
-<Pointer> '*'
-<NullableAnnotation> '_Nonnull'
`)
runParseTest(`NSArray<NSString *> * _Nonnull`,
`<TypeName> ''
-<TypedefName> 'NSArray'
-<GenericList> ''
--<Generic> ''
---<TypedefName> 'NSString'
---<Pointer> '*'
-<Pointer> '*'
-<NullableAnnotation> '_Nonnull'
`)
runParseTest(`id _Nonnull (^ _Nonnull)(id _Nullable, NSArray<NSExpression *> * _Nonnull, NSMutableDictionary * _Nullable)`,
`<TypeName> ''
-<TypedefName> 'id'
-<NullableAnnotation> '_Nonnull'
-<Parenthesized> ''
--<Block> '^'
--<NullableAnnotation> '_Nonnull'
-<Function> ''
--<ParameterDeclaration> ''
---<TypedefName> 'id'
---<NullableAnnotation> '_Nullable'
--<ParameterDeclaration> ''
---<TypedefName> 'NSArray'
---<GenericList> ''
----<Generic> ''
-----<TypedefName> 'NSExpression'
-----<Pointer> '*'
---<Pointer> '*'
---<NullableAnnotation> '_Nonnull'
--<ParameterDeclaration> ''
---<TypedefName> 'NSMutableDictionary'
---<Pointer> '*'
---<NullableAnnotation> '_Nullable'
`)
runSigTest(`(void)pressed`,
`<MethodSignature> ''
-<TypeName> ''
--<TypeSpecifier> 'void'
-<Identifier> 'pressed'
`)
runSigTest(`(void)performSelector:(SEL)aSelector target:(id)target argument:(id)arg order:(NSUInteger)order modes:(NSArray<NSRunLoopMode> *)modes`,
`<MethodSignature> ''
-<TypeName> ''
--<TypeSpecifier> 'void'
-<Identifier> 'performSelector'
-<MethodParameter> ''
--<TypeName> ''
---<TypedefName> 'SEL'
--<Identifier> 'aSelector'
-<MethodParameter> ''
--<Identifier> 'target'
--<TypeName> ''
---<TypedefName> 'id'
--<Identifier> 'target'
-<MethodParameter> ''
--<Identifier> 'argument'
--<TypeName> ''
---<TypedefName> 'id'
--<Identifier> 'arg'
-<MethodParameter> ''
--<Identifier> 'order'
--<TypeName> ''
---<TypedefName> 'NSUInteger'
--<Identifier> 'order'
-<MethodParameter> ''
--<Identifier> 'modes'
--<TypeName> ''
---<TypedefName> 'NSArray'
---<GenericList> ''
----<Generic> ''
-----<TypedefName> 'NSRunLoopMode'
---<Pointer> '*'
--<Identifier> 'modes'
`)
}
func TestFuncs(t *testing.T) {
i := 1
var n *Node
var err error
f := func(input string, actual, expected interface{}) {
t.Run(fmt.Sprintf("TestFunc%d", i), func(t *testing.T) {
if err != nil {
t.Errorf("Error parsing %s\n", input)
}
if actual == nil && expected == nil {
return
}
if !reflect.DeepEqual(actual, expected) {
t.Errorf("Test failed for %s\n", input)
}
})
i++
}
str := "int*"
n, err = Parse(str)
f(str, n.HasFunc(), false)
str = "int (*)(void)"
n, err = Parse(str)
f(str, n.HasFunc(), true)
n, err = nil, nil
f("", n.HasFunc(), false)
f("", n.IsId(), false)
f("", n.IsFunction(), false)
f("", n.IsInstancetype(), false)
f("", n.IsArray(), false)
f("", n.IsStruct(), false)
if n.BaseType() != nil {
t.Errorf("BaseType() for nil node is not nil\n")
}
if n.PointsTo() != nil {
t.Errorf("PointsTo() for nil node is not nil\n")
}
if n.ReturnType() != nil {
t.Errorf("ReturnType() for nil node is not nil\n")
}
f("", n.String(), "")
f("", n.Qualifiers(), "")
f("", n.Annotations(), "")
str = "int"
n, err = Parse(str)
f(str, n.isIndirect("Pointer"), false)
if n.ReturnType() != nil {
t.Errorf("Return type for non-function is not nil\n")
}
str = "int*"
n, err = Parse(str)
f(str, n.isIndirect("Pointer"), true)
f(str, n.isIndirect("Array"), false)
str = "int* _Nullable"
n, err = Parse(str)
f(str, n.isIndirect("Pointer"), true)
str = "int* _Nonnull"
n, err = Parse(str)
f(str, n.isIndirect("Pointer"), true)
f(str, n.CType(), "int* _Nonnull")
f(str, n.CTypeSimplified(), "int*")
f(str, n.Annotations(), "_Nonnull")
n, err = Parse("int[]")
n2, err2 := Parse("int")
if err2 != nil {
t.Errorf("Cannot parse int")
}
f(str, n.isIndirect("Pointer"), false)
f(str, n.isIndirect("Array"), true)
f(str, n.ArrayOf(), n2)
f(str, n.CType(), "int[]")
f(str, n.CTypeSimplified(), "int[]")
str = "const int*[]"
n, err = Parse(str)
f(str, n.isIndirect("Array"), true)
f(str, n.Qualifiers(), "const")
str = "int (*)[]"
n, err = Parse(str)
f(str, n.isIndirect("Array"), true)
f(str, n.isIndirect("Pointer"), true)
str = "int (* _Nullable * _Nonnull)[]"
n, err = Parse(str)
f(str, n.isIndirect("Pointer"), true)
str = "int (*)(void)"
n, err = Parse(str)
n2, err2 = Parse("int(void)")
if err2 != nil {
t.Errorf("Failed to parse int(void)")
}
f(str, n.PointsTo(), n2)
f(str, n.IsPointer(), true)
f(str, n.IsFunction(), false)
f(str, n.CType(), "int (*)(void)")
str = "int *(void)"
n, err = Parse(str)
f(str, n.IsFunction(), true)
n2, _ = Parse("int*")
f(str, n.ReturnType(), n2)
str = "__kindof NSRange"
n, err = Parse(str)
f(str, n.IsStruct(), false)
f(str, n.IsInstancetype(), false)
str = "struct NSRange"
n, err = Parse(str)
f(str, n.IsStruct(), true)
f(str, n.IsFunction(), false)
str = "id"
n, err = Parse(str)
f(str, n.IsId(), true)
f(str, n.IsPointer(), true)
str = "int * _Nullable * _Nonnull"
n, err = Parse(str)
n2, _ = Parse("int")
f(str, n.BaseType(), n2)
str = "__kindof id"
n, err = Parse(str)
f(str, n.IsId(), true)
f(str, n.IsPointer(), true)
str = "NSArray<ObjectType> *"
n, err = Parse(str)
f(str, n.CType(), "NSArray <ObjectType>*")
f(str, n.CTypeSimplified(), "NSArray*")
str = "NSRange *(int, NSRange *)"
n, err = Parse(str)
f(str, n.renameTypedefs("NSRange", "struct NSRange"), true)
f(str, n.CType(), "struct NSRange* (int, struct NSRange*)")
str = "int*%&#$"
n, err = Parse(str)
if err == nil {
fmt.Printf("%s\n", n.String())
t.Errorf("Parse should have failed for %s\n", str)
}
var r func(i int) *Node
r = func(i int) *Node {
n := &Node{}
if i > 0 {
n.Children = []*Node{r(i - 1)}
}
return n
}
n = r(150)
str = n.String()
if str[len(str)-8:] != "too deep" {
fmt.Printf(str[len(str)-8:])
t.Errorf("Deep recursion did not produce an error from (*Node)String()\n")
}
}
func ExampleDebug() {
Debug = true
dbg("one %s two %d", "string", 15)
// Output: one string two 15
Debug = false
}