1
2
3
4
5 package vta
6
7 import (
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 )
17
18 func TestVTACallGraph(t *testing.T) {
19 for _, file := range []string{
20 "testdata/src/callgraph_static.go",
21 "testdata/src/callgraph_ho.go",
22 "testdata/src/callgraph_interfaces.go",
23 "testdata/src/callgraph_pointers.go",
24 "testdata/src/callgraph_collections.go",
25 "testdata/src/callgraph_fields.go",
26 "testdata/src/callgraph_field_funcs.go",
27 "testdata/src/callgraph_recursive_types.go",
28 "testdata/src/callgraph_issue_57756.go",
29 "testdata/src/callgraph_comma_maps.go",
30 "testdata/src/callgraph_type_aliases.go",
31 } {
32 t.Run(file, func(t *testing.T) {
33 prog, want, err := testProg(file, ssa.BuilderMode(0))
34 if err != nil {
35 t.Fatalf("couldn't load test file '%s': %s", file, err)
36 }
37 if len(want) == 0 {
38 t.Fatalf("couldn't find want in `%s`", file)
39 }
40
41 g := CallGraph(ssautil.AllFunctions(prog), cha.CallGraph(prog))
42 got := callGraphStr(g)
43 if diff := setdiff(want, got); len(diff) > 0 {
44 t.Errorf("computed callgraph %v\nshould contain\n%v\n(diff: %v)", got, want, diff)
45 }
46 })
47 }
48 }
49
50
51
52
53 func TestVTAProgVsFuncSet(t *testing.T) {
54 prog, want, err := testProg("testdata/src/callgraph_nested_ptr.go", ssa.BuilderMode(0))
55 if err != nil {
56 t.Fatalf("couldn't load test `testdata/src/callgraph_nested_ptr.go`: %s", err)
57 }
58 if len(want) == 0 {
59 t.Fatal("couldn't find want in `testdata/src/callgraph_nested_ptr.go`")
60 }
61
62 allFuncs := ssautil.AllFunctions(prog)
63 g := CallGraph(allFuncs, cha.CallGraph(prog))
64
65
66 got := callGraphStr(g)
67 if diff := setdiff(want, got); len(diff) > 0 {
68 t.Errorf("computed callgraph %v should contain %v (diff: %v)", got, want, diff)
69 }
70
71
72
73
74
75
76
77
78 noBarFuncs := make(map[*ssa.Function]bool)
79 for f, in := range allFuncs {
80 noBarFuncs[f] = in && (funcName(f) != "Bar")
81 }
82 want = []string{"Baz: Do(i) -> Do; invoke t2.Foo() -> A.Foo"}
83 g = CallGraph(noBarFuncs, cha.CallGraph(prog))
84 got = callGraphStr(g)
85 if diff := setdiff(want, got); len(diff) > 0 {
86 t.Errorf("pruned callgraph %v should contain %v (diff: %v)", got, want, diff)
87 }
88 }
89
90
91
92
93
94 func TestVTAPanicMissingDefinitions(t *testing.T) {
95 run := func(pass *analysis.Pass) (interface{}, error) {
96 s := pass.ResultOf[buildssa.Analyzer].(*buildssa.SSA)
97 CallGraph(ssautil.AllFunctions(s.Pkg.Prog), cha.CallGraph(s.Pkg.Prog))
98 return nil, nil
99 }
100
101 analyzer := &analysis.Analyzer{
102 Name: "test",
103 Doc: "test",
104 Run: run,
105 Requires: []*analysis.Analyzer{
106 buildssa.Analyzer,
107 },
108 }
109
110 testdata := analysistest.TestData()
111 res := analysistest.Run(t, testdata, analyzer, "t", "d")
112 if len(res) != 2 {
113 t.Errorf("want analysis results for 2 packages; got %v", len(res))
114 }
115 for _, r := range res {
116 if r.Err != nil {
117 t.Errorf("want no error for package %v; got %v", r.Pass.Pkg.Path(), r.Err)
118 }
119 }
120 }
121
122 func TestVTACallGraphGenerics(t *testing.T) {
123
124 files := []string{
125 "testdata/src/arrays_generics.go",
126 "testdata/src/callgraph_generics.go",
127 "testdata/src/issue63146.go",
128 }
129 for _, file := range files {
130 t.Run(file, func(t *testing.T) {
131 prog, want, err := testProg(file, ssa.InstantiateGenerics)
132 if err != nil {
133 t.Fatalf("couldn't load test file '%s': %s", file, err)
134 }
135 if len(want) == 0 {
136 t.Fatalf("couldn't find want in `%s`", file)
137 }
138
139 g := CallGraph(ssautil.AllFunctions(prog), cha.CallGraph(prog))
140 got := callGraphStr(g)
141 if diff := setdiff(want, got); len(diff) != 0 {
142 t.Errorf("computed callgraph %v should contain %v (diff: %v)", got, want, diff)
143 logFns(t, prog)
144 }
145 })
146 }
147 }
148
149 func TestVTACallGraphGo117(t *testing.T) {
150 file := "testdata/src/go117.go"
151 prog, want, err := testProg(file, ssa.BuilderMode(0))
152 if err != nil {
153 t.Fatalf("couldn't load test file '%s': %s", file, err)
154 }
155 if len(want) == 0 {
156 t.Fatalf("couldn't find want in `%s`", file)
157 }
158
159 g, _ := typePropGraph(ssautil.AllFunctions(prog), cha.CallGraph(prog))
160 got := vtaGraphStr(g)
161 if diff := setdiff(want, got); len(diff) != 0 {
162 t.Errorf("`%s`: want superset of %v;\n got %v", file, want, got)
163 }
164 }
165
View as plain text