From b5d5ffeeb2e19441769dba3e05d746de19536cba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vlado=20Paji=C4=87?= Date: Wed, 20 Nov 2024 20:17:21 +0100 Subject: [PATCH] add coverage stats serialization --- pkg/testcoverage/coverage/types.go | 73 +++++++++++++++++++++++-- pkg/testcoverage/coverage/types_test.go | 31 +++++++++++ 2 files changed, 98 insertions(+), 6 deletions(-) diff --git a/pkg/testcoverage/coverage/types.go b/pkg/testcoverage/coverage/types.go index a851a41c..a12f1ea4 100644 --- a/pkg/testcoverage/coverage/types.go +++ b/pkg/testcoverage/coverage/types.go @@ -1,8 +1,11 @@ package coverage import ( + "bytes" + "errors" "fmt" "regexp" + "strconv" "strings" ) @@ -83,13 +86,71 @@ func compileExcludePathRules(excludePaths []string) []*regexp.Regexp { return compiled } -func CalcTotalStats(coverageStats []Stats) Stats { - totalStats := Stats{} +func CalcTotalStats(stats []Stats) Stats { + total := Stats{} - for _, stats := range coverageStats { - totalStats.Total += stats.Total - totalStats.Covered += stats.Covered + for _, s := range stats { + total.Total += s.Total + total.Covered += s.Covered } - return totalStats + return total +} + +func SerializeStats(stats []Stats) []byte { + b := bytes.Buffer{} + sep, nl := []byte(";"), []byte("\n") + + //nolint:errcheck // relax + for _, s := range stats { + b.WriteString(s.Name) + b.Write(sep) + b.WriteString(strconv.FormatInt(s.Total, 10)) + b.Write(sep) + b.WriteString(strconv.FormatInt(s.Covered, 10)) + b.Write(nl) + } + + return b.Bytes() +} + +var ErrInvalidFormat = errors.New("invalid format") + +func DeserializeStats(b []byte) ([]Stats, error) { + deserializeLine := func(bl []byte) (Stats, error) { + fields := bytes.Split(bl, []byte(";")) + if len(fields) != 3 { //nolint:mnd // relax + return Stats{}, ErrInvalidFormat + } + + t, err := strconv.ParseInt(string(fields[1]), 10, 64) + if err != nil { + return Stats{}, ErrInvalidFormat + } + + c, err := strconv.ParseInt(string(fields[2]), 10, 64) + if err != nil { + return Stats{}, ErrInvalidFormat + } + + return Stats{Name: string(fields[0]), Total: t, Covered: c}, nil + } + + lines := bytes.Split(b, []byte("\n")) + result := make([]Stats, 0, len(lines)) + + for _, l := range lines { + if len(l) == 0 { + continue + } + + s, err := deserializeLine(l) + if err != nil { + return nil, err + } + + result = append(result, s) + } + + return result, nil } diff --git a/pkg/testcoverage/coverage/types_test.go b/pkg/testcoverage/coverage/types_test.go index 99b60776..e6168d78 100644 --- a/pkg/testcoverage/coverage/types_test.go +++ b/pkg/testcoverage/coverage/types_test.go @@ -37,3 +37,34 @@ func TestStatStr(t *testing.T) { assert.Equal(t, "22.2% (2/9)", Stats{Covered: 2, Total: 9}.Str()) assert.Equal(t, "100% (10/10)", Stats{Covered: 10, Total: 10}.Str()) } + +func TestStatsSerialization(t *testing.T) { + t.Parallel() + + stats := []Stats{ + {Name: "foo", Total: 11, Covered: 1}, + {Name: "bar", Total: 9, Covered: 2}, + } + + b := SerializeStats(stats) + assert.Equal(t, "foo;11;1\nbar;9;2\n", string(b)) + + ds, err := DeserializeStats(b) + assert.NoError(t, err) + assert.Equal(t, stats, ds) + + // ignore empty lines + ds, err = DeserializeStats([]byte("\n\n\n\n")) + assert.NoError(t, err) + assert.Empty(t, ds) + + // invalid formats + _, err = DeserializeStats([]byte("foo;11;")) + assert.Error(t, err) + + _, err = DeserializeStats([]byte("foo;;11")) + assert.Error(t, err) + + _, err = DeserializeStats([]byte("foo;")) + assert.Error(t, err) +}