本文整理匯總了Golang中github.com/fzipp/pythia/internal/tools/go/loader.Config類的典型用法代碼示例。如果您正苦於以下問題:Golang Config類的具體用法?Golang Config怎麽用?Golang Config使用的例子?那麽, 這裏精選的類代碼示例或許可以為您提供幫助。
在下文中一共展示了Config類的15個代碼示例,這些例子默認根據受歡迎程度排序。您可以為喜歡或者感覺有用的代碼點讚,您的評價將有助於係統推薦出更棒的Golang代碼示例。
示例1: Query
// Query runs a single oracle query.
//
// args specify the main package in (*loader.Config).FromArgs syntax.
// mode is the query mode ("callers", etc).
// ptalog is the (optional) pointer-analysis log file.
// buildContext is the go/build configuration for locating packages.
// reflection determines whether to model reflection soundly (currently slow).
//
// Clients that intend to perform multiple queries against the same
// analysis scope should use this pattern instead:
//
// conf := loader.Config{Build: buildContext}
// ... populate config, e.g. conf.FromArgs(args) ...
// iprog, err := conf.Load()
// if err != nil { ... }
// o, err := oracle.New(iprog, nil, false)
// if err != nil { ... }
// for ... {
// qpos, err := oracle.ParseQueryPos(imp, pos, needExact)
// if err != nil { ... }
//
// res, err := o.Query(mode, qpos)
// if err != nil { ... }
//
// // use res
// }
//
// TODO(adonovan): the ideal 'needsExact' parameter for ParseQueryPos
// depends on the query mode; how should we expose this?
//
func Query(args []string, mode, pos string, ptalog io.Writer, buildContext *build.Context, reflection bool) (*Result, error) {
if mode == "what" {
// Bypass package loading, type checking, SSA construction.
return what(pos, buildContext)
}
minfo := findMode(mode)
if minfo == nil {
return nil, fmt.Errorf("invalid mode type: %q", mode)
}
conf := loader.Config{Build: buildContext}
// Determine initial packages.
args, err := conf.FromArgs(args, true)
if err != nil {
return nil, err
}
if len(args) > 0 {
return nil, fmt.Errorf("surplus arguments: %q", args)
}
// For queries needing only a single typed package,
// reduce the analysis scope to that package.
if minfo.needs&(needSSA|needRetainTypeInfo) == 0 {
reduceScope(pos, &conf)
}
// TODO(adonovan): report type errors to the user via Serial
// types, not stderr?
// conf.TypeChecker.Error = func(err error) {
// E := err.(types.Error)
// fmt.Fprintf(os.Stderr, "%s: %s\n", E.Fset.Position(E.Pos), E.Msg)
// }
// Load/parse/type-check the program.
iprog, err := conf.Load()
if err != nil {
return nil, err
}
o, err := newOracle(iprog, ptalog, minfo.needs, reflection)
if err != nil {
return nil, err
}
qpos, err := ParseQueryPos(iprog, pos, minfo.needs&needExactPos != 0)
if err != nil && minfo.needs&(needPos|needExactPos) != 0 {
return nil, err
}
// SSA is built and we have the QueryPos.
// Release the other ASTs and type info to the GC.
iprog = nil
return o.query(minfo, qpos)
}
示例2: TestMultipleQueries
func TestMultipleQueries(t *testing.T) {
// Loader
var buildContext = build.Default
buildContext.GOPATH = "testdata"
conf := loader.Config{Build: &buildContext}
filename := "testdata/src/main/multi.go"
conf.CreateFromFilenames("", filename)
iprog, err := conf.Load()
if err != nil {
t.Fatalf("Load failed: %s", err)
}
// Oracle
o, err := oracle.New(iprog, nil, true)
if err != nil {
t.Fatalf("oracle.New failed: %s", err)
}
// QueryPos
pos := filename + ":#54,#58"
qpos, err := oracle.ParseQueryPos(iprog, pos, true)
if err != nil {
t.Fatalf("oracle.ParseQueryPos(%q) failed: %s", pos, err)
}
// SSA is built and we have the QueryPos.
// Release the other ASTs and type info to the GC.
iprog = nil
// Run different query modes on same scope and selection.
out := new(bytes.Buffer)
for _, mode := range [...]string{"callers", "describe", "freevars"} {
res, err := o.Query(mode, qpos)
if err != nil {
t.Errorf("(*oracle.Oracle).Query(%q) failed: %s", pos, err)
}
WriteResult(out, res)
}
want := `multi.f is called from these 1 sites:
static function call from multi.main
function call (or conversion) of type ()
Free identifiers:
var x int
`
if got := out.String(); got != want {
t.Errorf("Query output differs; want <<%s>>, got <<%s>>\n", want, got)
}
}
示例3: TestNullTestmainPackage
// CreateTestMainPackage should return nil if there were no tests.
func TestNullTestmainPackage(t *testing.T) {
var conf loader.Config
conf.CreateFromFilenames("", "testdata/b_test.go")
iprog, err := conf.Load()
if err != nil {
t.Fatalf("CreatePackages failed: %s", err)
}
prog := ssa.Create(iprog, ssa.SanityCheckFunctions)
mainPkg := prog.Package(iprog.Created[0].Pkg)
if mainPkg.Func("main") != nil {
t.Fatalf("unexpected main function")
}
if prog.CreateTestMainPackage(mainPkg) != nil {
t.Fatalf("CreateTestMainPackage returned non-nil")
}
}
示例4: reduceScope
// reduceScope is called for one-shot queries that need only a single
// typed package. It attempts to guess the query package from pos and
// reduce the analysis scope (set of loaded packages) to just that one
// plus (the exported parts of) its dependencies. It leaves its
// arguments unchanged on failure.
//
// TODO(adonovan): this is a real mess... but it's fast.
//
func reduceScope(pos string, conf *loader.Config) {
fqpos, err := fastQueryPos(pos)
if err != nil {
return // bad query
}
// TODO(adonovan): fix: this gives the wrong results for files
// in non-importable packages such as tests and ad-hoc packages
// specified as a list of files (incl. the oracle's tests).
_, importPath, err := guessImportPath(fqpos.fset.File(fqpos.start).Name(), conf.Build)
if err != nil {
return // can't find GOPATH dir
}
if importPath == "" {
return
}
// Check that it's possible to load the queried package.
// (e.g. oracle tests contain different 'package' decls in same dir.)
// Keep consistent with logic in loader/util.go!
cfg2 := *conf.Build
cfg2.CgoEnabled = false
bp, err := cfg2.Import(importPath, "", 0)
if err != nil {
return // no files for package
}
// Check that the queried file appears in the package:
// it might be a '// +build ignore' from an ad-hoc main
// package, e.g. $GOROOT/src/net/http/triv.go.
if !pkgContainsFile(bp, fqpos.fset.File(fqpos.start).Name()) {
return // not found
}
conf.TypeCheckFuncBodies = func(p string) bool { return p == importPath }
// Ignore packages specified on command line.
conf.CreatePkgs = nil
conf.ImportPkgs = nil
// Instead load just the one containing the query position
// (and possibly its corresponding tests/production code).
// TODO(adonovan): set 'augment' based on which file list
// contains
conf.ImportWithTests(importPath)
}
示例5: TestSwitches
func TestSwitches(t *testing.T) {
conf := loader.Config{ParserMode: parser.ParseComments}
f, err := conf.ParseFile("testdata/switches.go", nil)
if err != nil {
t.Error(err)
return
}
conf.CreateFromFiles("main", f)
iprog, err := conf.Load()
if err != nil {
t.Error(err)
return
}
prog := ssa.Create(iprog, 0)
mainPkg := prog.Package(iprog.Created[0].Pkg)
mainPkg.Build()
for _, mem := range mainPkg.Members {
if fn, ok := mem.(*ssa.Function); ok {
if fn.Synthetic != "" {
continue // e.g. init()
}
// Each (multi-line) "switch" comment within
// this function must match the printed form
// of a ConstSwitch.
var wantSwitches []string
for _, c := range f.Comments {
if fn.Syntax().Pos() <= c.Pos() && c.Pos() < fn.Syntax().End() {
text := strings.TrimSpace(c.Text())
if strings.HasPrefix(text, "switch ") {
wantSwitches = append(wantSwitches, text)
}
}
}
switches := ssautil.Switches(fn)
if len(switches) != len(wantSwitches) {
t.Errorf("in %s, found %d switches, want %d", fn, len(switches), len(wantSwitches))
}
for i, sw := range switches {
got := sw.String()
if i >= len(wantSwitches) {
continue
}
want := wantSwitches[i]
if got != want {
t.Errorf("in %s, found switch %d: got <<%s>>, want <<%s>>", fn, i, got, want)
}
}
}
}
}
示例6: create
func create(t *testing.T, content string) []*ssa.Package {
var conf loader.Config
f, err := conf.ParseFile("foo_test.go", content)
if err != nil {
t.Fatal(err)
}
conf.CreateFromFiles("foo", f)
iprog, err := conf.Load()
if err != nil {
t.Fatal(err)
}
// We needn't call Build.
return ssa.Create(iprog, ssa.SanityCheckFunctions).AllPackages()
}
示例7: TestRTA
// TestRTA runs RTA on each file in inputs, prints the results, and
// compares it with the golden results embedded in the WANT comment at
// the end of the file.
//
// The results string consists of two parts: the set of dynamic call
// edges, "f --> g", one per line, and the set of reachable functions,
// one per line. Each set is sorted.
//
func TestRTA(t *testing.T) {
for _, filename := range inputs {
content, err := ioutil.ReadFile(filename)
if err != nil {
t.Errorf("couldn't read file '%s': %s", filename, err)
continue
}
conf := loader.Config{
ParserMode: parser.ParseComments,
}
f, err := conf.ParseFile(filename, content)
if err != nil {
t.Error(err)
continue
}
want, pos := expectation(f)
if pos == token.NoPos {
t.Errorf("No WANT: comment in %s", filename)
continue
}
conf.CreateFromFiles("main", f)
iprog, err := conf.Load()
if err != nil {
t.Error(err)
continue
}
prog := ssa.Create(iprog, 0)
mainPkg := prog.Package(iprog.Created[0].Pkg)
prog.BuildAll()
res := rta.Analyze([]*ssa.Function{
mainPkg.Func("main"),
mainPkg.Func("init"),
}, true)
if got := printResult(res, mainPkg.Object); got != want {
t.Errorf("%s: got:\n%s\nwant:\n%s",
prog.Fset.Position(pos), got, want)
}
}
}
示例8: TestStatic
func TestStatic(t *testing.T) {
conf := loader.Config{ParserMode: parser.ParseComments}
f, err := conf.ParseFile("P.go", input)
if err != nil {
t.Fatal(err)
}
conf.CreateFromFiles("P", f)
iprog, err := conf.Load()
if err != nil {
t.Fatal(err)
}
P := iprog.Created[0].Pkg
prog := ssa.Create(iprog, 0)
prog.BuildAll()
cg := static.CallGraph(prog)
var edges []string
callgraph.GraphVisitEdges(cg, func(e *callgraph.Edge) error {
edges = append(edges, fmt.Sprintf("%s -> %s",
e.Caller.Func.RelString(P),
e.Callee.Func.RelString(P)))
return nil
})
sort.Strings(edges)
want := []string{
"(*C).f -> (C).f",
"f -> (C).f",
"f -> f$1",
"f -> g",
}
if !reflect.DeepEqual(edges, want) {
t.Errorf("Got edges %v, want %v", edges, want)
}
}
示例9: TestObjValueLookup
func TestObjValueLookup(t *testing.T) {
conf := loader.Config{ParserMode: parser.ParseComments}
f, err := conf.ParseFile("testdata/objlookup.go", nil)
if err != nil {
t.Error(err)
return
}
conf.CreateFromFiles("main", f)
// Maps each var Ident (represented "name:linenum") to the
// kind of ssa.Value we expect (represented "Constant", "&Alloc").
expectations := make(map[string]string)
// Find all annotations of form x::BinOp, &y::Alloc, etc.
re := regexp.MustCompile(`(\b|&)?(\w*)::(\w*)\b`)
for _, c := range f.Comments {
text := c.Text()
pos := conf.Fset.Position(c.Pos())
for _, m := range re.FindAllStringSubmatch(text, -1) {
key := fmt.Sprintf("%s:%d", m[2], pos.Line)
value := m[1] + m[3]
expectations[key] = value
}
}
iprog, err := conf.Load()
if err != nil {
t.Error(err)
return
}
prog := ssa.Create(iprog, 0 /*|ssa.PrintFunctions*/)
mainInfo := iprog.Created[0]
mainPkg := prog.Package(mainInfo.Pkg)
mainPkg.SetDebugMode(true)
mainPkg.Build()
var varIds []*ast.Ident
var varObjs []*types.Var
for id, obj := range mainInfo.Defs {
// Check invariants for func and const objects.
switch obj := obj.(type) {
case *types.Func:
checkFuncValue(t, prog, obj)
case *types.Const:
checkConstValue(t, prog, obj)
case *types.Var:
if id.Name == "_" {
continue
}
varIds = append(varIds, id)
varObjs = append(varObjs, obj)
}
}
for id, obj := range mainInfo.Uses {
if obj, ok := obj.(*types.Var); ok {
varIds = append(varIds, id)
varObjs = append(varObjs, obj)
}
}
// Check invariants for var objects.
// The result varies based on the specific Ident.
for i, id := range varIds {
obj := varObjs[i]
ref, _ := astutil.PathEnclosingInterval(f, id.Pos(), id.Pos())
pos := prog.Fset.Position(id.Pos())
exp := expectations[fmt.Sprintf("%s:%d", id.Name, pos.Line)]
if exp == "" {
t.Errorf("%s: no expectation for var ident %s ", pos, id.Name)
continue
}
wantAddr := false
if exp[0] == '&' {
wantAddr = true
exp = exp[1:]
}
checkVarValue(t, prog, mainPkg, ref, obj, exp, wantAddr)
}
}
示例10: TestValueForExpr
// Ensure that, in debug mode, we can determine the ssa.Value
// corresponding to every ast.Expr.
func TestValueForExpr(t *testing.T) {
conf := loader.Config{ParserMode: parser.ParseComments}
f, err := conf.ParseFile("testdata/valueforexpr.go", nil)
if err != nil {
t.Error(err)
return
}
conf.CreateFromFiles("main", f)
iprog, err := conf.Load()
if err != nil {
t.Error(err)
return
}
mainInfo := iprog.Created[0]
prog := ssa.Create(iprog, 0)
mainPkg := prog.Package(mainInfo.Pkg)
mainPkg.SetDebugMode(true)
mainPkg.Build()
if false {
// debugging
for _, mem := range mainPkg.Members {
if fn, ok := mem.(*ssa.Function); ok {
fn.WriteTo(os.Stderr)
}
}
}
// Find the actual AST node for each canonical position.
parenExprByPos := make(map[token.Pos]*ast.ParenExpr)
ast.Inspect(f, func(n ast.Node) bool {
if n != nil {
if e, ok := n.(*ast.ParenExpr); ok {
parenExprByPos[e.Pos()] = e
}
}
return true
})
// Find all annotations of form /*@kind*/.
for _, c := range f.Comments {
text := strings.TrimSpace(c.Text())
if text == "" || text[0] != '@' {
continue
}
text = text[1:]
pos := c.End() + 1
position := prog.Fset.Position(pos)
var e ast.Expr
if target := parenExprByPos[pos]; target == nil {
t.Errorf("%s: annotation doesn't precede ParenExpr: %q", position, text)
continue
} else {
e = target.X
}
path, _ := astutil.PathEnclosingInterval(f, pos, pos)
if path == nil {
t.Errorf("%s: can't find AST path from root to comment: %s", position, text)
continue
}
fn := ssa.EnclosingFunction(mainPkg, path)
if fn == nil {
t.Errorf("%s: can't find enclosing function", position)
continue
}
v, gotAddr := fn.ValueForExpr(e) // (may be nil)
got := strings.TrimPrefix(fmt.Sprintf("%T", v), "*ssa.")
if want := text; got != want {
t.Errorf("%s: got value %q, want %q", position, got, want)
}
if v != nil {
T := v.Type()
if gotAddr {
T = T.Underlying().(*types.Pointer).Elem() // deref
}
if !types.Identical(T, mainInfo.TypeOf(e)) {
t.Errorf("%s: got type %s, want %s", position, mainInfo.TypeOf(e), T)
}
}
}
}
示例11: TestEnclosingFunction
func TestEnclosingFunction(t *testing.T) {
tests := []struct {
input string // the input file
substr string // first occurrence of this string denotes interval
fn string // name of expected containing function
}{
// We use distinctive numbers as syntactic landmarks.
// Ordinary function:
{`package main
func f() { println(1003) }`,
"100", "main.f"},
// Methods:
{`package main
type T int
func (t T) f() { println(200) }`,
"200", "(main.T).f"},
// Function literal:
{`package main
func f() { println(func() { print(300) }) }`,
"300", "main.f$1"},
// Doubly nested
{`package main
func f() { println(func() { print(func() { print(350) })})}`,
"350", "main.f$1$1"},
// Implicit init for package-level var initializer.
{"package main; var a = 400", "400", "main.init"},
// No code for constants:
{"package main; const a = 500", "500", "(none)"},
// Explicit init()
{"package main; func init() { println(600) }", "600", "main.init#1"},
// Multiple explicit init functions:
{`package main
func init() { println("foo") }
func init() { println(800) }`,
"800", "main.init#2"},
// init() containing FuncLit.
{`package main
func init() { println(func(){print(900)}) }`,
"900", "main.init#1$1"},
}
for _, test := range tests {
conf := loader.Config{Fset: token.NewFileSet()}
f, start, end := findInterval(t, conf.Fset, test.input, test.substr)
if f == nil {
continue
}
path, exact := astutil.PathEnclosingInterval(f, start, end)
if !exact {
t.Errorf("EnclosingFunction(%q) not exact", test.substr)
continue
}
conf.CreateFromFiles("main", f)
iprog, err := conf.Load()
if err != nil {
t.Error(err)
continue
}
prog := ssa.Create(iprog, 0)
pkg := prog.Package(iprog.Created[0].Pkg)
pkg.Build()
name := "(none)"
fn := ssa.EnclosingFunction(pkg, path)
if fn != nil {
name = fn.String()
}
if name != test.fn {
t.Errorf("EnclosingFunction(%q in %q) got %s, want %s",
test.substr, test.input, name, test.fn)
continue
}
// While we're here: test HasEnclosingFunction.
if has := ssa.HasEnclosingFunction(pkg, path); has != (fn != nil) {
t.Errorf("HasEnclosingFunction(%q in %q) got %v, want %v",
test.substr, test.input, has, fn != nil)
continue
}
}
}
示例12: TestSyntheticFuncs
// TestSyntheticFuncs checks that the expected synthetic functions are
// created, reachable, and not duplicated.
func TestSyntheticFuncs(t *testing.T) {
const input = `package P
type T int
func (T) f() int
func (*T) g() int
var (
// thunks
a = T.f
b = T.f
c = (struct{T}).f
d = (struct{T}).f
e = (*T).g
f = (*T).g
g = (struct{*T}).g
h = (struct{*T}).g
// bounds
i = T(0).f
j = T(0).f
k = new(T).g
l = new(T).g
// wrappers
m interface{} = struct{T}{}
n interface{} = struct{T}{}
o interface{} = struct{*T}{}
p interface{} = struct{*T}{}
q interface{} = new(struct{T})
r interface{} = new(struct{T})
s interface{} = new(struct{*T})
t interface{} = new(struct{*T})
)
`
// Parse
var conf loader.Config
f, err := conf.ParseFile("<input>", input)
if err != nil {
t.Fatalf("parse: %v", err)
}
conf.CreateFromFiles(f.Name.Name, f)
// Load
iprog, err := conf.Load()
if err != nil {
t.Fatalf("Load: %v", err)
}
// Create and build SSA
prog := ssa.Create(iprog, 0)
prog.BuildAll()
// Enumerate reachable synthetic functions
want := map[string]string{
"(*P.T).g$bound": "bound method wrapper for func (*P.T).g() int",
"(P.T).f$bound": "bound method wrapper for func (P.T).f() int",
"(*P.T).g$thunk": "thunk for func (*P.T).g() int",
"(P.T).f$thunk": "thunk for func (P.T).f() int",
"(struct{*P.T}).g$thunk": "thunk for func (*P.T).g() int",
"(struct{P.T}).f$thunk": "thunk for func (P.T).f() int",
"(*P.T).f": "wrapper for func (P.T).f() int",
"(*struct{*P.T}).f": "wrapper for func (P.T).f() int",
"(*struct{*P.T}).g": "wrapper for func (*P.T).g() int",
"(*struct{P.T}).f": "wrapper for func (P.T).f() int",
"(*struct{P.T}).g": "wrapper for func (*P.T).g() int",
"(struct{*P.T}).f": "wrapper for func (P.T).f() int",
"(struct{*P.T}).g": "wrapper for func (*P.T).g() int",
"(struct{P.T}).f": "wrapper for func (P.T).f() int",
"P.init": "package initializer",
}
for fn := range ssautil.AllFunctions(prog) {
if fn.Synthetic == "" {
continue
}
name := fn.String()
wantDescr, ok := want[name]
if !ok {
t.Errorf("got unexpected/duplicate func: %q: %q", name, fn.Synthetic)
continue
}
delete(want, name)
if wantDescr != fn.Synthetic {
t.Errorf("(%s).Synthetic = %q, want %q", name, fn.Synthetic, wantDescr)
}
}
for fn, descr := range want {
t.Errorf("want func: %q: %q", fn, descr)
}
}
示例13: TestImportFromBinary
// Tests that programs partially loaded from gc object files contain
// functions with no code for the external portions, but are otherwise ok.
func TestImportFromBinary(t *testing.T) {
test := `
package main
import (
"bytes"
"io"
"testing"
)
func main() {
var t testing.T
t.Parallel() // static call to external declared method
t.Fail() // static call to promoted external declared method
testing.Short() // static call to external package-level function
var w io.Writer = new(bytes.Buffer)
w.Write(nil) // interface invoke of external declared method
}
`
// Create a single-file main package.
conf := loader.Config{ImportFromBinary: true}
f, err := conf.ParseFile("<input>", test)
if err != nil {
t.Error(err)
return
}
conf.CreateFromFiles("main", f)
iprog, err := conf.Load()
if err != nil {
t.Error(err)
return
}
prog := ssa.Create(iprog, ssa.SanityCheckFunctions)
mainPkg := prog.Package(iprog.Created[0].Pkg)
mainPkg.Build()
// The main package, its direct and indirect dependencies are loaded.
deps := []string{
// directly imported dependencies:
"bytes", "io", "testing",
// indirect dependencies (partial list):
"errors", "fmt", "os", "runtime",
}
all := prog.AllPackages()
if len(all) <= len(deps) {
t.Errorf("unexpected set of loaded packages: %q", all)
}
for _, path := range deps {
pkg := prog.ImportedPackage(path)
if pkg == nil {
t.Errorf("package not loaded: %q", path)
continue
}
// External packages should have no function bodies (except for wrappers).
isExt := pkg != mainPkg
// init()
if isExt && !isEmpty(pkg.Func("init")) {
t.Errorf("external package %s has non-empty init", pkg)
} else if !isExt && isEmpty(pkg.Func("init")) {
t.Errorf("main package %s has empty init", pkg)
}
for _, mem := range pkg.Members {
switch mem := mem.(type) {
case *ssa.Function:
// Functions at package level.
if isExt && !isEmpty(mem) {
t.Errorf("external function %s is non-empty", mem)
} else if !isExt && isEmpty(mem) {
t.Errorf("function %s is empty", mem)
}
case *ssa.Type:
// Methods of named types T.
// (In this test, all exported methods belong to *T not T.)
if !isExt {
t.Fatalf("unexpected name type in main package: %s", mem)
}
mset := prog.MethodSets.MethodSet(types.NewPointer(mem.Type()))
for i, n := 0, mset.Len(); i < n; i++ {
m := prog.Method(mset.At(i))
// For external types, only synthetic wrappers have code.
expExt := !strings.Contains(m.Synthetic, "wrapper")
if expExt && !isEmpty(m) {
t.Errorf("external method %s is non-empty: %s",
m, m.Synthetic)
} else if !expExt && isEmpty(m) {
t.Errorf("method function %s is empty: %s",
m, m.Synthetic)
}
}
//.........這裏部分代碼省略.........
示例14: TestStdlib
func TestStdlib(t *testing.T) {
runtime.GC()
t0 := time.Now()
var memstats runtime.MemStats
runtime.ReadMemStats(&memstats)
alloc := memstats.Alloc
// Load, parse and type-check the program.
ctxt := build.Default // copy
ctxt.GOPATH = "" // disable GOPATH
conf := loader.Config{Build: &ctxt}
for _, path := range buildutil.AllPackages(conf.Build) {
conf.ImportWithTests(path)
}
prog, err := conf.Load()
if err != nil {
t.Fatalf("Load failed: %v", err)
}
t1 := time.Now()
runtime.GC()
runtime.ReadMemStats(&memstats)
numPkgs := len(prog.AllPackages)
if want := 205; numPkgs < want {
t.Errorf("Loaded only %d packages, want at least %d", numPkgs, want)
}
// Dump package members.
if false {
for pkg := range prog.AllPackages {
fmt.Printf("Package %s:\n", pkg.Path())
scope := pkg.Scope()
for _, name := range scope.Names() {
if ast.IsExported(name) {
fmt.Printf("\t%s\n", types.ObjectString(pkg, scope.Lookup(name)))
}
}
fmt.Println()
}
}
// Check that Test functions for io/ioutil, regexp and
// compress/bzip2 are all simultaneously present.
// (The apparent cycle formed when augmenting all three of
// these packages by their tests was the original motivation
// for reporting b/7114.)
//
// compress/bzip2.TestBitReader in bzip2_test.go imports io/ioutil
// io/ioutil.TestTempFile in tempfile_test.go imports regexp
// regexp.TestRE2Search in exec_test.go imports compress/bzip2
for _, test := range []struct{ pkg, fn string }{
{"io/ioutil", "TestTempFile"},
{"regexp", "TestRE2Search"},
{"compress/bzip2", "TestBitReader"},
} {
info := prog.Imported[test.pkg]
if info == nil {
t.Errorf("failed to load package %q", test.pkg)
continue
}
obj, _ := info.Pkg.Scope().Lookup(test.fn).(*types.Func)
if obj == nil {
t.Errorf("package %q has no func %q", test.pkg, test.fn)
continue
}
}
// Dump some statistics.
// determine line count
var lineCount int
prog.Fset.Iterate(func(f *token.File) bool {
lineCount += f.LineCount()
return true
})
t.Log("GOMAXPROCS: ", runtime.GOMAXPROCS(0))
t.Log("#Source lines: ", lineCount)
t.Log("Load/parse/typecheck: ", t1.Sub(t0))
t.Log("#MB: ", int64(memstats.Alloc-alloc)/1000000)
}
示例15: TestCgoOption
func TestCgoOption(t *testing.T) {
switch runtime.GOOS {
// On these systems, the net and os/user packages don't use cgo.
case "plan9", "solaris", "windows":
return
}
// In nocgo builds (e.g. linux-amd64-nocgo),
// there is no "runtime/cgo" package,
// so cgo-generated Go files will have a failing import.
if !build.Default.CgoEnabled {
return
}
// Test that we can load cgo-using packages with
// CGO_ENABLED=[01], which causes go/build to select pure
// Go/native implementations, respectively, based on build
// tags.
//
// Each entry specifies a package-level object and the generic
// file expected to define it when cgo is disabled.
// When cgo is enabled, the exact file is not specified (since
// it varies by platform), but must differ from the generic one.
//
// The test also loads the actual file to verify that the
// object is indeed defined at that location.
for _, test := range []struct {
pkg, name, genericFile string
}{
{"net", "cgoLookupHost", "cgo_stub.go"},
{"os/user", "lookupId", "lookup_stubs.go"},
} {
ctxt := build.Default
for _, ctxt.CgoEnabled = range []bool{false, true} {
conf := loader.Config{Build: &ctxt}
conf.Import(test.pkg)
prog, err := conf.Load()
if err != nil {
t.Errorf("Load failed: %v", err)
continue
}
info := prog.Imported[test.pkg]
if info == nil {
t.Errorf("package %s not found", test.pkg)
continue
}
obj := info.Pkg.Scope().Lookup(test.name)
if obj == nil {
t.Errorf("no object %s.%s", test.pkg, test.name)
continue
}
posn := prog.Fset.Position(obj.Pos())
t.Logf("%s: %s (CgoEnabled=%t)", posn, obj, ctxt.CgoEnabled)
gotFile := filepath.Base(posn.Filename)
filesMatch := gotFile == test.genericFile
if ctxt.CgoEnabled && filesMatch {
t.Errorf("CGO_ENABLED=1: %s found in %s, want native file",
obj, gotFile)
} else if !ctxt.CgoEnabled && !filesMatch {
t.Errorf("CGO_ENABLED=0: %s found in %s, want %s",
obj, gotFile, test.genericFile)
}
// Load the file and check the object is declared at the right place.
b, err := ioutil.ReadFile(posn.Filename)
if err != nil {
t.Errorf("can't read %s: %s", posn.Filename, err)
continue
}
line := string(bytes.Split(b, []byte("\n"))[posn.Line-1])
ident := line[posn.Column-1:]
if !strings.HasPrefix(ident, test.name) {
t.Errorf("%s: %s not declared here (looking at %q)", posn, obj, ident)
}
}
}
}