github.com/goproxy0/go@v0.0.0-20171111080102-49cc0c489d2c/src/cmd/compile/internal/gc/ssa_test.go (about) 1 // Copyright 2015 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 package gc 6 7 import ( 8 "bytes" 9 "internal/testenv" 10 "io/ioutil" 11 "os/exec" 12 "path/filepath" 13 "runtime" 14 "strings" 15 "testing" 16 ) 17 18 // TODO: move all these tests elsewhere? 19 // Perhaps teach test/run.go how to run them with a new action verb. 20 func runTest(t *testing.T, filename string) { 21 t.Parallel() 22 doTest(t, filename, "run") 23 } 24 func buildTest(t *testing.T, filename string) { 25 t.Parallel() 26 doTest(t, filename, "build") 27 } 28 func doTest(t *testing.T, filename string, kind string) { 29 testenv.MustHaveGoBuild(t) 30 gotool := testenv.GoToolPath(t) 31 32 var stdout, stderr bytes.Buffer 33 cmd := exec.Command(gotool, kind, "-gcflags=-d=ssa/check/on", filepath.Join("testdata", filename)) 34 cmd.Stdout = &stdout 35 cmd.Stderr = &stderr 36 err := cmd.Run() 37 if err != nil { 38 t.Fatalf("Failed: %v:\nOut: %s\nStderr: %s\n", err, &stdout, &stderr) 39 } 40 if s := stdout.String(); s != "" { 41 t.Errorf("Stdout = %s\nWant empty", s) 42 } 43 if s := stderr.String(); strings.Contains(s, "SSA unimplemented") { 44 t.Errorf("Unimplemented message found in stderr:\n%s", s) 45 } 46 } 47 48 // runGenTest runs a test-generator, then runs the generated test. 49 // Generated test can either fail in compilation or execution. 50 // The environment variable parameter(s) is passed to the run 51 // of the generated test. 52 func runGenTest(t *testing.T, filename, tmpname string, ev ...string) { 53 testenv.MustHaveGoRun(t) 54 gotool := testenv.GoToolPath(t) 55 var stdout, stderr bytes.Buffer 56 cmd := exec.Command(gotool, "run", filepath.Join("testdata", filename)) 57 cmd.Stdout = &stdout 58 cmd.Stderr = &stderr 59 if err := cmd.Run(); err != nil { 60 t.Fatalf("Failed: %v:\nOut: %s\nStderr: %s\n", err, &stdout, &stderr) 61 } 62 // Write stdout into a temporary file 63 tmpdir, ok := ioutil.TempDir("", tmpname) 64 if ok != nil { 65 t.Fatalf("Failed to create temporary directory") 66 } 67 68 rungo := filepath.Join(tmpdir, "run.go") 69 ok = ioutil.WriteFile(rungo, stdout.Bytes(), 0600) 70 if ok != nil { 71 t.Fatalf("Failed to create temporary file " + rungo) 72 } 73 74 stdout.Reset() 75 stderr.Reset() 76 cmd = exec.Command("go", "run", "-gcflags=-d=ssa/check/on", rungo) 77 cmd.Stdout = &stdout 78 cmd.Stderr = &stderr 79 cmd.Env = append(cmd.Env, ev...) 80 err := cmd.Run() 81 if err != nil { 82 t.Fatalf("Failed: %v:\nOut: %s\nStderr: %s\n", err, &stdout, &stderr) 83 } 84 if s := stderr.String(); s != "" { 85 t.Errorf("Stderr = %s\nWant empty", s) 86 } 87 if s := stdout.String(); s != "" { 88 t.Errorf("Stdout = %s\nWant empty", s) 89 } 90 } 91 92 func TestGenFlowGraph(t *testing.T) { 93 runGenTest(t, "flowgraph_generator1.go", "ssa_fg_tmp1") 94 if runtime.GOOS != "windows" { 95 runGenTest(t, "flowgraph_generator1.go", "ssa_fg_tmp2", "GO_SSA_PHI_LOC_CUTOFF=0") 96 } 97 } 98 99 // TestShortCircuit tests OANDAND and OOROR expressions and short circuiting. 100 func TestShortCircuit(t *testing.T) { runTest(t, "short.go") } 101 102 // TestBreakContinue tests that continue and break statements do what they say. 103 func TestBreakContinue(t *testing.T) { runTest(t, "break.go") } 104 105 // TestTypeAssertion tests type assertions. 106 func TestTypeAssertion(t *testing.T) { runTest(t, "assert.go") } 107 108 // TestArithmetic tests that both backends have the same result for arithmetic expressions. 109 func TestArithmetic(t *testing.T) { runTest(t, "arith.go") } 110 111 // TestFP tests that both backends have the same result for floating point expressions. 112 func TestFP(t *testing.T) { runTest(t, "fp.go") } 113 114 // TestArithmeticBoundary tests boundary results for arithmetic operations. 115 func TestArithmeticBoundary(t *testing.T) { runTest(t, "arithBoundary.go") } 116 117 // TestArithmeticConst tests results for arithmetic operations against constants. 118 func TestArithmeticConst(t *testing.T) { runTest(t, "arithConst.go") } 119 120 func TestChan(t *testing.T) { runTest(t, "chan.go") } 121 122 // TestComparisonsConst tests results for comparison operations against constants. 123 func TestComparisonsConst(t *testing.T) { runTest(t, "cmpConst.go") } 124 125 func TestCompound(t *testing.T) { runTest(t, "compound.go") } 126 127 func TestCtl(t *testing.T) { runTest(t, "ctl.go") } 128 129 func TestLoadStore(t *testing.T) { runTest(t, "loadstore.go") } 130 131 func TestMap(t *testing.T) { runTest(t, "map.go") } 132 133 func TestRegalloc(t *testing.T) { runTest(t, "regalloc.go") } 134 135 func TestString(t *testing.T) { runTest(t, "string.go") } 136 137 func TestDeferNoReturn(t *testing.T) { buildTest(t, "deferNoReturn.go") } 138 139 // TestClosure tests closure related behavior. 140 func TestClosure(t *testing.T) { runTest(t, "closure.go") } 141 142 func TestArray(t *testing.T) { runTest(t, "array.go") } 143 144 func TestAppend(t *testing.T) { runTest(t, "append.go") } 145 146 func TestZero(t *testing.T) { runTest(t, "zero.go") } 147 148 func TestAddressed(t *testing.T) { runTest(t, "addressed.go") } 149 150 func TestCopy(t *testing.T) { runTest(t, "copy.go") } 151 152 func TestUnsafe(t *testing.T) { runTest(t, "unsafe.go") } 153 154 func TestPhi(t *testing.T) { runTest(t, "phi.go") } 155 156 func TestSlice(t *testing.T) { runTest(t, "slice.go") } 157 158 func TestNamedReturn(t *testing.T) { runTest(t, "namedReturn.go") } 159 160 func TestDuplicateLoad(t *testing.T) { runTest(t, "dupLoad.go") } 161 162 func TestSqrt(t *testing.T) { runTest(t, "sqrt_const.go") }