create coverage +reader

This commit is contained in:
Adrien Marquès 2019-11-23 01:04:35 +01:00
parent 1e1f38a89d
commit 743f7aa332
2 changed files with 159 additions and 0 deletions

116
coverage/reader.go Normal file
View File

@ -0,0 +1,116 @@
package coverage
import (
"bufio"
"fmt"
"io"
"strconv"
"strings"
)
// Parse creates a coverage files struct from a coverage file format
// you must provide @gopkg which is the package name
func Parse(r io.Reader, gopkg string) (*Files, error) {
reader := bufio.NewReader(r)
eof := false
var n uint = 0
files := &Files{
files: make(map[string]File),
packagePath: gopkg,
}
// read loop
for true {
n++
if eof {
break
}
notrim, err := reader.ReadString('\n')
if err == io.EOF {
if len(notrim) > 0 {
eof = true
} else {
break
}
}
line := strings.Trim(notrim, " \t\r\n")
if len(line) < 1 {
continue
}
// ignore first line
if n == 1 && line == "mode: set" {
continue
}
// extract features from line
var cover = Coverage{}
// format: filename:startLine.startColumn,endLine.endColumn occurences count
splitFile := strings.Split(line, ":")
if len(splitFile) != 2 {
return nil, fmt.Errorf("invalid format line %d", n)
}
filename := splitFile[0]
if !strings.HasPrefix(filename, gopkg) {
return nil, fmt.Errorf("invalid package name '%s' on line %d", gopkg, n)
}
filename = strings.TrimPrefix(filename, gopkg)
if len(filename) < 2 {
return nil, fmt.Errorf("invalid format line %d", n)
}
// remove starting '/'
if filename[0] == '/' {
filename = filename[1:]
}
splitSpace := strings.Split(splitFile[1], " ")
if len(splitSpace) != 3 {
return nil, fmt.Errorf("invalid format line %d", n)
}
separators := strings.Split(splitSpace[0], ",")
if len(separators) != 2 {
return nil, fmt.Errorf("invalid format line %d", n)
}
splitStart := strings.Split(separators[0], ".")
if len(splitStart) != 2 {
return nil, fmt.Errorf("invalid format line %d", n)
}
cover.StartLine, err = strconv.ParseUint(splitStart[0], 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid format line %d", n)
}
cover.StartColumn, err = strconv.ParseUint(splitStart[1], 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid format line %d", n)
}
splitEnd := strings.Split(separators[1], ".")
if len(splitEnd) != 2 {
return nil, fmt.Errorf("invalid format line %d", n)
}
cover.EndLine, err = strconv.ParseUint(splitEnd[0], 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid format line %d", n)
}
cover.EndColumn, err = strconv.ParseUint(splitEnd[1], 10, 64)
if err != nil {
return nil, fmt.Errorf("invalid format line %d", n)
}
// append to files
_, isset := files.files[filename]
if !isset {
files.files[filename] = make(File, 0)
}
files.files[filename] = append(files.files[filename], cover)
}
return files, nil
}

43
coverage/types.go Normal file
View File

@ -0,0 +1,43 @@
package coverage
import "strings"
// Files contains coverage files indexed by file path
type Files struct {
packagePath string
files map[string]File
}
// File represents every coverage chunk for a file
type File []Coverage
// Coverage represents a covered chunk
type Coverage struct {
StartLine uint64
StartColumn uint64
EndLine uint64
EndColumn uint64
}
// GetFile returns the formatted coverage for the file located at @path
func (f *Files) GetFile(path string) []File {
var isDir bool = !strings.HasSuffix(path, ".go")
files := make([]File, 0)
// search in coverage files
for fPath, fileCoverage := range f.files {
if !isDir && path == fPath {
files = append(files, fileCoverage)
// if not directory search, stop at first result
break
}
if isDir && (path == "." || strings.HasPrefix(fPath, path)) {
files = append(files, fileCoverage)
}
}
return files
}