Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merge coverprofiles instead of overwriting them #31

Merged
merged 4 commits into from
Sep 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
module github.com/Songmu/gotesplit

go 1.21
go 1.23

require (
github.com/jstemmer/go-junit-report/v2 v2.0.0
golang.org/x/sync v0.3.0
github.com/jstemmer/go-junit-report/v2 v2.1.0
golang.org/x/sync v0.8.0
)
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/jstemmer/go-junit-report/v2 v2.0.0 h1:bMZNO9B16VFn07tKyi4YJFIbZtVmJaa5Xakv9dcwK58=
github.com/jstemmer/go-junit-report/v2 v2.0.0/go.mod h1:mgHVr7VUo5Tn8OLVr1cKnLuEy0M92wdRntM99h7RkgQ=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
github.com/jstemmer/go-junit-report/v2 v2.1.0 h1:X3+hPYlSczH9IMIpSC9CQSZA0L+BipYafciZUWHEmsc=
github.com/jstemmer/go-junit-report/v2 v2.1.0/go.mod h1:mgHVr7VUo5Tn8OLVr1cKnLuEy0M92wdRntM99h7RkgQ=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
3 changes: 2 additions & 1 deletion gotesplit.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Options:
total := fs.Uint("total", 1, "total number of test splits (CIRCLE_NODE_TOTAL is used if set)")
index := fs.Uint("index", 0, "zero-based index number of test splits (CIRCLE_NODE_INDEX is used if set)")
junitDir := fs.String("junit-dir", "", "directory to store test result in JUnit format")
coverprofileDir := fs.String("coverprofile-dir", ".cover", "temporary directory for collecting coverprofile")
fs.VisitAll(func(f *flag.Flag) {
if f.Name == "index" || f.Name == "total" {
if s := os.Getenv("CIRCLE_NODE_" + strings.ToUpper(f.Name)); s != "" {
Expand All @@ -57,7 +58,7 @@ Options:
return rnr.run(ctx, argv[1:], outStream, errStream)
}
}
return run(ctx, *total, *index, *junitDir, argv, outStream, errStream)
return run(ctx, *total, *index, *junitDir, *coverprofileDir, argv, outStream, errStream)
}

func getTestListsFromPkgs(pkgs []string, tags string, withRace bool) ([]testList, error) {
Expand Down
75 changes: 73 additions & 2 deletions run.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"

"github.com/jstemmer/go-junit-report/v2/gtr"
Expand All @@ -20,7 +21,7 @@ import (
"golang.org/x/sync/errgroup"
)

func run(ctx context.Context, total, idx uint, junitDir string, argv []string, outStream io.Writer, errStream io.Writer) error {
func run(_ context.Context, total, idx uint, junitDir string, coverprofilesDir string, argv []string, outStream io.Writer, errStream io.Writer) error {
if idx >= total {
return fmt.Errorf("`index` should be the range from 0 to `total`-1, but: %d (total:%d)", idx, total)
}
Expand Down Expand Up @@ -111,6 +112,28 @@ func run(ctx context.Context, total, idx uint, junitDir string, argv []string, o
}
}

// Check if coverprofile flag is set. If so remove it from args and replace it
// later with separate coverprofile files for each `go test` run.
coverprofileFile := ""
for i := range testOpts {
if strings.HasPrefix(testOpts[i], "-coverprofile=") {
coverprofileFile = strings.TrimPrefix(testOpts[i], "-coverprofile=")

if i == len(testOpts)-1 {
testOpts = testOpts[:i]
} else {
testOpts = append(testOpts[:i], testOpts[i+1:]...)
}
break
}
}
if coverprofileFile != "" {
// Make temporary directory to store single coverprofile files in.
if err := os.MkdirAll(coverprofilesDir, 0755); err != nil {
return err
}
}

var testArgsList [][]string

if len(allPkgs) > 0 {
Expand All @@ -126,6 +149,11 @@ func run(ctx context.Context, total, idx uint, junitDir string, argv []string, o
}

for i, args := range testArgsList {
if coverprofileFile != "" {
// Write coverprofiles to temp folder.
args = append(args, fmt.Sprintf("-coverprofile=%s/coverprofile_%d", coverprofilesDir, i))
}

report := goTest(args, outStream, errStream, junitDir)
if err2 := report.err; err2 != nil {
err = err2
Expand All @@ -147,7 +175,50 @@ func run(ctx context.Context, total, idx uint, junitDir string, argv []string, o
}
}
}
return err
if err != nil {
return err
}

if coverprofileFile != "" {
// Merge single coverprofiles to one file.
err = mergeCoverprofiles(coverprofilesDir, coverprofileFile)
if err != nil {
return err
}

// Remove temp directory.
err = os.RemoveAll(coverprofilesDir)
if err != nil {
return err
}
}

return nil
}

func mergeCoverprofiles(dir string, coverprofileOut string) error {
files, err := os.ReadDir(dir)
if err != nil {
return err
}

modeRegex := regexp.MustCompile(`^mode: [a-zA-Z]+\n`)
mergedContent := []byte{}
for i, file := range files {
content, err := os.ReadFile(dir + "/" + file.Name())
if err != nil {
return fmt.Errorf("failed to read file %s: %w", file.Name(), err)
}

if i != 0 {
// Cover mode is set in first line, remove it from all the following
// files.
content = modeRegex.ReplaceAll(content, []byte{})
}
mergedContent = append(mergedContent, content...)
}

return os.WriteFile(coverprofileOut, mergedContent, 0755)
}

type junitReport struct {
Expand Down
Loading