github.com/please-build/go-rules/tools/please_go@v0.0.0-20240319165128-ea27d6f5caba/test/find_cover_vars.go (about)

     1  // Package test contains utilities used by plz_go_test.
     2  package test
     3  
     4  import (
     5  	"fmt"
     6  	"os"
     7  	"path"
     8  	"path/filepath"
     9  	"strings"
    10  )
    11  
    12  // A CoverVar is just a combination of package path and variable name
    13  // for one of the templated-in coverage variables.
    14  type CoverVar struct {
    15  	Dir, ImportPath, ImportName, Var, File string
    16  }
    17  
    18  // FindCoverVars searches the given directory recursively to find all Go files with coverage variables.
    19  func FindCoverVars(dir, testPackage string, external bool, excludedDirs []string) ([]CoverVar, error) {
    20  	if dir == "" {
    21  		return nil, nil
    22  	}
    23  	excludeMap := map[string]struct{}{}
    24  	for _, e := range excludedDirs {
    25  		excludeMap[e] = struct{}{}
    26  	}
    27  	var ret []CoverVar
    28  
    29  	err := filepath.WalkDir(dir, func(name string, info os.DirEntry, err error) error {
    30  		if err != nil {
    31  			return err
    32  		}
    33  		if _, present := excludeMap[name]; present {
    34  			if info.IsDir() {
    35  				return filepath.SkipDir
    36  			}
    37  		} else if strings.HasSuffix(name, ".cover_vars") {
    38  			vars, err := parseCoverVars(name, testPackage, external)
    39  			if err != nil {
    40  				return err
    41  			}
    42  			ret = append(ret, vars...)
    43  		}
    44  		return nil
    45  	})
    46  	return ret, err
    47  }
    48  
    49  // parseCoverVars parses the coverage variables file for all cover vars
    50  func parseCoverVars(filepath, testPackage string, external bool) ([]CoverVar, error) {
    51  	dir := strings.TrimRight(path.Dir(filepath), "/")
    52  	if dir == "" {
    53  		dir = "."
    54  	}
    55  
    56  	b, err := os.ReadFile(filepath)
    57  	if err != nil {
    58  		return nil, err
    59  	}
    60  	lines := strings.Split(string(b), "\n")
    61  	ret := make([]CoverVar, 0, len(lines))
    62  	for _, line := range lines {
    63  		if strings.TrimSpace(line) == "" {
    64  			continue
    65  		}
    66  
    67  		parts := strings.Split(line, "=")
    68  		if len(parts) != 2 {
    69  			return nil, fmt.Errorf("malformed cover var line in %v: %v", filepath, line)
    70  		}
    71  		if external || dir != os.Getenv("PKG_DIR") {
    72  			ret = append(ret, coverVar(dir, parts[0], parts[1]))
    73  		} else {
    74  			// We recompile the test package, so override the import path here to get the right version
    75  			ret = append(ret, coverVar(dir, testPackage, parts[1]))
    76  		}
    77  	}
    78  
    79  	return ret, nil
    80  }
    81  
    82  func coverVar(dir, importPath, v string) CoverVar {
    83  	fmt.Fprintf(os.Stderr, "Found cover variable: %s %s %s\n", dir, importPath, v)
    84  	f := path.Join(dir, strings.TrimPrefix(v, "GoCover_"))
    85  	if strings.HasSuffix(f, "_go") {
    86  		f = f[:len(f)-3] + ".go"
    87  	}
    88  	return CoverVar{
    89  		Dir:        dir,
    90  		ImportPath: importPath,
    91  		Var:        v,
    92  		File:       f,
    93  	}
    94  }