-
Notifications
You must be signed in to change notification settings - Fork 4
/
testmap.go
67 lines (56 loc) · 1.66 KB
/
testmap.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package tparallel
import (
"go/types"
"strings"
"github.com/gostaticanalysis/analysisutil"
"golang.org/x/tools/go/analysis/passes/buildssa"
"golang.org/x/tools/go/ssa"
"github.com/moricho/tparallel/pkg/ssainstr"
)
// getTestMap gets a set of a top-level test and its sub-tests
func getTestMap(ssaanalyzer *buildssa.SSA, testTyp types.Type) map[*ssa.Function][]*ssa.Function {
testMap := map[*ssa.Function][]*ssa.Function{}
trun := analysisutil.MethodOf(testTyp, "Run")
for _, f := range ssaanalyzer.SrcFuncs {
if !strings.HasPrefix(f.Name(), "Test") || !(f.Parent() == (*ssa.Function)(nil)) {
continue
}
testMap[f] = []*ssa.Function{}
for _, block := range f.Blocks {
for _, instr := range block.Instrs {
called := analysisutil.Called(instr, nil, trun)
if !called && ssainstr.HasArgs(instr, types.NewPointer(testTyp)) {
if instrs, ok := ssainstr.LookupCalled(instr, trun); ok {
for _, v := range instrs {
testMap[f] = appendTestMap(testMap[f], v)
}
}
} else if called {
testMap[f] = appendTestMap(testMap[f], instr)
}
}
}
}
return testMap
}
// appendTestMap converts ssa.Instruction to ssa.Function and append it to a given sub-test slice
func appendTestMap(subtests []*ssa.Function, instr ssa.Instruction) []*ssa.Function {
call, ok := instr.(ssa.CallInstruction)
if !ok {
return subtests
}
ssaCall := call.Value()
if ssaCall == nil {
return subtests
}
for _, arg := range ssaCall.Call.Args {
switch arg := arg.(type) {
case *ssa.Function:
subtests = append(subtests, arg)
case *ssa.MakeClosure:
fn, _ := arg.Fn.(*ssa.Function)
subtests = append(subtests, fn)
}
}
return subtests
}