dnscrypt-proxy/vendor/github.com/moricho/tparallel/testmap.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
}