1
0
mirror of https://github.com/golang/go synced 2024-11-19 04:24:39 -07:00
go/ssa/stdlib_test.go
Alan Donovan 3f2f9a7e70 go.tools/importer: generalize command-line syntax.
Motivation: pointer analysis tools (like the oracle) want the
user to specify a set of initial packages, like 'go test'.
This change enables the user to specify a set of packages on
the command line using importer.LoadInitialPackages(args).

Each argument is interpreted as either:
- a comma-separated list of *.go source files together
  comprising one non-importable ad-hoc package.
  e.g. "src/pkg/net/http/triv.go" gives us [main].
- an import path, denoting both the imported package
  and its non-importable external test package, if any.
  e.g. "fmt" gives us [fmt, fmt_test].

Current type-checker limitations mean that only the first
import path may contribute tests: multiple packages augmented
by *_test.go files could create import cycles, which 'go test'
avoids by building a separate executable for each one.
That approach is less attractive for static analysis.

Details:  (many files touched, but importer.go is the crux)

importer:
- PackageInfo.Importable boolean indicates whether
  package is importable.
- un-expose Importer.Packages; expose AllPackages() instead.
- CreatePackageFromArgs has become LoadInitialPackages.
- imports() moved to util.go, renamed importsOf().
- InitialPackagesUsage usage message exported to clients.
- the package name for ad-hoc packages now comes from the
  'package' decl, not "main".

ssa.Program:
- added CreatePackages() method
- PackagesByPath un-exposed, renamed 'imported'.
- expose AllPackages and ImportedPackage accessors.

oracle:
- describe: explain and workaround a go/types bug.

Misc:
- Removed various unnecessary error.Error() calls in Printf args.

R=crawshaw
CC=golang-dev
https://golang.org/cl/13579043
2013-09-06 18:13:57 -04:00

118 lines
2.7 KiB
Go

// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ssa_test
// This file runs the SSA builder in sanity-checking mode on all
// packages beneath $GOROOT and prints some summary information.
//
// Run test with GOMAXPROCS=8.
import (
"go/build"
"os"
"path/filepath"
"runtime"
"strings"
"testing"
"time"
"code.google.com/p/go.tools/importer"
"code.google.com/p/go.tools/ssa"
)
const debugMode = false
func allPackages() []string {
var pkgs []string
root := filepath.Join(runtime.GOROOT(), "src/pkg") + string(os.PathSeparator)
filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
// Prune the search if we encounter any of these names:
switch filepath.Base(path) {
case "testdata", ".hg":
return filepath.SkipDir
}
if info.IsDir() {
pkg := strings.TrimPrefix(path, root)
switch pkg {
case "builtin", "pkg", "code.google.com":
return filepath.SkipDir // skip these subtrees
case "":
return nil // ignore root of tree
}
pkgs = append(pkgs, pkg)
}
return nil
})
return pkgs
}
func TestStdlib(t *testing.T) {
impctx := importer.Config{Build: &build.Default}
// Load, parse and type-check the program.
t0 := time.Now()
imp := importer.New(&impctx)
if _, _, err := imp.LoadInitialPackages(allPackages()); err != nil {
t.Errorf("LoadInitialPackages failed: %s", err)
return
}
t1 := time.Now()
runtime.GC()
var memstats runtime.MemStats
runtime.ReadMemStats(&memstats)
alloc := memstats.Alloc
// Create SSA packages.
prog := ssa.NewProgram(imp.Fset, ssa.SanityCheckFunctions)
if err := prog.CreatePackages(imp); err != nil {
t.Errorf("CreatePackages failed: %s", err)
return
}
// Enable debug mode globally.
for _, info := range imp.AllPackages() {
prog.Package(info.Pkg).SetDebugMode(debugMode)
}
t2 := time.Now()
// Build SSA IR... if it's safe.
prog.BuildAll()
t3 := time.Now()
runtime.GC()
runtime.ReadMemStats(&memstats)
numPkgs := len(prog.AllPackages())
if want := 140; numPkgs < want {
t.Errorf("Loaded only %d packages, want at least %d", numPkgs, want)
}
// Dump some statistics.
allFuncs := ssa.AllFunctions(prog)
var numInstrs int
for fn := range allFuncs {
for _, b := range fn.Blocks {
numInstrs += len(b.Instrs)
}
}
t.Log("GOMAXPROCS: ", runtime.GOMAXPROCS(0))
t.Log("Load/parse/typecheck: ", t1.Sub(t0))
t.Log("SSA create: ", t2.Sub(t1))
t.Log("SSA build: ", t3.Sub(t2))
// SSA stats:
t.Log("#Packages: ", numPkgs)
t.Log("#Functions: ", len(allFuncs))
t.Log("#Instructions: ", numInstrs)
t.Log("#MB: ", (memstats.Alloc-alloc)/1000000)
}