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 / rta / rta_test.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/honnef.co/go/tools@v0.0.1-2020.1.5/callgraph/rta/rta_test.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/honnef.co/go/tools@v0.0.1-2020.1.5/callgraph/rta/rta_test.go
new file mode 100644 (file)
index 0000000..e586db7
--- /dev/null
@@ -0,0 +1,141 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//lint:file-ignore SA1019 go/callgraph's test suite is built around the deprecated go/loader. We'll leave fixing that to upstream.
+
+// No testdata on Android.
+
+// +build !android
+
+package rta_test
+
+import (
+       "bytes"
+       "fmt"
+       "go/ast"
+       "go/parser"
+       "go/token"
+       "go/types"
+       "io/ioutil"
+       "sort"
+       "strings"
+       "testing"
+
+       "golang.org/x/tools/go/loader"
+       "honnef.co/go/tools/callgraph"
+       "honnef.co/go/tools/callgraph/rta"
+       "honnef.co/go/tools/ir"
+       "honnef.co/go/tools/ir/irutil"
+)
+
+var inputs = []string{
+       "testdata/func.go",
+       "testdata/rtype.go",
+       "testdata/iface.go",
+}
+
+func expectation(f *ast.File) (string, token.Pos) {
+       for _, c := range f.Comments {
+               text := strings.TrimSpace(c.Text())
+               if t := strings.TrimPrefix(text, "WANT:\n"); t != text {
+                       return t, c.Pos()
+               }
+       }
+       return "", token.NoPos
+}
+
+// TestRTA runs RTA on each file in inputs, prints the results, and
+// compares it with the golden results embedded in the WANT comment at
+// the end of the file.
+//
+// The results string consists of two parts: the set of dynamic call
+// edges, "f --> g", one per line, and the set of reachable functions,
+// one per line.  Each set is sorted.
+//
+func TestRTA(t *testing.T) {
+       for _, filename := range inputs {
+               content, err := ioutil.ReadFile(filename)
+               if err != nil {
+                       t.Errorf("couldn't read file '%s': %s", filename, err)
+                       continue
+               }
+
+               conf := loader.Config{
+                       ParserMode: parser.ParseComments,
+               }
+               f, err := conf.ParseFile(filename, content)
+               if err != nil {
+                       t.Error(err)
+                       continue
+               }
+
+               want, pos := expectation(f)
+               if pos == token.NoPos {
+                       t.Errorf("No WANT: comment in %s", filename)
+                       continue
+               }
+
+               conf.CreateFromFiles("main", f)
+               iprog, err := conf.Load()
+               if err != nil {
+                       t.Error(err)
+                       continue
+               }
+
+               prog := irutil.CreateProgram(iprog, 0)
+               mainPkg := prog.Package(iprog.Created[0].Pkg)
+               prog.Build()
+
+               res := rta.Analyze([]*ir.Function{
+                       mainPkg.Func("main"),
+                       mainPkg.Func("init"),
+               }, true)
+
+               if got := printResult(res, mainPkg.Pkg); got != want {
+                       t.Errorf("%s: got:\n%s\nwant:\n%s",
+                               prog.Fset.Position(pos), got, want)
+               }
+       }
+}
+
+func printResult(res *rta.Result, from *types.Package) string {
+       var buf bytes.Buffer
+
+       writeSorted := func(ss []string) {
+               sort.Strings(ss)
+               for _, s := range ss {
+                       fmt.Fprintf(&buf, "  %s\n", s)
+               }
+       }
+
+       buf.WriteString("Dynamic calls\n")
+       var edges []string
+       callgraph.GraphVisitEdges(res.CallGraph, func(e *callgraph.Edge) error {
+               if strings.Contains(e.Description(), "dynamic") {
+                       edges = append(edges, fmt.Sprintf("%s --> %s",
+                               e.Caller.Func.RelString(from),
+                               e.Callee.Func.RelString(from)))
+               }
+               return nil
+       })
+       writeSorted(edges)
+
+       buf.WriteString("Reachable functions\n")
+       var reachable []string
+       for f := range res.Reachable {
+               reachable = append(reachable, f.RelString(from))
+       }
+       writeSorted(reachable)
+
+       buf.WriteString("Reflect types\n")
+       var rtypes []string
+       res.RuntimeTypes.Iterate(func(key types.Type, value interface{}) {
+               if value == false { // accessible to reflection
+                       rtypes = append(rtypes, types.TypeString(key, types.RelativeTo(from)))
+               }
+       })
+       writeSorted(rtypes)
+
+       return strings.TrimSpace(buf.String())
+}