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