89 lines
1.4 KiB
Go
89 lines
1.4 KiB
Go
// Copyright 2014 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 static_test
|
|
|
|
import (
|
|
"fmt"
|
|
"go/parser"
|
|
"reflect"
|
|
"sort"
|
|
"testing"
|
|
|
|
"golang.org/x/tools/go/callgraph"
|
|
"golang.org/x/tools/go/callgraph/static"
|
|
"golang.org/x/tools/go/loader"
|
|
"golang.org/x/tools/go/ssa/ssautil"
|
|
)
|
|
|
|
const input = `package P
|
|
|
|
type C int
|
|
func (C) f()
|
|
|
|
type I interface{f()}
|
|
|
|
func f() {
|
|
p := func() {}
|
|
g()
|
|
p() // SSA constant propagation => static
|
|
|
|
if unknown {
|
|
p = h
|
|
}
|
|
p() // dynamic
|
|
|
|
C(0).f()
|
|
}
|
|
|
|
func g() {
|
|
var i I = C(0)
|
|
i.f()
|
|
}
|
|
|
|
func h()
|
|
|
|
var unknown bool
|
|
`
|
|
|
|
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 := ssautil.CreateProgram(iprog, 0)
|
|
prog.Build()
|
|
|
|
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)
|
|
}
|
|
}
|