github.com/tiagovtristao/plz@v13.4.0+incompatible/src/test/gcov_coverage.go (about)

     1  // Code for parsing gcov coverage output.
     2  
     3  package test
     4  
     5  import (
     6  	"bytes"
     7  	"fmt"
     8  	"strconv"
     9  	"strings"
    10  
    11  	"github.com/thought-machine/please/src/core"
    12  )
    13  
    14  // gcovPlaceholder is used to mark empty coverage files for C++ tests when coverage is disabled for them.
    15  var gcovPlaceholder = []byte{'g', 'c', 'o', 'v'}
    16  
    17  func parseGcovCoverageResults(target *core.BuildTarget, coverage *core.TestCoverage, data []byte) error {
    18  	if bytes.Equal(data, gcovPlaceholder) {
    19  		return nil // Coverage is disabled, not an error.
    20  	}
    21  	// The data we have is a sequence of .gcov files smashed together.
    22  	lines := bytes.Split(data, []byte{'\n'})
    23  	if len(lines) == 0 {
    24  		return fmt.Errorf("Empty coverage file")
    25  	}
    26  	currentFilename := ""
    27  	for lineno, line := range lines {
    28  		fields := bytes.Split(line, []byte{':'})
    29  		if len(fields) < 3 {
    30  			continue
    31  		}
    32  		if bytes.Equal(fields[2], []byte("Source")) {
    33  			if len(fields) < 4 {
    34  				return fmt.Errorf("Bad source on line %d: %s", lineno, string(line))
    35  			}
    36  			currentFilename = string(fields[3])
    37  			continue
    38  		}
    39  		covLine, err := strconv.Atoi(strings.TrimSpace(string(fields[1])))
    40  		if err != nil {
    41  			return fmt.Errorf("Bad line number on line %d: %s", lineno, string(line))
    42  		} else if covLine > 0 {
    43  			coverage.Files[currentFilename] = append(coverage.Files[currentFilename], translateGcovCount(bytes.TrimSpace(fields[0])))
    44  		}
    45  	}
    46  	return nil
    47  }
    48  
    49  // translateGcovCount coverts gcov's format to ours.
    50  // AFAICT the format is:
    51  //       -: Not executable
    52  //   #####: Not covered
    53  //      32: line was hit 32 times
    54  func translateGcovCount(gcov []byte) core.LineCoverage {
    55  	if len(gcov) > 0 && gcov[0] == '-' {
    56  		return core.NotExecutable
    57  	} else if i, err := strconv.Atoi(string(gcov)); err == nil && i > 0 {
    58  		return core.Covered
    59  	}
    60  	return core.Uncovered
    61  }
    62  
    63  // looksLikeGcovCoverageResults returns true if the given data appears to be gcov results.
    64  func looksLikeGcovCoverageResults(data []byte) bool {
    65  	return bytes.HasPrefix(data, []byte("        -:    0:Source:")) || bytes.Equal(data, gcovPlaceholder)
    66  }