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