GoPLS Viewer

Home|gopls/go/callgraph/vta/vta_test.go
1// Copyright 2021 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
5package vta
6
7import (
8    "testing"
9
10    "golang.org/x/tools/go/analysis"
11    "golang.org/x/tools/go/analysis/analysistest"
12    "golang.org/x/tools/go/analysis/passes/buildssa"
13    "golang.org/x/tools/go/callgraph/cha"
14    "golang.org/x/tools/go/ssa"
15    "golang.org/x/tools/go/ssa/ssautil"
16    "golang.org/x/tools/internal/typeparams"
17)
18
19func TestVTACallGraph(t *testing.T) {
20    for _file := range []string{
21        "testdata/src/callgraph_static.go",
22        "testdata/src/callgraph_ho.go",
23        "testdata/src/callgraph_interfaces.go",
24        "testdata/src/callgraph_pointers.go",
25        "testdata/src/callgraph_collections.go",
26        "testdata/src/callgraph_fields.go",
27        "testdata/src/callgraph_field_funcs.go",
28        "testdata/src/callgraph_recursive_types.go",
29    } {
30        t.Run(file, func(t *testing.T) {
31            progwanterr := testProg(filessa.BuilderMode(0))
32            if err != nil {
33                t.Fatalf("couldn't load test file '%s': %s"fileerr)
34            }
35            if len(want) == 0 {
36                t.Fatalf("couldn't find want in `%s`"file)
37            }
38
39            g := CallGraph(ssautil.AllFunctions(prog), cha.CallGraph(prog))
40            if got := callGraphStr(g); !subGraph(wantgot) {
41                t.Errorf("computed callgraph %v should contain %v"gotwant)
42            }
43        })
44    }
45}
46
47// TestVTAProgVsFuncSet exemplifies and tests different possibilities
48// enabled by having an arbitrary function set as input to CallGraph
49// instead of the whole program (i.e., ssautil.AllFunctions(prog)).
50func TestVTAProgVsFuncSet(t *testing.T) {
51    progwanterr := testProg("testdata/src/callgraph_nested_ptr.go"ssa.BuilderMode(0))
52    if err != nil {
53        t.Fatalf("couldn't load test `testdata/src/callgraph_nested_ptr.go`: %s"err)
54    }
55    if len(want) == 0 {
56        t.Fatal("couldn't find want in `testdata/src/callgraph_nested_ptr.go`")
57    }
58
59    allFuncs := ssautil.AllFunctions(prog)
60    g := CallGraph(allFuncscha.CallGraph(prog))
61    // VTA over the whole program will produce a call graph that
62    // includes Baz:(**i).Foo -> A.Foo, B.Foo.
63    if got := callGraphStr(g); !subGraph(wantgot) {
64        t.Errorf("computed callgraph %v should contain %v"gotwant)
65    }
66
67    // Prune the set of program functions to exclude Bar(). This should
68    // yield a call graph that includes different set of callees for Baz
69    // Baz:(**i).Foo -> A.Foo
70    //
71    // Note that the exclusion of Bar can happen, for instance, if Baz is
72    // considered an entry point of some data flow analysis and Bar is
73    // provably (e.g., using CHA forward reachability) unreachable from Baz.
74    noBarFuncs := make(map[*ssa.Function]bool)
75    for fin := range allFuncs {
76        noBarFuncs[f] = in && (funcName(f) != "Bar")
77    }
78    want = []string{"Baz: Do(i) -> Do; invoke t2.Foo() -> A.Foo"}
79    g = CallGraph(noBarFuncscha.CallGraph(prog))
80    if got := callGraphStr(g); !subGraph(wantgot) {
81        t.Errorf("pruned callgraph %v should contain %v"gotwant)
82    }
83}
84
85// TestVTAPanicMissingDefinitions tests if VTA gracefully handles the case
86// where VTA panics when a definition of a function or method is not
87// available, which can happen when using analysis package. A successful
88// test simply does not panic.
89func TestVTAPanicMissingDefinitions(t *testing.T) {
90    run := func(pass *analysis.Pass) (interface{}, error) {
91        s := pass.ResultOf[buildssa.Analyzer].(*buildssa.SSA)
92        CallGraph(ssautil.AllFunctions(s.Pkg.Prog), cha.CallGraph(s.Pkg.Prog))
93        return nilnil
94    }
95
96    analyzer := &analysis.Analyzer{
97        Name"test",
98        Doc:  "test",
99        Run:  run,
100        Requires: []*analysis.Analyzer{
101            buildssa.Analyzer,
102        },
103    }
104
105    testdata := analysistest.TestData()
106    res := analysistest.Run(ttestdataanalyzer"t""d")
107    if len(res) != 2 {
108        t.Errorf("want analysis results for 2 packages; got %v"len(res))
109    }
110    for _r := range res {
111        if r.Err != nil {
112            t.Errorf("want no error for package %v; got %v"r.Pass.Pkg.Path(), r.Err)
113        }
114    }
115}
116
117func TestVTACallGraphGenerics(t *testing.T) {
118    if !typeparams.Enabled {
119        t.Skip("TestVTACallGraphGenerics requires type parameters")
120    }
121
122    // TODO(zpavlinovic): add more tests
123    file := "testdata/src/callgraph_generics.go"
124    progwanterr := testProg(filessa.InstantiateGenerics)
125    if err != nil {
126        t.Fatalf("couldn't load test file '%s': %s"fileerr)
127    }
128    if len(want) == 0 {
129        t.Fatalf("couldn't find want in `%s`"file)
130    }
131
132    g := CallGraph(ssautil.AllFunctions(prog), cha.CallGraph(prog))
133    if got := callGraphStr(g); !subGraph(wantgot) {
134        t.Errorf("computed callgraph %v should contain %v"gotwant)
135    }
136}
137
MembersX
TestVTAPanicMissingDefinitions.analyzer
TestVTAPanicMissingDefinitions.res
TestVTACallGraphGenerics.err
TestVTACallGraphGenerics.got
TestVTACallGraph.t
TestVTACallGraph.RangeStmt_515.BlockStmt.BlockStmt.want
TestVTAProgVsFuncSet.noBarFuncs
TestVTACallGraphGenerics.t
TestVTACallGraphGenerics.prog
TestVTACallGraph.RangeStmt_515.file
TestVTACallGraph.RangeStmt_515.BlockStmt.BlockStmt.prog
TestVTACallGraph.RangeStmt_515.BlockStmt.BlockStmt.err
TestVTACallGraph.RangeStmt_515.BlockStmt.BlockStmt.got
TestVTAProgVsFuncSet.prog
TestVTACallGraphGenerics.file
TestVTAProgVsFuncSet.allFuncs
TestVTAProgVsFuncSet.g
TestVTAProgVsFuncSet.got
TestVTAProgVsFuncSet.RangeStmt_2612.f
TestVTAProgVsFuncSet.RangeStmt_2612.in
TestVTAPanicMissingDefinitions.testdata
analysis
TestVTAProgVsFuncSet.t
TestVTAProgVsFuncSet.want
analysistest
TestVTACallGraph
TestVTACallGraph.RangeStmt_515.BlockStmt.BlockStmt.g
TestVTAProgVsFuncSet
TestVTAPanicMissingDefinitions.t
TestVTACallGraphGenerics.want
buildssa
TestVTAPanicMissingDefinitions
TestVTAPanicMissingDefinitions.RangeStmt_3762.r
TestVTACallGraphGenerics.g
TestVTAProgVsFuncSet.err
TestVTACallGraphGenerics
Members
X