blob: e1bfcd70759f590e78da5c8e0481dd2638875ba7 [file] [log] [blame]
// 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)
}
}