1
2
3
4
5 package ssautil_test
6
7 import (
8 "bytes"
9 "go/ast"
10 "go/importer"
11 "go/parser"
12 "go/token"
13 "go/types"
14 "os"
15 "path"
16 "strings"
17 "testing"
18
19 "golang.org/x/tools/go/packages"
20 "golang.org/x/tools/go/packages/packagestest"
21 "golang.org/x/tools/go/ssa"
22 "golang.org/x/tools/go/ssa/ssautil"
23 "golang.org/x/tools/internal/testenv"
24 )
25
26 const hello = `package main
27
28 import "fmt"
29
30 func main() {
31 fmt.Println("Hello, world")
32 }
33 `
34
35 func TestBuildPackage(t *testing.T) {
36 testenv.NeedsGoBuild(t)
37
38
39
40
41 fset := token.NewFileSet()
42 f, err := parser.ParseFile(fset, "hello.go", hello, 0)
43 if err != nil {
44 t.Fatal(err)
45 }
46
47 for _, mode := range []ssa.BuilderMode{
48 ssa.SanityCheckFunctions,
49 ssa.InstantiateGenerics | ssa.SanityCheckFunctions,
50 } {
51 pkg := types.NewPackage("hello", "")
52 ssapkg, _, err := ssautil.BuildPackage(&types.Config{Importer: importer.Default()}, fset, pkg, []*ast.File{f}, mode)
53 if err != nil {
54 t.Fatal(err)
55 }
56 if pkg.Name() != "main" {
57 t.Errorf("pkg.Name() = %s, want main", pkg.Name())
58 }
59 if ssapkg.Func("main") == nil {
60 ssapkg.WriteTo(os.Stderr)
61 t.Errorf("ssapkg has no main function")
62 }
63
64 }
65 }
66
67 func TestPackages(t *testing.T) {
68 testenv.NeedsGoPackages(t)
69
70 cfg := &packages.Config{Mode: packages.LoadSyntax}
71 initial, err := packages.Load(cfg, "bytes")
72 if err != nil {
73 t.Fatal(err)
74 }
75 if packages.PrintErrors(initial) > 0 {
76 t.Fatal("there were errors")
77 }
78
79 for _, mode := range []ssa.BuilderMode{
80 ssa.SanityCheckFunctions,
81 ssa.SanityCheckFunctions | ssa.InstantiateGenerics,
82 } {
83 prog, pkgs := ssautil.Packages(initial, mode)
84 bytesNewBuffer := pkgs[0].Func("NewBuffer")
85 bytesNewBuffer.Pkg.Build()
86
87
88 out := new(bytes.Buffer)
89 bytesNewBuffer.WriteTo(out)
90
91
92 location := prog.Fset.Position(bytesNewBuffer.Pos()).String()
93 got := strings.Replace(out.String(), location, "$GOROOT/src/bytes/buffer.go:1", -1)
94
95 want := `
96 # Name: bytes.NewBuffer
97 # Package: bytes
98 # Location: $GOROOT/src/bytes/buffer.go:1
99 func NewBuffer(buf []byte) *Buffer:
100 0: entry P:0 S:0
101 t0 = new Buffer (complit) *Buffer
102 t1 = &t0.buf [#0] *[]byte
103 *t1 = buf
104 return t0
105
106 `[1:]
107 if got != want {
108 t.Errorf("bytes.NewBuffer SSA = <<%s>>, want <<%s>>", got, want)
109 }
110 }
111 }
112
113 func TestBuildPackage_MissingImport(t *testing.T) {
114 fset := token.NewFileSet()
115 f, err := parser.ParseFile(fset, "bad.go", `package bad; import "missing"`, 0)
116 if err != nil {
117 t.Fatal(err)
118 }
119
120 pkg := types.NewPackage("bad", "")
121 ssapkg, _, err := ssautil.BuildPackage(new(types.Config), fset, pkg, []*ast.File{f}, ssa.BuilderMode(0))
122 if err == nil || ssapkg != nil {
123 t.Fatal("BuildPackage succeeded unexpectedly")
124 }
125 }
126
127 func TestIssue28106(t *testing.T) {
128 testenv.NeedsGoPackages(t)
129
130
131
132
133
134 cfg := &packages.Config{Mode: packages.LoadSyntax}
135 pkgs, err := packages.Load(cfg, "runtime")
136 if err != nil {
137 t.Fatal(err)
138 }
139 prog, _ := ssautil.Packages(pkgs, ssa.BuilderMode(0))
140 prog.Build()
141 }
142
143 func TestIssue53604(t *testing.T) {
144
145
146
147
148
149
150
151
152
153
154 e := packagestest.Export(t, packagestest.Modules, []packagestest.Module{
155 {
156 Name: "golang.org/fake",
157 Files: map[string]interface{}{
158 "x/x.go": `package x; import "golang.org/fake/y"; var V = y.F()`,
159 "y/y.go": `package y; import "golang.org/fake/z"; var F = func () *int { return &z.Z } `,
160 "z/z.go": `package z; var Z int`,
161 },
162 },
163 })
164 defer e.Cleanup()
165
166
167 e.Config.Mode = packages.LoadSyntax
168 pkgs, err := packages.Load(e.Config, path.Join(e.Temp(), "fake/x"), path.Join(e.Temp(), "fake/z"))
169 if err != nil {
170 t.Fatal(err)
171 }
172 for _, p := range pkgs {
173 if len(p.Errors) > 0 {
174 t.Fatalf("%v", p.Errors)
175 }
176 }
177
178 prog, _ := ssautil.Packages(pkgs, ssa.BuilderMode(0))
179 prog.Build()
180
181
182 y := prog.ImportedPackage("golang.org/fake/y")
183 if y == nil {
184 t.Fatal("Failed to load intermediate package y")
185 }
186 yinit := y.Members["init"].(*ssa.Function)
187 for _, bb := range yinit.Blocks {
188 for _, i := range bb.Instrs {
189 if store, ok := i.(*ssa.Store); ok && store.Addr == y.Var("F") {
190 t.Errorf("y.init() stores to F %v", store)
191 }
192 }
193 }
194
195 }
196
View as plain text