in tools/test-reader/reader/reader.go [113:157]
func readTestFunc(testFunc *ast.FuncDecl, funcDecls map[string]*ast.FuncDecl, varDecls map[string]*ast.BasicLit) ([]*Test, error) {
// This is an exported test function.
var tests []*Test
var errs []error
vars := make(map[string]*ast.CompositeLit, len(testFunc.Body.List)) // map of variable names to composite literal values in function body
for _, stmt := range testFunc.Body.List {
if exprStmt, ok := stmt.(*ast.ExprStmt); ok {
if callExpr, ok := exprStmt.X.(*ast.CallExpr); ok {
// This is a call expression.
ident, isIdent := callExpr.Fun.(*ast.Ident)
selExpr, isSelExpr := callExpr.Fun.(*ast.SelectorExpr)
if isIdent && ident.Name == "VcrTest" || isSelExpr && selExpr.Sel.Name == "VcrTest" {
test, err := readVcrTestCall(callExpr, funcDecls, varDecls)
if err != nil {
errs = append(errs, err)
}
test.Name = testFunc.Name.Name
tests = append(tests, test)
}
}
} else if assignStmt, ok := stmt.(*ast.AssignStmt); ok {
if len(assignStmt.Lhs) == 1 && len(assignStmt.Rhs) == 1 {
// For now, only allow single assignment variables for serial test maps.
// e.g. testCases := map[string]func(t *testing.T) {...
if ident, ok := assignStmt.Lhs[0].(*ast.Ident); ok {
if rhsCompLit, ok := assignStmt.Rhs[0].(*ast.CompositeLit); ok {
vars[ident.Name] = rhsCompLit
}
}
}
} else if rangeStmt, ok := stmt.(*ast.RangeStmt); ok {
if ident, ok := rangeStmt.X.(*ast.Ident); ok {
if varCompLit, ok := vars[ident.Name]; ok {
serialTests, serialErrs := readSerialTestCompLit(varCompLit, funcDecls, varDecls)
errs = append(errs, serialErrs...)
tests = append(tests, serialTests...)
}
}
}
}
if len(errs) > 0 {
return tests, fmt.Errorf("errors reading test func %s: %v", testFunc.Name.Name, errs)
}
return tests, nil
}