GoPLS Viewer

Home|gopls/go/ssa/ssautil/load_test.go
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
5package ssautil_test
6
7import (
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
26const hello = `package main
27
28import "fmt"
29
30func main() {
31    fmt.Println("Hello, world")
32}
33`
34
35func TestBuildPackage(t *testing.T) {
36    testenv.NeedsGoBuild(t// for importer.Default()
37
38    // There is a more substantial test of BuildPackage and the
39    // SSA program it builds in ../ssa/builder_test.go.
40
41    fset := token.NewFileSet()
42    ferr := parser.ParseFile(fset"hello.go"hello0)
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{Importerimporter.Default()}, fsetpkg, []*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
67func TestPackages(t *testing.T) {
68    testenv.NeedsGoPackages(t)
69
70    cfg := &packages.Config{Modepackages.LoadSyntax}
71    initialerr := 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        progpkgs := ssautil.Packages(initialmode)
84        bytesNewBuffer := pkgs[0].Func("NewBuffer")
85        bytesNewBuffer.Pkg.Build()
86
87        // We'll dump the SSA of bytes.NewBuffer because it is small and stable.
88        out := new(bytes.Buffer)
89        bytesNewBuffer.WriteTo(out)
90
91        // For determinism, sanitize the location.
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
99func NewBuffer(buf []byte) *Buffer:
1000:                                                                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>>"gotwant)
109        }
110    }
111}
112
113func TestBuildPackage_MissingImport(t *testing.T) {
114    fset := token.NewFileSet()
115    ferr := 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), fsetpkg, []*ast.File{f}, ssa.BuilderMode(0))
122    if err == nil || ssapkg != nil {
123        t.Fatal("BuildPackage succeeded unexpectedly")
124    }
125}
126
127func TestIssue28106(t *testing.T) {
128    testenv.NeedsGoPackages(t)
129
130    // In go1.10, go/packages loads all packages from source, not
131    // export data, but does not type check function bodies of
132    // imported packages. This test ensures that we do not attempt
133    // to run the SSA builder on functions without type information.
134    cfg := &packages.Config{Modepackages.LoadSyntax}
135    pkgserr := packages.Load(cfg"runtime")
136    if err != nil {
137        t.Fatal(err)
138    }
139    prog_ := ssautil.Packages(pkgsssa.BuilderMode(0))
140    prog.Build() // no crash
141}
142
143func TestIssue53604(t *testing.T) {
144    // Tests that variable initializers are not added to init() when syntax
145    // is not present but types.Info is available.
146    //
147    // Packages x, y, z are loaded with mode `packages.LoadSyntax`.
148    // Package x imports y, and y imports z.
149    // Packages are built using ssautil.Packages() with x and z as roots.
150    // This setup creates y using CreatePackage(pkg, files, info, ...)
151    // where len(files) == 0 but info != nil.
152    //
153    // Tests that globals from y are not initialized.
154    e := packagestest.Export(tpackagestest.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    // Load x and z as entry packages using packages.LoadSyntax
167    e.Config.Mode = packages.LoadSyntax
168    pkgserr := packages.Load(e.Configpath.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(pkgsssa.BuilderMode(0))
179    prog.Build()
180
181    // y does not initialize F.
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 storeok := 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
MembersX
TestPackages
TestPackages.RangeStmt_1703.BlockStmt.prog
TestPackages.RangeStmt_1703.BlockStmt.got
TestIssue28106.t
bytes
TestIssue53604.y
TestBuildPackage.RangeStmt_906.BlockStmt.ssapkg
TestIssue53604.err
TestIssue53604.RangeStmt_5189.bb
TestBuildPackage.RangeStmt_906.BlockStmt.err
TestBuildPackage_MissingImport
strings
TestPackages.initial
TestIssue53604.t
TestBuildPackage.RangeStmt_906.BlockStmt._
TestPackages.RangeStmt_1703.BlockStmt.pkgs
TestBuildPackage_MissingImport.fset
TestBuildPackage_MissingImport.err
TestBuildPackage.err
testenv
TestPackages.RangeStmt_1703.BlockStmt.location
parser
TestBuildPackage_MissingImport.f
TestBuildPackage_MissingImport._
TestIssue28106._
TestPackages.cfg
TestIssue28106.cfg
TestIssue28106.prog
TestIssue53604.pkgs
TestBuildPackage_MissingImport.t
path
TestBuildPackage.RangeStmt_906.BlockStmt.pkg
TestPackages.RangeStmt_1703.mode
TestIssue28106.err
os
TestBuildPackage.f
TestBuildPackage.RangeStmt_906.mode
TestIssue28106
TestIssue53604.RangeStmt_4842.p
TestIssue53604._
packagestest
hello
TestBuildPackage
TestPackages.RangeStmt_1703.BlockStmt.out
TestIssue53604
testing
TestPackages.t
TestBuildPackage_MissingImport.pkg
TestBuildPackage_MissingImport.ssapkg
TestIssue28106.pkgs
TestIssue53604.e
ssautil
TestBuildPackage.t
TestPackages.err
TestIssue53604.prog
TestIssue53604.RangeStmt_5189.BlockStmt.RangeStmt_5225.i
importer
TestPackages.RangeStmt_1703.BlockStmt.bytesNewBuffer
TestBuildPackage.fset
Members
X