Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201028153306-37f0764111ff / go / ssa / interp / interp_test.go
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 package interp_test
6
7 // This test runs the SSA interpreter over sample Go programs.
8 // Because the interpreter requires intrinsics for assembly
9 // functions and many low-level runtime routines, it is inherently
10 // not robust to evolutionary change in the standard library.
11 // Therefore the test cases are restricted to programs that
12 // use a fake standard library in testdata/src containing a tiny
13 // subset of simple functions useful for writing assertions.
14 //
15 // We no longer attempt to interpret any real standard packages such as
16 // fmt or testing, as it proved too fragile.
17
18 import (
19         "bytes"
20         "fmt"
21         "go/build"
22         "go/types"
23         "log"
24         "os"
25         "path/filepath"
26         "strings"
27         "testing"
28         "time"
29
30         "golang.org/x/tools/go/loader"
31         "golang.org/x/tools/go/ssa"
32         "golang.org/x/tools/go/ssa/interp"
33         "golang.org/x/tools/go/ssa/ssautil"
34 )
35
36 // Each line contains a space-separated list of $GOROOT/test/
37 // filenames comprising the main package of a program.
38 // They are ordered quickest-first, roughly.
39 //
40 // If a test in this list fails spuriously, remove it.
41 var gorootTestTests = []string{
42         "235.go",
43         "alias1.go",
44         "func5.go",
45         "func6.go",
46         "func7.go",
47         "func8.go",
48         "helloworld.go",
49         "varinit.go",
50         "escape3.go",
51         "initcomma.go",
52         "cmp.go",
53         "compos.go",
54         "turing.go",
55         "indirect.go",
56         "complit.go",
57         "for.go",
58         "struct0.go",
59         "intcvt.go",
60         "printbig.go",
61         "deferprint.go",
62         "escape.go",
63         "range.go",
64         "const4.go",
65         "float_lit.go",
66         "bigalg.go",
67         "decl.go",
68         "if.go",
69         "named.go",
70         "bigmap.go",
71         "func.go",
72         "reorder2.go",
73         "gc.go",
74         "simassign.go",
75         "iota.go",
76         "nilptr2.go",
77         "utf.go",
78         "method.go",
79         "char_lit.go",
80         "env.go",
81         "int_lit.go",
82         "string_lit.go",
83         "defer.go",
84         "typeswitch.go",
85         "stringrange.go",
86         "reorder.go",
87         "method3.go",
88         "literal.go",
89         "nul1.go", // doesn't actually assert anything (errorcheckoutput)
90         "zerodivide.go",
91         "convert.go",
92         "convT2X.go",
93         "switch.go",
94         "ddd.go",
95         "blank.go", // partly disabled
96         "closedchan.go",
97         "divide.go",
98         "rename.go",
99         "nil.go",
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 }
107
108 // These are files in go.tools/go/ssa/interp/testdata/.
109 var testdataTests = []string{
110         "boundmeth.go",
111         "complit.go",
112         "coverage.go",
113         "defer.go",
114         "fieldprom.go",
115         "ifaceconv.go",
116         "ifaceprom.go",
117         "initorder.go",
118         "methprom.go",
119         "mrvchain.go",
120         "range.go",
121         "recover.go",
122         "reflect.go",
123         "static.go",
124 }
125
126 func run(t *testing.T, input string) bool {
127         // The recover2 test case is broken on Go 1.14+. See golang/go#34089.
128         // TODO(matloob): Fix this.
129         if filepath.Base(input) == "recover2.go" {
130                 t.Skip("The recover2.go test is broken in go1.14+. See golang.org/issue/34089.")
131         }
132
133         t.Logf("Input: %s\n", input)
134
135         start := time.Now()
136
137         ctx := build.Default    // copy
138         ctx.GOROOT = "testdata" // fake goroot
139         ctx.GOOS = "linux"
140         ctx.GOARCH = "amd64"
141
142         conf := loader.Config{Build: &ctx}
143         if _, err := conf.FromArgs([]string{input}, true); err != nil {
144                 t.Errorf("FromArgs(%s) failed: %s", input, err)
145                 return false
146         }
147
148         conf.Import("runtime")
149
150         // Print a helpful hint if we don't make it to the end.
151         var hint string
152         defer func() {
153                 if hint != "" {
154                         fmt.Println("FAIL")
155                         fmt.Println(hint)
156                 } else {
157                         fmt.Println("PASS")
158                 }
159
160                 interp.CapturedOutput = nil
161         }()
162
163         hint = fmt.Sprintf("To dump SSA representation, run:\n%% go build golang.org/x/tools/cmd/ssadump && ./ssadump -test -build=CFP %s\n", input)
164
165         iprog, err := conf.Load()
166         if err != nil {
167                 t.Errorf("conf.Load(%s) failed: %s", input, err)
168                 return false
169         }
170
171         prog := ssautil.CreateProgram(iprog, ssa.SanityCheckFunctions)
172         prog.Build()
173
174         mainPkg := prog.Package(iprog.Created[0].Pkg)
175         if mainPkg == nil {
176                 t.Fatalf("not a main package: %s", input)
177         }
178
179         interp.CapturedOutput = new(bytes.Buffer)
180
181         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)
182         exitCode := interp.Interpret(mainPkg, 0, &types.StdSizes{WordSize: 8, MaxAlign: 8}, input, []string{})
183         if exitCode != 0 {
184                 t.Fatalf("interpreting %s: exit code was %d", input, exitCode)
185         }
186         // $GOROOT/test tests use this convention:
187         if strings.Contains(interp.CapturedOutput.String(), "BUG") {
188                 t.Fatalf("interpreting %s: exited zero but output contained 'BUG'", input)
189         }
190
191         hint = "" // call off the hounds
192
193         if false {
194                 t.Log(input, time.Since(start)) // test profiling
195         }
196
197         return true
198 }
199
200 func printFailures(failures []string) {
201         if failures != nil {
202                 fmt.Println("The following tests failed:")
203                 for _, f := range failures {
204                         fmt.Printf("\t%s\n", f)
205                 }
206         }
207 }
208
209 // TestTestdataFiles runs the interpreter on testdata/*.go.
210 func TestTestdataFiles(t *testing.T) {
211         cwd, err := os.Getwd()
212         if err != nil {
213                 log.Fatal(err)
214         }
215
216         var failures []string
217         for _, input := range testdataTests {
218                 if !run(t, filepath.Join(cwd, "testdata", input)) {
219                         failures = append(failures, input)
220                 }
221         }
222         printFailures(failures)
223 }
224
225 // TestGorootTest runs the interpreter on $GOROOT/test/*.go.
226 func TestGorootTest(t *testing.T) {
227         var failures []string
228
229         for _, input := range gorootTestTests {
230                 if !run(t, filepath.Join(build.Default.GOROOT, "test", input)) {
231                         failures = append(failures, input)
232                 }
233         }
234         printFailures(failures)
235 }