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`, ` '' - 'int' `) runParseTest(`int`, ` '' - 'int' `) runParseTest(`char*`, ` '' - 'char' - '*' `) runParseTest(`struct Str`, ` '' - 'struct' -- 'Str' `) runParseTest(`uint`, ` '' - 'uint' `) runParseTest(`uind`, ` '' - 'uind' `) runParseTest(`void ()`, ` '' - 'void' - '' `) runParseTest(`void (*)(struct NSRange)`, ` '' - 'void' - '' -- '*' - '' -- '' --- 'struct' ---- 'NSRange' `) runParseTest(`void (* _Nullable)(int)`, ` '' - 'void' - '' -- '*' -- '_Nullable' - '' -- '' --- 'int' `) runParseTest(`NSRange[3]`, ` '' - 'NSRange' - '' -- '3' `) runParseTest(`struct _NSRange[3]`, ` '' - 'struct' -- '_NSRange' - '' -- '3' `) runParseTest(`struct _NSRange (*)(int, char[])`, ` '' - 'struct' -- '_NSRange' - '' -- '*' - '' -- '' --- 'int' -- '' --- 'char' --- '' `) runParseTest(`struct _NSRange (*)(int, char[],NSRange)`, ` '' - 'struct' -- '_NSRange' - '' -- '*' - '' -- '' --- 'int' -- '' --- 'char' --- '' -- '' --- 'NSRange' `) runParseTest(`struct _NSRange (*)(int, char[],struct _NSRange)`, ` '' - 'struct' -- '_NSRange' - '' -- '*' - '' -- '' --- 'int' -- '' --- 'char' --- '' -- '' --- 'struct' ---- '_NSRange' `) runParseTest(`mytype`, ` '' - 'mytype' `) runParseTest(`const int`, ` '' - 'const' - 'int' `) runParseTest(`int[*]`, ` '' - 'int' - '' -- '*' `) runParseTest(`int[3][5]`, ` '' - 'int' - '' -- '3' - '' -- '5' `) runParseTest(`int *`, ` '' - 'int' - '*' `) runParseTest(`int * _Nonnull`, ` '' - 'int' - '*' - '_Nonnull' `) runParseTest(`int **`, ` '' - 'int' - '*' - '*' `) runParseTest(`int *[3]`, ` '' - 'int' - '*' - '' -- '3' `) runParseTest(`int (*)[3]`, ` '' - 'int' - '' -- '*' - '' -- '3' `) runParseTest(`int (*)[*]`, ` '' - 'int' - '' -- '*' - '' -- '*' `) runParseTest(`int *()`, ` '' - 'int' - '*' - '' `) runParseTest(`int (*)(void)`, ` '' - 'int' - '' -- '*' - '' -- '' --- 'void' `) runParseTest(`int (*)(int, unsigned int)`, ` '' - 'int' - '' -- '*' - '' -- '' --- 'int' -- '' --- 'unsigned' --- 'int' `) runParseTest(`int (* _Nullable)(int, unsigned int)`, ` '' - 'int' - '' -- '*' -- '_Nullable' - '' -- '' --- 'int' -- '' --- 'unsigned' --- 'int' `) runParseTest(`int (*const [])(unsigned int, ...)`, ` '' - 'int' - '' -- '*' -- 'const' -- '' - '' -- '' --- 'unsigned' --- 'int' -- '' --- '...' `) runParseTest(`BOOL (* _Nullable)()`, ` '' - 'BOOL' - '' -- '*' -- '_Nullable' - '' `) runParseTest(`BOOL (* _Nullable)(const void * _Nonnull, const void * _Nonnull)`, ` '' - 'BOOL' - '' -- '*' -- '_Nullable' - '' -- '' --- 'const' --- 'void' --- '*' --- '_Nonnull' -- '' --- 'const' --- 'void' --- '*' --- '_Nonnull' `) runParseTest(`BOOL (* _Nullable)(const void * _Nonnull, const void * _Nonnull, int (* _Nullable)(const void * _Nonnull))`, ` '' - 'BOOL' - '' -- '*' -- '_Nullable' - '' -- '' --- 'const' --- 'void' --- '*' --- '_Nonnull' -- '' --- 'const' --- 'void' --- '*' --- '_Nonnull' -- '' --- 'int' --- '' ---- '*' ---- '_Nullable' --- '' ---- '' ----- 'const' ----- 'void' ----- '*' ----- '_Nonnull' `) runParseTest(`BOOL (* _Nullable)(const void * _Nonnull, const void * _Nonnull, NSUInteger (* _Nullable)(const void * _Nonnull))`, ` '' - 'BOOL' - '' -- '*' -- '_Nullable' - '' -- '' --- 'const' --- 'void' --- '*' --- '_Nonnull' -- '' --- 'const' --- 'void' --- '*' --- '_Nonnull' -- '' --- 'NSUInteger' --- '' ---- '*' ---- '_Nullable' --- '' ---- '' ----- 'const' ----- 'void' ----- '*' ----- '_Nonnull' `) runParseTest(`NSEnumerator * _Nonnull`, ` '' - 'NSEnumerator' - '' -- '' --- 'ObjectType' - '*' - '_Nonnull' `) runParseTest(`NSArray * _Nonnull`, ` '' - 'NSArray' - '' -- '' --- 'NSString' --- '*' - '*' - '_Nonnull' `) runParseTest(`id _Nonnull (^ _Nonnull)(id _Nullable, NSArray * _Nonnull, NSMutableDictionary * _Nullable)`, ` '' - 'id' - '_Nonnull' - '' -- '^' -- '_Nonnull' - '' -- '' --- 'id' --- '_Nullable' -- '' --- 'NSArray' --- '' ---- '' ----- 'NSExpression' ----- '*' --- '*' --- '_Nonnull' -- '' --- 'NSMutableDictionary' --- '*' --- '_Nullable' `) runSigTest(`(void)pressed`, ` '' - '' -- 'void' - 'pressed' `) runSigTest(`(void)performSelector:(SEL)aSelector target:(id)target argument:(id)arg order:(NSUInteger)order modes:(NSArray *)modes`, ` '' - '' -- 'void' - 'performSelector' - '' -- '' --- 'SEL' -- 'aSelector' - '' -- 'target' -- '' --- 'id' -- 'target' - '' -- 'argument' -- '' --- 'id' -- 'arg' - '' -- 'order' -- '' --- 'NSUInteger' -- 'order' - '' -- 'modes' -- '' --- 'NSArray' --- '' ---- '' ----- 'NSRunLoopMode' --- '*' -- '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 *" n,err = Parse(str) f(str,n.CType(),"NSArray *") 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 }