github.com/mattn/anko@v0.1.10/ast/astutil/walk_test.go (about) 1 package astutil 2 3 import ( 4 "errors" 5 "fmt" 6 "testing" 7 8 "github.com/mattn/anko/ast" 9 "github.com/mattn/anko/parser" 10 ) 11 12 const ( 13 goodSrc string = ` 14 var fmt = import("fmt") 15 16 a = "1" 17 b = 2 18 m = {} 19 func testA(arg1, arg2, arg3) { 20 v, ok = m["foo"] 21 return "A" + arg1 + arg2 + arg3 22 } 23 24 func Main(arg1) { 25 fmt.Println("enter Main") 26 b = testA(1, 2, 3) + Tester() 27 28 if b == 0 { 29 fmt.Println("b is 0") 30 } else if b == 1 { 31 fmt.Println("b is 1") 32 } else { 33 fmt.Println("b is other") 34 } 35 36 switch arg1 { 37 case 0: 38 fmt.Println("arg0 is 0") 39 case 1: 40 fmt.Println("arg0 is 1") 41 default: 42 fmt.Println("arg0 is other") 43 } 44 45 try { 46 throw "WTF!" 47 } catch e { 48 fmt.Println(e) 49 } 50 51 for n = 0; n < 3; n++ { 52 if n < 2 { 53 continue 54 } 55 fmt.Println(n) 56 } 57 58 for n in [1, 2, 3, 4, 5] { 59 fmt.Println(n) 60 if n > 3 { 61 break 62 } 63 } 64 65 n = 0 66 for n < 3 { 67 n++ 68 } 69 70 a = {"foo": "bar"} 71 a.foo = "baz" 72 if a["foo"] == "zoo" { 73 fmt.Println("foo is zoo") 74 } 75 fmt.Println(a["foo"] == "zoo" ? "zoo" : "baz") 76 77 c = make(chan int64) 78 79 go func() { 80 c <- 1 81 c <- 2 82 c <- 3 83 }() 84 85 println(<-c) 86 println(<-c) 87 println(<-c) 88 89 v = make([]int, 3) 90 fmt.Println("sizeof v is ", len(v)) 91 92 x = 1 93 y = (&x) 94 *y = 2 95 fmt.Println(x) 96 97 x, y = !x, 2 98 fmt.Println(x, y) 99 100 x = new(string) 101 fmt.Println(x) 102 103 var f = func() { 104 return "foo" 105 } 106 x = f()[0:1] 107 y = f()[0] 108 fmt.Println(x == y ? true : false) 109 } 110 111 func Tester() { 112 return "YES" 113 } 114 115 func testLen() { 116 return len("test") 117 } 118 119 fmt.Println(Main(1)) 120 ` 121 ) 122 123 func TestWalk(t *testing.T) { 124 stmts, err := parser.ParseSrc(goodSrc) 125 if err != nil { 126 t.Fatal(err) 127 } 128 var mainFound bool 129 var lenFound bool 130 err = Walk(stmts, func(e interface{}) error { 131 switch exp := e.(type) { 132 case *ast.CallExpr: 133 switch exp.Name { 134 case `testA`: 135 if len(exp.SubExprs) != 3 { 136 return errors.New("invalid parameter count") 137 } 138 case `Main`: 139 if len(exp.SubExprs) != 1 { 140 return errors.New("invalid parameter count") 141 } 142 case `Tester`: 143 if len(exp.SubExprs) != 0 { 144 return errors.New("invalid parameter count") 145 } 146 } 147 case *ast.FuncExpr: 148 if !mainFound && exp.Name == `Main` { 149 mainFound = true 150 } else if mainFound && exp.Name == `Main` { 151 return errors.New("Main redefined") 152 } 153 case *ast.LenExpr: 154 lenFound = true 155 } 156 return nil 157 }) 158 if err != nil { 159 t.Fatal(err) 160 } 161 if !mainFound { 162 t.Fatal("Main not found") 163 } 164 if !lenFound { 165 t.Fatal("len not found") 166 } 167 } 168 169 func Example_astWalk() { 170 src := ` 171 var fmt = import("fmt") 172 173 func TestFunc(arg1, arg2, arg3) { 174 return (arg1 + arg2) * arg3 175 } 176 177 func Main() { 178 return TestFunc(1, 2, 3) + BuiltinFuncX(1, 2, 3) 179 } 180 181 fmt.Println(Main()) 182 ` 183 stmts, err := parser.ParseSrc(src) 184 if err != nil { 185 fmt.Println("ERROR: ", err) 186 return 187 } 188 var mainFound bool 189 err = Walk(stmts, func(e interface{}) error { 190 switch e := e.(type) { 191 case *ast.CallExpr: 192 //check if the BuiltinFuncX is getting the right number of args 193 if e.Name == `BuiltinFuncX` && len(e.SubExprs) != 3 { 194 return errors.New("invalid number of arguments to BuiltinFuncX") 195 } 196 case *ast.FuncExpr: 197 if !mainFound && e.Name == `Main` { 198 if len(e.Params) != 0 { 199 return errors.New("Too many args to main") 200 } 201 mainFound = true 202 } else if mainFound && e.Name == `Main` { 203 return errors.New("Main redefined") 204 } 205 } 206 return nil 207 }) 208 if err != nil { 209 fmt.Println("ERROR: ", err) 210 return 211 } 212 if !mainFound { 213 fmt.Println("ERROR: Main not found") 214 } 215 } 216 217 func TestBadCode(t *testing.T) { 218 var codes = []string{ 219 `const 1 = 2`, 220 `a["foo"] = 2, 3`, 221 `if a, 2 {}`, 222 `if break {}`, 223 `if a { else }`, 224 `if a { } else foo { }`, 225 `try a { } else { }`, 226 `try { } catch 1, 2 { }`, 227 `throw 1, 2`, 228 `for.true`, 229 `switch { var }`, 230 `case { var }`, 231 `v, ok = { "foo": "bar" }[const 1]`, 232 } 233 for _, code := range codes { 234 _, err := parser.ParseSrc(code) 235 if err == nil { 236 t.Fatalf("code %q should fail", code) 237 } 238 } 239 }