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