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