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