From 999efc12fa21e1936be5da805128540a968e1c46 Mon Sep 17 00:00:00 2001 From: Jin Date: Thu, 29 Apr 2021 18:22:18 +0800 Subject: [PATCH 1/4] Refactors to support package importing --- .idea/.gitignore | 8 +++ .idea/gcov2lcov.iml | 9 +++ .idea/modules.xml | 8 +++ .idea/vcs.xml | 6 ++ Makefile | 6 +- cmd/main.go | 68 ++++++++++++++++++++++ cmd/main_test.go | 4 ++ main.go => gcov2kov.go | 93 +++++++------------------------ main_test.go => gcov2lcov_test.go | 35 ++++++------ 9 files changed, 143 insertions(+), 94 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/gcov2lcov.iml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 cmd/main.go create mode 100644 cmd/main_test.go rename main.go => gcov2kov.go (80%) rename main_test.go => gcov2lcov_test.go (72%) diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..73f69e0 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/gcov2lcov.iml b/.idea/gcov2lcov.iml new file mode 100644 index 0000000..5e764c4 --- /dev/null +++ b/.idea/gcov2lcov.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..e512733 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Makefile b/Makefile index 6be341a..78d3f40 100644 --- a/Makefile +++ b/Makefile @@ -2,9 +2,9 @@ .PHONY: build test inttest clean build: - GOOS=linux GOARCH=amd64 go build -o bin/gcov2lcov-linux-amd64 . - GOOS=windows GOARCH=amd64 go build -o bin/gcov2lcov-win-amd64 . - GOOS=darwin GOARCH=amd64 go build -o bin/gcov2lcov-darwin-amd64 . + GOOS=linux GOARCH=amd64 go build -o bin/gcov2lcov-linux-amd64 ./cmd + GOOS=windows GOARCH=amd64 go build -o bin/gcov2lcov-win-amd64 ./cmd + GOOS=darwin GOARCH=amd64 go build -o bin/gcov2lcov-darwin-amd64 ./cmd test: go test ./... -coverprofile coverage.out diff --git a/cmd/main.go b/cmd/main.go new file mode 100644 index 0000000..0eb7308 --- /dev/null +++ b/cmd/main.go @@ -0,0 +1,68 @@ +// gcov2lcov - convert golang coverage files to the lcov format. +// +// Copyright (c) 2019 Jan Delgado +// Copyright (c) 2019 Richard S Allinson +// +// Credits: +// This tool is based on covfmt (https://github.com/ricallinson/covfmt) and +// uses some parts of goveralls (https://github.com/mattn/goveralls). +// +package main + +import ( + "flag" + "github.com/jandelgado/gcov2lcov" + "log" + "os" +) + +func main() { + os.Exit(gcovmain()) +} + +func gcovmain() int { + infileName := flag.String("infile", "", "go coverage file to read, default: ") + outfileName := flag.String("outfile", "", "lcov file to write, default: ") + useAbsoluteSourcePath := flag.Bool("use-absolute-source-path", false, + "use absolute paths for source file in lcov output, default: false") + flag.Parse() + if len(flag.Args()) > 0 { + flag.Usage() + return 1 + } + + infile := os.Stdin + outfile := os.Stdout + var err error + if *infileName != "" { + infile, err = os.Open(*infileName) + if err != nil { + log.Printf("error opening input file: %v\n", err) + return 2 + } + defer infile.Close() + } + if *outfileName != "" { + outfile, err = os.Create(*outfileName) + if err != nil { + log.Printf("error opening output file: %v\n", err) + return 3 + } + defer outfile.Close() + } + + var pathResolverFunc func(string) string + if *useAbsoluteSourcePath { + pathResolverFunc = gcov2lcov.AbsolutePathResolver + } else { + pathResolverFunc = gcov2lcov.RelativePathResolver + } + + err = gcov2lcov.ConvertCoverage(infile, outfile, pathResolverFunc) + if err != nil { + log.Printf("error: convert: %v", err) + return 4 + } + return 0 +} + diff --git a/cmd/main_test.go b/cmd/main_test.go new file mode 100644 index 0000000..5675657 --- /dev/null +++ b/cmd/main_test.go @@ -0,0 +1,4 @@ +// gcov2lcov - convert golang coverage files to the lcov format. +// (c) 2019 Jan Delgado +package main + diff --git a/main.go b/gcov2kov.go similarity index 80% rename from main.go rename to gcov2kov.go index e9d6496..388c1ef 100644 --- a/main.go +++ b/gcov2kov.go @@ -7,12 +7,11 @@ // This tool is based on covfmt (https://github.com/ricallinson/covfmt) and // uses some parts of goveralls (https://github.com/mattn/goveralls). // -package main +package gcov2lcov import ( "bufio" "errors" - "flag" "go/build" "io" "log" @@ -41,6 +40,26 @@ type cacheEntry struct { var pkgCache = map[string]cacheEntry{} +func ConvertCoverage(in io.Reader, out io.Writer, pathResolverFunc func(string) string) error { + blocks, err := parseCoverage(in, pathResolverFunc) + if err != nil { + return err + } + return writeLcov(blocks, out) +} + +func AbsolutePathResolver(name string) string { + return name +} + +func RelativePathResolver(name string) string { + if dir, ok := findRepositoryRoot(name); ok { + filename := strings.TrimPrefix(name, dir+string(os.PathSeparator)) + return filename + } + return name +} + // given a module+file spec (e.g. github.com/jandelgado/gcov2lcov/main.go), // strip of the module name and return the file name (e.g. main.go). func findFile(filePath string) (string, error) { @@ -73,18 +92,6 @@ func findRepositoryRoot(dir string) (string, bool) { return findRepositoryRoot(nextdir) } -func getSourceFileName(name string) string { - return name -} - -func getCoverallsSourceFileName(name string) string { - if dir, ok := findRepositoryRoot(name); ok { - filename := strings.TrimPrefix(name, dir+string(os.PathSeparator)) - return filename - } - return name -} - func keysOfMap(m map[int]int) []int { keys := make([]int, len(m)) i := 0 @@ -235,61 +242,3 @@ func parseCoverage(coverage io.Reader, pathResolverFunc func(string) string) (ma } return blocks, nil } - -func convertCoverage(in io.Reader, out io.Writer, pathResolverFunc func(string) string) error { - blocks, err := parseCoverage(in, pathResolverFunc) - if err != nil { - return err - } - return writeLcov(blocks, out) -} - -func main() { - os.Exit(gcovmain()) -} - -func gcovmain() int { - infileName := flag.String("infile", "", "go coverage file to read, default: ") - outfileName := flag.String("outfile", "", "lcov file to write, default: ") - useAbsoluteSourcePath := flag.Bool("use-absolute-source-path", false, - "use absolute paths for source file in lcov output, default: false") - flag.Parse() - if len(flag.Args()) > 0 { - flag.Usage() - return 1 - } - - infile := os.Stdin - outfile := os.Stdout - var err error - if *infileName != "" { - infile, err = os.Open(*infileName) - if err != nil { - log.Printf("error opening input file: %v\n", err) - return 2 - } - defer infile.Close() - } - if *outfileName != "" { - outfile, err = os.Create(*outfileName) - if err != nil { - log.Printf("error opening output file: %v\n", err) - return 3 - } - defer outfile.Close() - } - - var pathResolverFunc func(string) string - if *useAbsoluteSourcePath { - pathResolverFunc = getSourceFileName - } else { - pathResolverFunc = getCoverallsSourceFileName - } - - err = convertCoverage(infile, outfile, pathResolverFunc) - if err != nil { - log.Printf("error: convert: %v", err) - return 4 - } - return 0 -} diff --git a/main_test.go b/gcov2lcov_test.go similarity index 72% rename from main_test.go rename to gcov2lcov_test.go index 8d3817d..1605e1d 100644 --- a/main_test.go +++ b/gcov2lcov_test.go @@ -1,14 +1,11 @@ -// gcov2lcov - convert golang coverage files to the lcov format. -// (c) 2019 Jan Delgado -package main +package gcov2lcov import ( "bytes" + "github.com/stretchr/testify/assert" "os" "strings" "testing" - - "github.com/stretchr/testify/assert" ) func TestKeysOfMapReturnsAllKeysOfMap(t *testing.T) { @@ -35,11 +32,11 @@ func TestParseCoverageLineFailsOnInvalidLines(t *testing.T) { } func TestParseCoverageLineOfParsesValidLineCorrectly(t *testing.T) { - line := "github.com/jandelgado/gcov2lcov/main.go:6.14,8.3 2 1" + line := "github.com/jandelgado/gcov2lcov/cmd/main.go:6.14,8.3 2 1" file, b, err := parseCoverageLine(line) assert.Nil(t, err) - assert.Equal(t, "github.com/jandelgado/gcov2lcov/main.go", file) + assert.Equal(t, "github.com/jandelgado/gcov2lcov/cmd/main.go", file) assert.Equal(t, 6, b.startLine) assert.Equal(t, 14, b.startChar) assert.Equal(t, 8, b.endLine) @@ -53,17 +50,17 @@ func TestParseCoverage(t *testing.T) { // note: in this integrative test, the package path must match the actual // repository name of this project. cov := `mode: set -github.com/jandelgado/gcov2lcov/main.go:6.14,8.3 2 1` +github.com/jandelgado/gcov2lcov/cmd/main.go:6.14,8.3 2 1` reader := strings.NewReader(cov) - res, err := parseCoverage(reader, getCoverallsSourceFileName) + res, err := parseCoverage(reader, RelativePathResolver) assert.NoError(t, err) assert.Equal(t, 1, len(res)) for k, blks := range res { assert.Equal(t, 1, len(blks)) b := blks[0] - assert.Equal(t, "main.go", k) + assert.Equal(t, "cmd/main.go", k) assert.Equal(t, 6, b.startLine) assert.Equal(t, 14, b.startChar) assert.Equal(t, 8, b.endLine) @@ -78,16 +75,16 @@ func TestConvertCoverage(t *testing.T) { // repository name of this project. Format: // name.go:line.column,line.column numberOfStatements count cov := `mode: set -github.com/jandelgado/gcov2lcov/main.go:6.14,8.3 2 1 -github.com/jandelgado/gcov2lcov/main.go:7.14,9.3 2 0 -github.com/jandelgado/gcov2lcov/main.go:10.1,11.10 2 2` +github.com/jandelgado/gcov2lcov/cmd/main.go:6.14,8.3 2 1 +github.com/jandelgado/gcov2lcov/cmd/main.go:7.14,9.3 2 0 +github.com/jandelgado/gcov2lcov/cmd/main.go:10.1,11.10 2 2` in := strings.NewReader(cov) out := bytes.NewBufferString("") - err := convertCoverage(in, out, getCoverallsSourceFileName) + err := ConvertCoverage(in, out, RelativePathResolver) expected := `TN: -SF:main.go +SF:cmd/main.go DA:6,1 DA:7,1 DA:8,1 @@ -106,9 +103,9 @@ func TestPathResolverFunc(t *testing.T) { pwd, err := os.Getwd() assert.NoError(t, err) - name := getCoverallsSourceFileName(pwd + "/main.go") - assert.Equal(t, "main.go", name) + name := RelativePathResolver(pwd + "/cmd/main.go") + assert.Equal(t, "cmd/main.go", name) - name = getSourceFileName(pwd + "/main.go") - assert.Equal(t, pwd+"/main.go", name) + name = AbsolutePathResolver(pwd + "/cmd/main.go") + assert.Equal(t, pwd+"/cmd/main.go", name) } From 6544f4249b597b56046690b2d89167cc13205739 Mon Sep 17 00:00:00 2001 From: Jin Date: Thu, 29 Apr 2021 18:24:05 +0800 Subject: [PATCH 2/4] remove .idea files --- .idea/.gitignore | 8 -------- .idea/gcov2lcov.iml | 9 --------- .idea/modules.xml | 8 -------- .idea/vcs.xml | 6 ------ 4 files changed, 31 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/gcov2lcov.iml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 73f69e0..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml -# Editor-based HTTP Client requests -/httpRequests/ diff --git a/.idea/gcov2lcov.iml b/.idea/gcov2lcov.iml deleted file mode 100644 index 5e764c4..0000000 --- a/.idea/gcov2lcov.iml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index e512733..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file From 91ee25c07918abd23eb4ec0222d63f601b67a4b6 Mon Sep 17 00:00:00 2001 From: Jin Date: Thu, 29 Apr 2021 18:24:42 +0800 Subject: [PATCH 3/4] remove empty test file --- cmd/main_test.go | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 cmd/main_test.go diff --git a/cmd/main_test.go b/cmd/main_test.go deleted file mode 100644 index 5675657..0000000 --- a/cmd/main_test.go +++ /dev/null @@ -1,4 +0,0 @@ -// gcov2lcov - convert golang coverage files to the lcov format. -// (c) 2019 Jan Delgado -package main - From 2c41a9e28e2d7b99614d3a215a63f9260f4a9c4c Mon Sep 17 00:00:00 2001 From: Jin Date: Thu, 29 Apr 2021 20:13:59 +0800 Subject: [PATCH 4/4] refactors --- cmd/main.go | 2 +- gcov2kov.go => gcov2lcov.go | 25 +++++++++++++++---------- gcov2lcov_test.go | 10 ++++------ 3 files changed, 20 insertions(+), 17 deletions(-) rename gcov2kov.go => gcov2lcov.go (92%) diff --git a/cmd/main.go b/cmd/main.go index 0eb7308..d6f7acf 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -51,7 +51,7 @@ func gcovmain() int { defer outfile.Close() } - var pathResolverFunc func(string) string + var pathResolverFunc gcov2lcov.PathResolver if *useAbsoluteSourcePath { pathResolverFunc = gcov2lcov.AbsolutePathResolver } else { diff --git a/gcov2kov.go b/gcov2lcov.go similarity index 92% rename from gcov2kov.go rename to gcov2lcov.go index 388c1ef..5a5f7ee 100644 --- a/gcov2kov.go +++ b/gcov2lcov.go @@ -40,7 +40,9 @@ type cacheEntry struct { var pkgCache = map[string]cacheEntry{} -func ConvertCoverage(in io.Reader, out io.Writer, pathResolverFunc func(string) string) error { +type PathResolver func(name string) (string, error) + +func ConvertCoverage(in io.Reader, out io.Writer, pathResolverFunc PathResolver) error { blocks, err := parseCoverage(in, pathResolverFunc) if err != nil { return err @@ -48,16 +50,21 @@ func ConvertCoverage(in io.Reader, out io.Writer, pathResolverFunc func(string) return writeLcov(blocks, out) } -func AbsolutePathResolver(name string) string { - return name +func AbsolutePathResolver(name string) (string, error) { + return name, nil } -func RelativePathResolver(name string) string { +func RelativePathResolver(name string) (string, error) { + name, err := findFile(name) + if err != nil { + return "", err + } + if dir, ok := findRepositoryRoot(name); ok { filename := strings.TrimPrefix(name, dir+string(os.PathSeparator)) - return filename + return filename, nil } - return name + return name, nil } // given a module+file spec (e.g. github.com/jandelgado/gcov2lcov/main.go), @@ -210,7 +217,7 @@ func parseCoverageLine(line string) (string, *block, error) { return path[0], b, err } -func parseCoverage(coverage io.Reader, pathResolverFunc func(string) string) (map[string][]*block, error) { +func parseCoverage(coverage io.Reader, pathResolverFunc PathResolver) (map[string][]*block, error) { scanner := bufio.NewScanner(coverage) blocks := map[string][]*block{} for scanner.Scan() { @@ -219,14 +226,12 @@ func parseCoverage(coverage io.Reader, pathResolverFunc func(string) string) (ma continue } if f, b, err := parseCoverageLine(line); err == nil { - f, err := findFile(f) + f, err = pathResolverFunc(f) if err != nil { log.Printf("warn: %v", err) continue } - f = pathResolverFunc(f) - // Make sure the filePath is a key in the map. if _, found := blocks[f]; !found { blocks[f] = []*block{} diff --git a/gcov2lcov_test.go b/gcov2lcov_test.go index 1605e1d..d7610b3 100644 --- a/gcov2lcov_test.go +++ b/gcov2lcov_test.go @@ -3,7 +3,6 @@ package gcov2lcov import ( "bytes" "github.com/stretchr/testify/assert" - "os" "strings" "testing" ) @@ -100,12 +99,11 @@ end_of_record } func TestPathResolverFunc(t *testing.T) { - pwd, err := os.Getwd() + name, err := RelativePathResolver("github.com/jandelgado/gcov2lcov/cmd/main.go") assert.NoError(t, err) - - name := RelativePathResolver(pwd + "/cmd/main.go") assert.Equal(t, "cmd/main.go", name) - name = AbsolutePathResolver(pwd + "/cmd/main.go") - assert.Equal(t, pwd+"/cmd/main.go", name) + name, err = AbsolutePathResolver("github.com/jandelgado/gcov2lcov/cmd/main.go") + assert.NoError(t, err) + assert.Equal(t, "github.com/jandelgado/gcov2lcov/cmd/main.go", name) }