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