add calculate and merge coverage files #7
5
go.mod
5
go.mod
@ -10,6 +10,7 @@ require (
|
|||||||
github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c
|
github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c
|
||||||
github.com/jmoiron/sqlx v1.3.1
|
github.com/jmoiron/sqlx v1.3.1
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
|
github.com/stretchr/testify v1.8.3
|
||||||
go.unistack.org/micro-client-http/v4 v4.0.2
|
go.unistack.org/micro-client-http/v4 v4.0.2
|
||||||
go.unistack.org/micro-codec-json/v4 v4.0.0
|
go.unistack.org/micro-codec-json/v4 v4.0.0
|
||||||
go.unistack.org/micro-codec-jsonpb/v4 v4.0.0
|
go.unistack.org/micro-codec-jsonpb/v4 v4.0.0
|
||||||
@ -25,6 +26,7 @@ require (
|
|||||||
go.unistack.org/protoc-gen-go-micro/v4 v4.0.7
|
go.unistack.org/protoc-gen-go-micro/v4 v4.0.7
|
||||||
golang.org/x/mod v0.12.0
|
golang.org/x/mod v0.12.0
|
||||||
golang.org/x/sync v0.3.0
|
golang.org/x/sync v0.3.0
|
||||||
|
golang.org/x/tools v0.11.0
|
||||||
google.golang.org/protobuf v1.31.0
|
google.golang.org/protobuf v1.31.0
|
||||||
modernc.org/sqlite v1.21.0
|
modernc.org/sqlite v1.21.0
|
||||||
)
|
)
|
||||||
@ -37,6 +39,7 @@ require (
|
|||||||
github.com/acomagu/bufpipe v1.0.4 // indirect
|
github.com/acomagu/bufpipe v1.0.4 // indirect
|
||||||
github.com/cenkalti/backoff/v3 v3.2.2 // indirect
|
github.com/cenkalti/backoff/v3 v3.2.2 // indirect
|
||||||
github.com/cloudflare/circl v1.3.3 // indirect
|
github.com/cloudflare/circl v1.3.3 // indirect
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
github.com/emirpasic/gods v1.18.1 // indirect
|
github.com/emirpasic/gods v1.18.1 // indirect
|
||||||
github.com/fatih/structtag v1.2.0 // indirect
|
github.com/fatih/structtag v1.2.0 // indirect
|
||||||
@ -76,6 +79,7 @@ require (
|
|||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||||
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
github.com/rs/zerolog v1.30.0 // indirect
|
github.com/rs/zerolog v1.30.0 // indirect
|
||||||
github.com/ryanuber/go-glob v1.0.0 // indirect
|
github.com/ryanuber/go-glob v1.0.0 // indirect
|
||||||
@ -92,7 +96,6 @@ require (
|
|||||||
golang.org/x/sys v0.11.0 // indirect
|
golang.org/x/sys v0.11.0 // indirect
|
||||||
golang.org/x/text v0.12.0 // indirect
|
golang.org/x/text v0.12.0 // indirect
|
||||||
golang.org/x/time v0.3.0 // indirect
|
golang.org/x/time v0.3.0 // indirect
|
||||||
golang.org/x/tools v0.11.0 // indirect
|
|
||||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
1
go.sum
1
go.sum
@ -987,6 +987,7 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
|
|||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
|
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
|
||||||
|
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||||
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||||
|
94
internal/analyzer/coverage/coverage.go
Normal file
94
internal/analyzer/coverage/coverage.go
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
package coverage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"git.unistack.org/unistack-org/pkgdash/internal/models"
|
||||||
|
"golang.org/x/tools/cover"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Analyze(ctx context.Context, dataCoverage io.Reader, pack models.Package) (float64, error) {
|
||||||
|
calculcate, err := calculateFiles(dataCoverage)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
mapCover := make(map[string]float64)
|
||||||
|
{
|
||||||
|
tree, err := GetTreeFromGit(ctx, pack.URL)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
list, err := tree.GoFileList("")
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, f := range list {
|
||||||
|
mapCover[f] = 0.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cur := len(mapCover)
|
||||||
|
|
||||||
|
for _, d := range calculcate.Files {
|
||||||
|
file := strings.TrimPrefix(d.Name, pack.Name+"/")
|
||||||
|
mapCover[file] = d.Coverage
|
||||||
|
}
|
||||||
|
|
||||||
|
// check)
|
||||||
|
if len(mapCover) != cur {
|
||||||
|
fmt.Printf("add new keys, was: %d, has: %d", cur, len(mapCover))
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO add calculate full
|
||||||
|
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type Data struct {
|
||||||
|
Files []*calculateFile
|
||||||
|
Set bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type calculateFile struct {
|
||||||
|
Name string
|
||||||
|
Coverage float64
|
||||||
|
}
|
||||||
|
|
||||||
|
func calculateFiles(coverSrc io.Reader) (d *Data, err error) {
|
||||||
|
profiles, err := cover.ParseProfilesFromReader(coverSrc)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
d = new(Data)
|
||||||
|
for _, profile := range profiles {
|
||||||
|
fn := profile.FileName
|
||||||
|
if profile.Mode == "set" {
|
||||||
|
d.Set = true
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Files = append(d.Files, &calculateFile{
|
||||||
|
Name: fn,
|
||||||
|
Coverage: percentCovered(profile),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return d, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func percentCovered(p *cover.Profile) float64 {
|
||||||
|
var total, covered int64
|
||||||
|
for _, b := range p.Blocks {
|
||||||
|
total += int64(b.NumStmt)
|
||||||
|
if b.Count > 0 {
|
||||||
|
covered += int64(b.NumStmt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if total == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return float64(covered) / float64(total) * 100
|
||||||
|
}
|
36
internal/analyzer/coverage/coverage_test.go
Normal file
36
internal/analyzer/coverage/coverage_test.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package coverage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"git.unistack.org/unistack-org/pkgdash/internal/models"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_Calculate(t *testing.T) {
|
||||||
|
file, err := os.Open("cover_test.out")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
defer func() {
|
||||||
|
assert.Nil(t, file.Close())
|
||||||
|
}()
|
||||||
|
|
||||||
|
dataFiles, err := calculateFiles(file)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.NotNil(t, dataFiles)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_Analyze(t *testing.T) {
|
||||||
|
file, err := os.Open("cover_test.out")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
defer func() {
|
||||||
|
assert.Nil(t, file.Close())
|
||||||
|
}()
|
||||||
|
|
||||||
|
analyze, err := Analyze(context.Background(), file, models.Package{
|
||||||
|
Name: "go.unistack.org/micro/v4",
|
||||||
|
URL: "https://git.unistack.org/unistack-org/micro.git",
|
||||||
|
})
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, analyze, 0.0)
|
||||||
|
}
|
70
internal/analyzer/coverage/git.go
Normal file
70
internal/analyzer/coverage/git.go
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
package coverage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/go-git/go-git/v5"
|
||||||
|
"github.com/go-git/go-git/v5/plumbing/filemode"
|
||||||
|
"github.com/go-git/go-git/v5/plumbing/object"
|
||||||
|
"github.com/go-git/go-git/v5/storage/memory"
|
||||||
|
"os"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
fileNil = errors.New("file pointer is nil")
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetTreeFromGit(ctx context.Context, url string) (*Tree, error) {
|
||||||
|
cloneOpts := &git.CloneOptions{
|
||||||
|
URL: url,
|
||||||
|
Progress: os.Stdout,
|
||||||
|
}
|
||||||
|
|
||||||
|
repo, err := git.CloneContext(ctx, memory.NewStorage(), nil, cloneOpts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ref, err := repo.Head()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get head: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
commit, err := repo.CommitObject(ref.Hash())
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get commit: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tree, err := commit.Tree()
|
||||||
|
|
||||||
|
return &Tree{tree}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type Tree struct {
|
||||||
|
*object.Tree
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t Tree) GoFileList(pattern string) ([]string, error) {
|
||||||
|
matcher, err := regexp.Compile(pattern)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var list []string
|
||||||
|
err = t.Files().ForEach(func(file *object.File) error {
|
||||||
|
if file == nil {
|
||||||
|
return fileNil
|
||||||
|
}
|
||||||
|
if file.Mode == filemode.Regular && strings.HasSuffix(file.Name, ".go") && !strings.HasSuffix(file.Name, "_test.go") && matcher.MatchString(file.Name) {
|
||||||
|
list = append(list, file.Name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return list, err
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user