github.com/golangci/go-tools@v0.0.0-20190318060251-af6baa5dc196/callgraph/static/static_test.go (about)

     1  // Copyright 2014 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package static_test
     6  
     7  import (
     8  	"fmt"
     9  	"go/parser"
    10  	"reflect"
    11  	"sort"
    12  	"testing"
    13  
    14  	"github.com/golangci/go-tools/callgraph"
    15  	"github.com/golangci/go-tools/callgraph/static"
    16  	"golang.org/x/tools/go/loader"
    17  	"github.com/golangci/go-tools/ssa/ssautil"
    18  )
    19  
    20  const input = `package P
    21  
    22  type C int
    23  func (C) f()
    24  
    25  type I interface{f()}
    26  
    27  func f() {
    28  	p := func() {}
    29  	g()
    30  	p() // SSA constant propagation => static
    31  
    32  	if unknown {
    33  		p = h
    34  	}
    35  	p() // dynamic
    36  
    37  	C(0).f()
    38  }
    39  
    40  func g() {
    41  	var i I = C(0)
    42  	i.f()
    43  }
    44  
    45  func h()
    46  
    47  var unknown bool
    48  `
    49  
    50  func TestStatic(t *testing.T) {
    51  	conf := loader.Config{ParserMode: parser.ParseComments}
    52  	f, err := conf.ParseFile("P.go", input)
    53  	if err != nil {
    54  		t.Fatal(err)
    55  	}
    56  
    57  	conf.CreateFromFiles("P", f)
    58  	iprog, err := conf.Load()
    59  	if err != nil {
    60  		t.Fatal(err)
    61  	}
    62  
    63  	P := iprog.Created[0].Pkg
    64  
    65  	prog := ssautil.CreateProgram(iprog, 0)
    66  	prog.Build()
    67  
    68  	cg := static.CallGraph(prog)
    69  
    70  	var edges []string
    71  	callgraph.GraphVisitEdges(cg, func(e *callgraph.Edge) error {
    72  		edges = append(edges, fmt.Sprintf("%s -> %s",
    73  			e.Caller.Func.RelString(P),
    74  			e.Callee.Func.RelString(P)))
    75  		return nil
    76  	})
    77  	sort.Strings(edges)
    78  
    79  	want := []string{
    80  		"(*C).f -> (C).f",
    81  		"f -> (C).f",
    82  		"f -> f$1",
    83  		"f -> g",
    84  	}
    85  	if !reflect.DeepEqual(edges, want) {
    86  		t.Errorf("Got edges %v, want %v", edges, want)
    87  	}
    88  }