aboutsummaryrefslogtreecommitdiff
path: root/go/ssa/ssautil/load_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'go/ssa/ssautil/load_test.go')
-rw-r--r--go/ssa/ssautil/load_test.go120
1 files changed, 95 insertions, 25 deletions
diff --git a/go/ssa/ssautil/load_test.go b/go/ssa/ssautil/load_test.go
index 55684e0a6..efa2ba40a 100644
--- a/go/ssa/ssautil/load_test.go
+++ b/go/ssa/ssautil/load_test.go
@@ -12,10 +12,13 @@ import (
"go/token"
"go/types"
"os"
+ "path"
"strings"
"testing"
"golang.org/x/tools/go/packages"
+ "golang.org/x/tools/go/packages/packagestest"
+ "golang.org/x/tools/go/ssa"
"golang.org/x/tools/go/ssa/ssautil"
"golang.org/x/tools/internal/testenv"
)
@@ -30,6 +33,8 @@ func main() {
`
func TestBuildPackage(t *testing.T) {
+ testenv.NeedsGoBuild(t) // for importer.Default()
+
// There is a more substantial test of BuildPackage and the
// SSA program it builds in ../ssa/builder_test.go.
@@ -39,17 +44,23 @@ func TestBuildPackage(t *testing.T) {
t.Fatal(err)
}
- pkg := types.NewPackage("hello", "")
- ssapkg, _, err := ssautil.BuildPackage(&types.Config{Importer: importer.Default()}, fset, pkg, []*ast.File{f}, 0)
- if err != nil {
- t.Fatal(err)
- }
- if pkg.Name() != "main" {
- t.Errorf("pkg.Name() = %s, want main", pkg.Name())
- }
- if ssapkg.Func("main") == nil {
- ssapkg.WriteTo(os.Stderr)
- t.Errorf("ssapkg has no main function")
+ for _, mode := range []ssa.BuilderMode{
+ ssa.SanityCheckFunctions,
+ ssa.InstantiateGenerics | ssa.SanityCheckFunctions,
+ } {
+ pkg := types.NewPackage("hello", "")
+ ssapkg, _, err := ssautil.BuildPackage(&types.Config{Importer: importer.Default()}, fset, pkg, []*ast.File{f}, mode)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if pkg.Name() != "main" {
+ t.Errorf("pkg.Name() = %s, want main", pkg.Name())
+ }
+ if ssapkg.Func("main") == nil {
+ ssapkg.WriteTo(os.Stderr)
+ t.Errorf("ssapkg has no main function")
+ }
+
}
}
@@ -65,19 +76,23 @@ func TestPackages(t *testing.T) {
t.Fatal("there were errors")
}
- prog, pkgs := ssautil.Packages(initial, 0)
- bytesNewBuffer := pkgs[0].Func("NewBuffer")
- bytesNewBuffer.Pkg.Build()
+ for _, mode := range []ssa.BuilderMode{
+ ssa.SanityCheckFunctions,
+ ssa.SanityCheckFunctions | ssa.InstantiateGenerics,
+ } {
+ prog, pkgs := ssautil.Packages(initial, mode)
+ bytesNewBuffer := pkgs[0].Func("NewBuffer")
+ bytesNewBuffer.Pkg.Build()
- // We'll dump the SSA of bytes.NewBuffer because it is small and stable.
- out := new(bytes.Buffer)
- bytesNewBuffer.WriteTo(out)
+ // We'll dump the SSA of bytes.NewBuffer because it is small and stable.
+ out := new(bytes.Buffer)
+ bytesNewBuffer.WriteTo(out)
- // For determinism, sanitize the location.
- location := prog.Fset.Position(bytesNewBuffer.Pos()).String()
- got := strings.Replace(out.String(), location, "$GOROOT/src/bytes/buffer.go:1", -1)
+ // For determinism, sanitize the location.
+ location := prog.Fset.Position(bytesNewBuffer.Pos()).String()
+ got := strings.Replace(out.String(), location, "$GOROOT/src/bytes/buffer.go:1", -1)
- want := `
+ want := `
# Name: bytes.NewBuffer
# Package: bytes
# Location: $GOROOT/src/bytes/buffer.go:1
@@ -89,8 +104,9 @@ func NewBuffer(buf []byte) *Buffer:
return t0
`[1:]
- if got != want {
- t.Errorf("bytes.NewBuffer SSA = <<%s>>, want <<%s>>", got, want)
+ if got != want {
+ t.Errorf("bytes.NewBuffer SSA = <<%s>>, want <<%s>>", got, want)
+ }
}
}
@@ -102,7 +118,7 @@ func TestBuildPackage_MissingImport(t *testing.T) {
}
pkg := types.NewPackage("bad", "")
- ssapkg, _, err := ssautil.BuildPackage(new(types.Config), fset, pkg, []*ast.File{f}, 0)
+ ssapkg, _, err := ssautil.BuildPackage(new(types.Config), fset, pkg, []*ast.File{f}, ssa.BuilderMode(0))
if err == nil || ssapkg != nil {
t.Fatal("BuildPackage succeeded unexpectedly")
}
@@ -120,6 +136,60 @@ func TestIssue28106(t *testing.T) {
if err != nil {
t.Fatal(err)
}
- prog, _ := ssautil.Packages(pkgs, 0)
+ prog, _ := ssautil.Packages(pkgs, ssa.BuilderMode(0))
prog.Build() // no crash
}
+
+func TestIssue53604(t *testing.T) {
+ // Tests that variable initializers are not added to init() when syntax
+ // is not present but types.Info is available.
+ //
+ // Packages x, y, z are loaded with mode `packages.LoadSyntax`.
+ // Package x imports y, and y imports z.
+ // Packages are built using ssautil.Packages() with x and z as roots.
+ // This setup creates y using CreatePackage(pkg, files, info, ...)
+ // where len(files) == 0 but info != nil.
+ //
+ // Tests that globals from y are not initialized.
+ e := packagestest.Export(t, packagestest.Modules, []packagestest.Module{
+ {
+ Name: "golang.org/fake",
+ Files: map[string]interface{}{
+ "x/x.go": `package x; import "golang.org/fake/y"; var V = y.F()`,
+ "y/y.go": `package y; import "golang.org/fake/z"; var F = func () *int { return &z.Z } `,
+ "z/z.go": `package z; var Z int`,
+ },
+ },
+ })
+ defer e.Cleanup()
+
+ // Load x and z as entry packages using packages.LoadSyntax
+ e.Config.Mode = packages.LoadSyntax
+ pkgs, err := packages.Load(e.Config, path.Join(e.Temp(), "fake/x"), path.Join(e.Temp(), "fake/z"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ for _, p := range pkgs {
+ if len(p.Errors) > 0 {
+ t.Fatalf("%v", p.Errors)
+ }
+ }
+
+ prog, _ := ssautil.Packages(pkgs, ssa.BuilderMode(0))
+ prog.Build()
+
+ // y does not initialize F.
+ y := prog.ImportedPackage("golang.org/fake/y")
+ if y == nil {
+ t.Fatal("Failed to load intermediate package y")
+ }
+ yinit := y.Members["init"].(*ssa.Function)
+ for _, bb := range yinit.Blocks {
+ for _, i := range bb.Instrs {
+ if store, ok := i.(*ssa.Store); ok && store.Addr == y.Var("F") {
+ t.Errorf("y.init() stores to F %v", store)
+ }
+ }
+ }
+
+}