github.com/llvm-mirror/llgo@v0.0.0-20190322182713-bf6f0a60fce1/third_party/gotools/go/ssa/interp/interp_test.go (about) 1 // Copyright 2013 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build !windows,!plan9 6 7 package interp_test 8 9 import ( 10 "bytes" 11 "fmt" 12 "go/build" 13 "os" 14 "path/filepath" 15 "strings" 16 "testing" 17 "time" 18 19 "llvm.org/llgo/third_party/gotools/go/loader" 20 "llvm.org/llgo/third_party/gotools/go/ssa" 21 "llvm.org/llgo/third_party/gotools/go/ssa/interp" 22 "llvm.org/llgo/third_party/gotools/go/types" 23 ) 24 25 // Each line contains a space-separated list of $GOROOT/test/ 26 // filenames comprising the main package of a program. 27 // They are ordered quickest-first, roughly. 28 // 29 // TODO(adonovan): integrate into the $GOROOT/test driver scripts, 30 // golden file checking, etc. 31 var gorootTestTests = []string{ 32 "235.go", 33 "alias1.go", 34 "chancap.go", 35 "func5.go", 36 "func6.go", 37 "func7.go", 38 "func8.go", 39 "helloworld.go", 40 "varinit.go", 41 "escape3.go", 42 "initcomma.go", 43 "cmp.go", 44 "compos.go", 45 "turing.go", 46 "indirect.go", 47 "complit.go", 48 "for.go", 49 "struct0.go", 50 "intcvt.go", 51 "printbig.go", 52 "deferprint.go", 53 "escape.go", 54 "range.go", 55 "const4.go", 56 "float_lit.go", 57 "bigalg.go", 58 "decl.go", 59 "if.go", 60 "named.go", 61 "bigmap.go", 62 "func.go", 63 "reorder2.go", 64 "closure.go", 65 "gc.go", 66 "simassign.go", 67 "iota.go", 68 "nilptr2.go", 69 "goprint.go", // doesn't actually assert anything (cmpout) 70 "utf.go", 71 "method.go", 72 "char_lit.go", 73 "env.go", 74 "int_lit.go", 75 "string_lit.go", 76 "defer.go", 77 "typeswitch.go", 78 "stringrange.go", 79 "reorder.go", 80 "method3.go", 81 "literal.go", 82 "nul1.go", // doesn't actually assert anything (errorcheckoutput) 83 "zerodivide.go", 84 "convert.go", 85 "convT2X.go", 86 "switch.go", 87 "initialize.go", 88 "ddd.go", 89 "blank.go", // partly disabled 90 "map.go", 91 "closedchan.go", 92 "divide.go", 93 "rename.go", 94 "const3.go", 95 "nil.go", 96 "recover.go", // reflection parts disabled 97 "recover1.go", 98 "recover2.go", 99 "recover3.go", 100 "typeswitch1.go", 101 "floatcmp.go", 102 "crlf.go", // doesn't actually assert anything (runoutput) 103 // Slow tests follow. 104 "bom.go", // ~1.7s 105 "gc1.go", // ~1.7s 106 "cmplxdivide.go cmplxdivide1.go", // ~2.4s 107 108 // Working, but not worth enabling: 109 // "append.go", // works, but slow (15s). 110 // "gc2.go", // works, but slow, and cheats on the memory check. 111 // "sigchld.go", // works, but only on POSIX. 112 // "peano.go", // works only up to n=9, and slow even then. 113 // "stack.go", // works, but too slow (~30s) by default. 114 // "solitaire.go", // works, but too slow (~30s). 115 // "const.go", // works but for but one bug: constant folder doesn't consider representations. 116 // "init1.go", // too slow (80s) and not that interesting. Cheats on ReadMemStats check too. 117 // "rotate.go rotate0.go", // emits source for a test 118 // "rotate.go rotate1.go", // emits source for a test 119 // "rotate.go rotate2.go", // emits source for a test 120 // "rotate.go rotate3.go", // emits source for a test 121 // "64bit.go", // emits source for a test 122 // "run.go", // test driver, not a test. 123 124 // Broken. TODO(adonovan): fix. 125 // copy.go // very slow; but with N=4 quickly crashes, slice index out of range. 126 // nilptr.go // interp: V > uintptr not implemented. Slow test, lots of mem 127 // args.go // works, but requires specific os.Args from the driver. 128 // index.go // a template, not a real test. 129 // mallocfin.go // SetFinalizer not implemented. 130 131 // TODO(adonovan): add tests from $GOROOT/test/* subtrees: 132 // bench chan bugs fixedbugs interface ken. 133 } 134 135 // These are files in go.tools/go/ssa/interp/testdata/. 136 var testdataTests = []string{ 137 "boundmeth.go", 138 "complit.go", 139 "coverage.go", 140 "defer.go", 141 "fieldprom.go", 142 "ifaceconv.go", 143 "ifaceprom.go", 144 "initorder.go", 145 "methprom.go", 146 "mrvchain.go", 147 "range.go", 148 "recover.go", 149 "reflect.go", 150 "static.go", 151 "callstack.go", 152 } 153 154 // These are files and packages in $GOROOT/src/. 155 var gorootSrcTests = []string{ 156 "encoding/ascii85", 157 "encoding/csv", 158 "encoding/hex", 159 "encoding/pem", 160 "hash/crc32", 161 // "testing", // TODO(adonovan): implement runtime.Goexit correctly 162 "text/scanner", 163 "unicode", 164 165 // Too slow: 166 // "container/ring", 167 // "hash/adler32", 168 169 // TODO(adonovan): packages with Examples require os.Pipe (unimplemented): 170 // "unicode/utf8", 171 // "log", 172 // "path", 173 // "flag", 174 } 175 176 type successPredicate func(exitcode int, output string) error 177 178 func run(t *testing.T, dir, input string, success successPredicate) bool { 179 fmt.Printf("Input: %s\n", input) 180 181 start := time.Now() 182 183 var inputs []string 184 for _, i := range strings.Split(input, " ") { 185 if strings.HasSuffix(i, ".go") { 186 i = dir + i 187 } 188 inputs = append(inputs, i) 189 } 190 191 var conf loader.Config 192 if _, err := conf.FromArgs(inputs, true); err != nil { 193 t.Errorf("FromArgs(%s) failed: %s", inputs, err) 194 return false 195 } 196 197 conf.Import("runtime") 198 199 // Print a helpful hint if we don't make it to the end. 200 var hint string 201 defer func() { 202 if hint != "" { 203 fmt.Println("FAIL") 204 fmt.Println(hint) 205 } else { 206 fmt.Println("PASS") 207 } 208 209 interp.CapturedOutput = nil 210 }() 211 212 hint = fmt.Sprintf("To dump SSA representation, run:\n%% go build golang.org/x/tools/cmd/ssadump && ./ssadump -build=CFP %s\n", input) 213 214 iprog, err := conf.Load() 215 if err != nil { 216 t.Errorf("conf.Load(%s) failed: %s", inputs, err) 217 return false 218 } 219 220 prog := ssa.Create(iprog, ssa.SanityCheckFunctions) 221 prog.BuildAll() 222 223 var mainPkg *ssa.Package 224 var initialPkgs []*ssa.Package 225 for _, info := range iprog.InitialPackages() { 226 if info.Pkg.Path() == "runtime" { 227 continue // not an initial package 228 } 229 p := prog.Package(info.Pkg) 230 initialPkgs = append(initialPkgs, p) 231 if mainPkg == nil && p.Func("main") != nil { 232 mainPkg = p 233 } 234 } 235 if mainPkg == nil { 236 testmainPkg := prog.CreateTestMainPackage(initialPkgs...) 237 if testmainPkg == nil { 238 t.Errorf("CreateTestMainPackage(%s) returned nil", mainPkg) 239 return false 240 } 241 if testmainPkg.Func("main") == nil { 242 t.Errorf("synthetic testmain package has no main") 243 return false 244 } 245 mainPkg = testmainPkg 246 } 247 248 var out bytes.Buffer 249 interp.CapturedOutput = &out 250 251 hint = fmt.Sprintf("To trace execution, run:\n%% go build golang.org/x/tools/cmd/ssadump && ./ssadump -build=C -run --interp=T %s\n", input) 252 exitCode := interp.Interpret(mainPkg, 0, &types.StdSizes{8, 8}, inputs[0], []string{}) 253 254 // The definition of success varies with each file. 255 if err := success(exitCode, out.String()); err != nil { 256 t.Errorf("interp.Interpret(%s) failed: %s", inputs, err) 257 return false 258 } 259 260 hint = "" // call off the hounds 261 262 if false { 263 fmt.Println(input, time.Since(start)) // test profiling 264 } 265 266 return true 267 } 268 269 const slash = string(os.PathSeparator) 270 271 func printFailures(failures []string) { 272 if failures != nil { 273 fmt.Println("The following tests failed:") 274 for _, f := range failures { 275 fmt.Printf("\t%s\n", f) 276 } 277 } 278 } 279 280 func success(exitcode int, output string) error { 281 if exitcode != 0 { 282 return fmt.Errorf("exit code was %d", exitcode) 283 } 284 if strings.Contains(output, "BUG") { 285 return fmt.Errorf("exited zero but output contained 'BUG'") 286 } 287 return nil 288 } 289 290 // TestTestdataFiles runs the interpreter on testdata/*.go. 291 func TestTestdataFiles(t *testing.T) { 292 var failures []string 293 for _, input := range testdataTests { 294 if !run(t, "testdata"+slash, input, success) { 295 failures = append(failures, input) 296 } 297 } 298 printFailures(failures) 299 } 300 301 // TestGorootTest runs the interpreter on $GOROOT/test/*.go. 302 func TestGorootTest(t *testing.T) { 303 if testing.Short() { 304 return // too slow (~30s) 305 } 306 307 var failures []string 308 309 for _, input := range gorootTestTests { 310 if !run(t, filepath.Join(build.Default.GOROOT, "test")+slash, input, success) { 311 failures = append(failures, input) 312 } 313 } 314 for _, input := range gorootSrcTests { 315 if !run(t, filepath.Join(build.Default.GOROOT, "src")+slash, input, success) { 316 failures = append(failures, input) 317 } 318 } 319 printFailures(failures) 320 } 321 322 // TestTestmainPackage runs the interpreter on a synthetic "testmain" package. 323 func TestTestmainPackage(t *testing.T) { 324 success := func(exitcode int, output string) error { 325 if exitcode == 0 { 326 return fmt.Errorf("unexpected success") 327 } 328 if !strings.Contains(output, "FAIL: TestFoo") { 329 return fmt.Errorf("missing failure log for TestFoo") 330 } 331 if !strings.Contains(output, "FAIL: TestBar") { 332 return fmt.Errorf("missing failure log for TestBar") 333 } 334 // TODO(adonovan): test benchmarks too 335 return nil 336 } 337 run(t, "testdata"+slash, "a_test.go", success) 338 } 339 340 // CreateTestMainPackage should return nil if there were no tests. 341 func TestNullTestmainPackage(t *testing.T) { 342 var conf loader.Config 343 conf.CreateFromFilenames("", "testdata/b_test.go") 344 iprog, err := conf.Load() 345 if err != nil { 346 t.Fatalf("CreatePackages failed: %s", err) 347 } 348 prog := ssa.Create(iprog, ssa.SanityCheckFunctions) 349 mainPkg := prog.Package(iprog.Created[0].Pkg) 350 if mainPkg.Func("main") != nil { 351 t.Fatalf("unexpected main function") 352 } 353 if prog.CreateTestMainPackage(mainPkg) != nil { 354 t.Fatalf("CreateTestMainPackage returned non-nil") 355 } 356 }