summaryrefslogtreecommitdiffstats
path: root/src/cmd/compile/internal/gc/ssa_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/compile/internal/gc/ssa_test.go')
-rw-r--r--src/cmd/compile/internal/gc/ssa_test.go191
1 files changed, 191 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/gc/ssa_test.go b/src/cmd/compile/internal/gc/ssa_test.go
new file mode 100644
index 0000000..7f7c946
--- /dev/null
+++ b/src/cmd/compile/internal/gc/ssa_test.go
@@ -0,0 +1,191 @@
+// Copyright 2015 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 gc
+
+import (
+ "bytes"
+ "fmt"
+ "go/ast"
+ "go/parser"
+ "go/token"
+ "internal/testenv"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "runtime"
+ "strings"
+ "testing"
+)
+
+// runGenTest runs a test-generator, then runs the generated test.
+// Generated test can either fail in compilation or execution.
+// The environment variable parameter(s) is passed to the run
+// of the generated test.
+func runGenTest(t *testing.T, filename, tmpname string, ev ...string) {
+ testenv.MustHaveGoRun(t)
+ gotool := testenv.GoToolPath(t)
+ var stdout, stderr bytes.Buffer
+ cmd := exec.Command(gotool, "run", filepath.Join("testdata", filename))
+ cmd.Stdout = &stdout
+ cmd.Stderr = &stderr
+ if err := cmd.Run(); err != nil {
+ t.Fatalf("Failed: %v:\nOut: %s\nStderr: %s\n", err, &stdout, &stderr)
+ }
+ // Write stdout into a temporary file
+ tmpdir, ok := ioutil.TempDir("", tmpname)
+ if ok != nil {
+ t.Fatalf("Failed to create temporary directory")
+ }
+ defer os.RemoveAll(tmpdir)
+
+ rungo := filepath.Join(tmpdir, "run.go")
+ ok = ioutil.WriteFile(rungo, stdout.Bytes(), 0600)
+ if ok != nil {
+ t.Fatalf("Failed to create temporary file " + rungo)
+ }
+
+ stdout.Reset()
+ stderr.Reset()
+ cmd = exec.Command(gotool, "run", "-gcflags=-d=ssa/check/on", rungo)
+ cmd.Stdout = &stdout
+ cmd.Stderr = &stderr
+ cmd.Env = append(cmd.Env, ev...)
+ err := cmd.Run()
+ if err != nil {
+ t.Fatalf("Failed: %v:\nOut: %s\nStderr: %s\n", err, &stdout, &stderr)
+ }
+ if s := stderr.String(); s != "" {
+ t.Errorf("Stderr = %s\nWant empty", s)
+ }
+ if s := stdout.String(); s != "" {
+ t.Errorf("Stdout = %s\nWant empty", s)
+ }
+}
+
+func TestGenFlowGraph(t *testing.T) {
+ if testing.Short() {
+ t.Skip("not run in short mode.")
+ }
+ runGenTest(t, "flowgraph_generator1.go", "ssa_fg_tmp1")
+}
+
+// TestCode runs all the tests in the testdata directory as subtests.
+// These tests are special because we want to run them with different
+// compiler flags set (and thus they can't just be _test.go files in
+// this directory).
+func TestCode(t *testing.T) {
+ testenv.MustHaveGoBuild(t)
+ gotool := testenv.GoToolPath(t)
+
+ // Make a temporary directory to work in.
+ tmpdir, err := ioutil.TempDir("", "TestCode")
+ if err != nil {
+ t.Fatalf("Failed to create temporary directory: %v", err)
+ }
+ defer os.RemoveAll(tmpdir)
+
+ // Find all the test functions (and the files containing them).
+ var srcs []string // files containing Test functions
+ type test struct {
+ name string // TestFoo
+ usesFloat bool // might use float operations
+ }
+ var tests []test
+ files, err := ioutil.ReadDir("testdata")
+ if err != nil {
+ t.Fatalf("can't read testdata directory: %v", err)
+ }
+ for _, f := range files {
+ if !strings.HasSuffix(f.Name(), "_test.go") {
+ continue
+ }
+ text, err := ioutil.ReadFile(filepath.Join("testdata", f.Name()))
+ if err != nil {
+ t.Fatalf("can't read testdata/%s: %v", f.Name(), err)
+ }
+ fset := token.NewFileSet()
+ code, err := parser.ParseFile(fset, f.Name(), text, 0)
+ if err != nil {
+ t.Fatalf("can't parse testdata/%s: %v", f.Name(), err)
+ }
+ srcs = append(srcs, filepath.Join("testdata", f.Name()))
+ foundTest := false
+ for _, d := range code.Decls {
+ fd, ok := d.(*ast.FuncDecl)
+ if !ok {
+ continue
+ }
+ if !strings.HasPrefix(fd.Name.Name, "Test") {
+ continue
+ }
+ if fd.Recv != nil {
+ continue
+ }
+ if fd.Type.Results != nil {
+ continue
+ }
+ if len(fd.Type.Params.List) != 1 {
+ continue
+ }
+ p := fd.Type.Params.List[0]
+ if len(p.Names) != 1 {
+ continue
+ }
+ s, ok := p.Type.(*ast.StarExpr)
+ if !ok {
+ continue
+ }
+ sel, ok := s.X.(*ast.SelectorExpr)
+ if !ok {
+ continue
+ }
+ base, ok := sel.X.(*ast.Ident)
+ if !ok {
+ continue
+ }
+ if base.Name != "testing" {
+ continue
+ }
+ if sel.Sel.Name != "T" {
+ continue
+ }
+ // Found a testing function.
+ tests = append(tests, test{name: fd.Name.Name, usesFloat: bytes.Contains(text, []byte("float"))})
+ foundTest = true
+ }
+ if !foundTest {
+ t.Fatalf("test file testdata/%s has no tests in it", f.Name())
+ }
+ }
+
+ flags := []string{""}
+ if runtime.GOARCH == "arm" || runtime.GOARCH == "mips" || runtime.GOARCH == "mips64" {
+ flags = append(flags, ",softfloat")
+ }
+ for _, flag := range flags {
+ args := []string{"test", "-c", "-gcflags=-d=ssa/check/on" + flag, "-o", filepath.Join(tmpdir, "code.test")}
+ args = append(args, srcs...)
+ out, err := exec.Command(gotool, args...).CombinedOutput()
+ if err != nil || len(out) != 0 {
+ t.Fatalf("Build failed: %v\n%s\n", err, out)
+ }
+
+ // Now we have a test binary. Run it with all the tests as subtests of this one.
+ for _, test := range tests {
+ test := test
+ if flag == ",softfloat" && !test.usesFloat {
+ // No point in running the soft float version if the test doesn't use floats.
+ continue
+ }
+ t.Run(fmt.Sprintf("%s%s", test.name[4:], flag), func(t *testing.T) {
+ out, err := exec.Command(filepath.Join(tmpdir, "code.test"), "-test.run="+test.name).CombinedOutput()
+ if err != nil || string(out) != "PASS\n" {
+ t.Errorf("Failed:\n%s\n", out)
+ }
+ })
+ }
+ }
+}