// 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) } }