Marvin Preuss
1d4ae27878
All checks were successful
continuous-integration/drone/push Build is passing
64 lines
1.6 KiB
Go
64 lines
1.6 KiB
Go
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()
|
|
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
|
|
}
|