+++ /dev/null
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package interp_test
-
-// This test runs the SSA interpreter over sample Go programs.
-// Because the interpreter requires intrinsics for assembly
-// functions and many low-level runtime routines, it is inherently
-// not robust to evolutionary change in the standard library.
-// Therefore the test cases are restricted to programs that
-// use a fake standard library in testdata/src containing a tiny
-// subset of simple functions useful for writing assertions.
-//
-// We no longer attempt to interpret any real standard packages such as
-// fmt or testing, as it proved too fragile.
-
-import (
- "bytes"
- "fmt"
- "go/build"
- "go/types"
- "log"
- "os"
- "path/filepath"
- "strings"
- "testing"
- "time"
-
- "golang.org/x/tools/go/loader"
- "golang.org/x/tools/go/ssa"
- "golang.org/x/tools/go/ssa/interp"
- "golang.org/x/tools/go/ssa/ssautil"
-)
-
-// Each line contains a space-separated list of $GOROOT/test/
-// filenames comprising the main package of a program.
-// They are ordered quickest-first, roughly.
-//
-// If a test in this list fails spuriously, remove it.
-var gorootTestTests = []string{
- "235.go",
- "alias1.go",
- "func5.go",
- "func6.go",
- "func7.go",
- "func8.go",
- "helloworld.go",
- "varinit.go",
- "escape3.go",
- "initcomma.go",
- "cmp.go",
- "compos.go",
- "turing.go",
- "indirect.go",
- "complit.go",
- "for.go",
- "struct0.go",
- "intcvt.go",
- "printbig.go",
- "deferprint.go",
- "escape.go",
- "range.go",
- "const4.go",
- "float_lit.go",
- "bigalg.go",
- "decl.go",
- "if.go",
- "named.go",
- "bigmap.go",
- "func.go",
- "reorder2.go",
- "gc.go",
- "simassign.go",
- "iota.go",
- "nilptr2.go",
- "utf.go",
- "method.go",
- "char_lit.go",
- "env.go",
- "int_lit.go",
- "string_lit.go",
- "defer.go",
- "typeswitch.go",
- "stringrange.go",
- "reorder.go",
- "method3.go",
- "literal.go",
- "nul1.go", // doesn't actually assert anything (errorcheckoutput)
- "zerodivide.go",
- "convert.go",
- "convT2X.go",
- "switch.go",
- "ddd.go",
- "blank.go", // partly disabled
- "closedchan.go",
- "divide.go",
- "rename.go",
- "nil.go",
- "recover1.go",
- "recover2.go",
- "recover3.go",
- "typeswitch1.go",
- "floatcmp.go",
- "crlf.go", // doesn't actually assert anything (runoutput)
-}
-
-// These are files in go.tools/go/ssa/interp/testdata/.
-var testdataTests = []string{
- "boundmeth.go",
- "complit.go",
- "coverage.go",
- "defer.go",
- "fieldprom.go",
- "ifaceconv.go",
- "ifaceprom.go",
- "initorder.go",
- "methprom.go",
- "mrvchain.go",
- "range.go",
- "recover.go",
- "reflect.go",
- "static.go",
-}
-
-func run(t *testing.T, input string) bool {
- // The recover2 test case is broken on Go 1.14+. See golang/go#34089.
- // TODO(matloob): Fix this.
- if filepath.Base(input) == "recover2.go" {
- t.Skip("The recover2.go test is broken in go1.14+. See golang.org/issue/34089.")
- }
-
- t.Logf("Input: %s\n", input)
-
- start := time.Now()
-
- ctx := build.Default // copy
- ctx.GOROOT = "testdata" // fake goroot
- ctx.GOOS = "linux"
- ctx.GOARCH = "amd64"
-
- conf := loader.Config{Build: &ctx}
- if _, err := conf.FromArgs([]string{input}, true); err != nil {
- t.Errorf("FromArgs(%s) failed: %s", input, err)
- return false
- }
-
- conf.Import("runtime")
-
- // Print a helpful hint if we don't make it to the end.
- var hint string
- defer func() {
- if hint != "" {
- fmt.Println("FAIL")
- fmt.Println(hint)
- } else {
- fmt.Println("PASS")
- }
-
- interp.CapturedOutput = nil
- }()
-
- hint = fmt.Sprintf("To dump SSA representation, run:\n%% go build golang.org/x/tools/cmd/ssadump && ./ssadump -test -build=CFP %s\n", input)
-
- iprog, err := conf.Load()
- if err != nil {
- t.Errorf("conf.Load(%s) failed: %s", input, err)
- return false
- }
-
- prog := ssautil.CreateProgram(iprog, ssa.SanityCheckFunctions)
- prog.Build()
-
- mainPkg := prog.Package(iprog.Created[0].Pkg)
- if mainPkg == nil {
- t.Fatalf("not a main package: %s", input)
- }
-
- interp.CapturedOutput = new(bytes.Buffer)
-
- hint = fmt.Sprintf("To trace execution, run:\n%% go build golang.org/x/tools/cmd/ssadump && ./ssadump -build=C -test -run --interp=T %s\n", input)
- exitCode := interp.Interpret(mainPkg, 0, &types.StdSizes{WordSize: 8, MaxAlign: 8}, input, []string{})
- if exitCode != 0 {
- t.Fatalf("interpreting %s: exit code was %d", input, exitCode)
- }
- // $GOROOT/test tests use this convention:
- if strings.Contains(interp.CapturedOutput.String(), "BUG") {
- t.Fatalf("interpreting %s: exited zero but output contained 'BUG'", input)
- }
-
- hint = "" // call off the hounds
-
- if false {
- t.Log(input, time.Since(start)) // test profiling
- }
-
- return true
-}
-
-func printFailures(failures []string) {
- if failures != nil {
- fmt.Println("The following tests failed:")
- for _, f := range failures {
- fmt.Printf("\t%s\n", f)
- }
- }
-}
-
-// TestTestdataFiles runs the interpreter on testdata/*.go.
-func TestTestdataFiles(t *testing.T) {
- cwd, err := os.Getwd()
- if err != nil {
- log.Fatal(err)
- }
-
- var failures []string
- for _, input := range testdataTests {
- if !run(t, filepath.Join(cwd, "testdata", input)) {
- failures = append(failures, input)
- }
- }
- printFailures(failures)
-}
-
-// TestGorootTest runs the interpreter on $GOROOT/test/*.go.
-func TestGorootTest(t *testing.T) {
- var failures []string
-
- for _, input := range gorootTestTests {
- if !run(t, filepath.Join(build.Default.GOROOT, "test", input)) {
- failures = append(failures, input)
- }
- }
- printFailures(failures)
-}