github.com/llvm-mirror/llgo@v0.0.0-20190322182713-bf6f0a60fce1/third_party/gotools/go/callgraph/cha/cha_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 cha_test 6 7 import ( 8 "bytes" 9 "fmt" 10 "go/ast" 11 "go/parser" 12 "go/token" 13 "io/ioutil" 14 "sort" 15 "strings" 16 "testing" 17 18 "llvm.org/llgo/third_party/gotools/go/callgraph" 19 "llvm.org/llgo/third_party/gotools/go/callgraph/cha" 20 "llvm.org/llgo/third_party/gotools/go/loader" 21 "llvm.org/llgo/third_party/gotools/go/ssa" 22 "llvm.org/llgo/third_party/gotools/go/types" 23 ) 24 25 var inputs = []string{ 26 "testdata/func.go", 27 "testdata/iface.go", 28 "testdata/recv.go", 29 } 30 31 func expectation(f *ast.File) (string, token.Pos) { 32 for _, c := range f.Comments { 33 text := strings.TrimSpace(c.Text()) 34 if t := strings.TrimPrefix(text, "WANT:\n"); t != text { 35 return t, c.Pos() 36 } 37 } 38 return "", token.NoPos 39 } 40 41 // TestCHA runs CHA on each file in inputs, prints the dynamic edges of 42 // the call graph, and compares it with the golden results embedded in 43 // the WANT comment at the end of the file. 44 // 45 func TestCHA(t *testing.T) { 46 for _, filename := range inputs { 47 content, err := ioutil.ReadFile(filename) 48 if err != nil { 49 t.Errorf("couldn't read file '%s': %s", filename, err) 50 continue 51 } 52 53 conf := loader.Config{ 54 ParserMode: parser.ParseComments, 55 } 56 f, err := conf.ParseFile(filename, content) 57 if err != nil { 58 t.Error(err) 59 continue 60 } 61 62 want, pos := expectation(f) 63 if pos == token.NoPos { 64 t.Errorf("No WANT: comment in %s", filename) 65 continue 66 } 67 68 conf.CreateFromFiles("main", f) 69 iprog, err := conf.Load() 70 if err != nil { 71 t.Error(err) 72 continue 73 } 74 75 prog := ssa.Create(iprog, 0) 76 mainPkg := prog.Package(iprog.Created[0].Pkg) 77 prog.BuildAll() 78 79 cg := cha.CallGraph(prog) 80 81 if got := printGraph(cg, mainPkg.Object); got != want { 82 t.Errorf("%s: got:\n%s\nwant:\n%s", 83 prog.Fset.Position(pos), got, want) 84 } 85 } 86 } 87 88 func printGraph(cg *callgraph.Graph, from *types.Package) string { 89 var edges []string 90 callgraph.GraphVisitEdges(cg, func(e *callgraph.Edge) error { 91 if strings.Contains(e.Description(), "dynamic") { 92 edges = append(edges, fmt.Sprintf("%s --> %s", 93 e.Caller.Func.RelString(from), 94 e.Callee.Func.RelString(from))) 95 } 96 return nil 97 }) 98 sort.Strings(edges) 99 100 var buf bytes.Buffer 101 buf.WriteString("Dynamic calls\n") 102 for _, edge := range edges { 103 fmt.Fprintf(&buf, " %s\n", edge) 104 } 105 return strings.TrimSpace(buf.String()) 106 }