Skip to content

Commit

Permalink
Filter changed cover profiles (#85)
Browse files Browse the repository at this point in the history
filter
  • Loading branch information
yangzuo0621 authored Mar 3, 2023
1 parent 6654fa6 commit c109cf0
Show file tree
Hide file tree
Showing 3 changed files with 3,070 additions and 2,952 deletions.
76 changes: 47 additions & 29 deletions pkg/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ func NewParser(
) *Parser {
return &Parser{
coverProfileFiles: coverProfileFiles,
coverProfiles: make([]*cover.Profile, 0),
packages: make(map[string]*Package),
packagesCache: make(packagesCache),
logger: logger.WithField("source", "Parser"),
Expand All @@ -35,63 +36,80 @@ type Parser struct {
packages map[string]*Package
packagesCache packagesCache
coverProfileFiles []string
coverProfiles []*cover.Profile

logger logrus.FieldLogger
}

// Parse parses cover profiles into statements, and modify their state based on git changes.
func (parser *Parser) Parse(changes []*gittool.Change) (Packages, error) {
if err := parser.filterCoverProfiles(changes); err != nil {
parser.logger.WithError(err).Error("filter cover profiles")
return nil, err
}
if err := parser.buildPackageCache(); err != nil {
parser.logger.WithError(err).Error("build package cache")
return nil, err
}

var result Packages

for _, coverProfile := range parser.coverProfileFiles {

profiles, err := cover.ParseProfiles(coverProfile)
if err != nil {
parser.logger.WithError(err).Error("parse cover profile")
for _, p := range parser.coverProfiles {
if err := parser.convertProfile(p, findChange(p, changes)); err != nil {
parser.logger.WithError(err).Error("covert cover profile")
return nil, err
}
for _, p := range profiles {
if err := parser.convertProfile(p, findChange(p, changes)); err != nil {
parser.logger.WithError(err).Error("covert cover profile")
return nil, err
}
}
}

for _, pkg := range parser.packages {
result.AddPackage(pkg)
}
for _, pkg := range parser.packages {
result.AddPackage(pkg)
}

return result, nil
}

func (parser *Parser) buildPackageCache() error {
// filterCoverProfiles filters cover profiles based on git changes.
// If changes is nil, all cover profiles will be kept.
// If changes is not nil, only cover profiles that are changed will be kept.
func (parser *Parser) filterCoverProfiles(changes []*gittool.Change) error {

for _, coverFile := range parser.coverProfileFiles {
profiles, err := cover.ParseProfiles(coverFile)
for _, coverProfile := range parser.coverProfileFiles {
profiles, err := cover.ParseProfiles(coverProfile)
if err != nil {
return err
}

for _, profile := range profiles {
dir, _ := filepath.Split(profile.FileName)
if dir != "" {
dir = strings.TrimSuffix(dir, "/")
if changes == nil {
parser.coverProfiles = append(parser.coverProfiles, profiles...)
continue
}

for _, p := range profiles {
if findChange(p, changes) != nil {
parser.coverProfiles = append(parser.coverProfiles, p)
}
_, ok := parser.packagesCache[dir]
if !ok {
pkg, err := build.Import(dir, ".", build.FindOnly)
if err != nil {
return err
}
parser.packagesCache[dir] = pkg
parser.packages[pkg.ImportPath] = &Package{Name: pkg.ImportPath}
}
}

return nil
}

// buildPackageCache builds a cache of packages for all cover profiles.
func (parser *Parser) buildPackageCache() error {

for _, profile := range parser.coverProfiles {
dir, _ := filepath.Split(profile.FileName)
if dir != "" {
dir = strings.TrimSuffix(dir, "/")
}
_, ok := parser.packagesCache[dir]
if !ok {
pkg, err := build.Import(dir, ".", build.FindOnly)
if err != nil {
return err
}
parser.packagesCache[dir] = pkg
parser.packages[pkg.ImportPath] = &Package{Name: pkg.ImportPath}
}
}

Expand Down
90 changes: 80 additions & 10 deletions pkg/parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,38 @@ import (

"github.com/Azure/gocover/pkg/gittool"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"golang.org/x/tools/cover"
)

var (
allPackages = []string{
"github.com/Azure/gocover/pkg/parser",
"github.com/Azure/gocover/pkg/report",
"github.com/Azure/gocover/pkg/gocover",
"github.com/Azure/gocover/pkg/gittool",
"github.com/Azure/gocover/pkg/dbclient",
"github.com/Azure/gocover/pkg/cmd",
"github.com/Azure/gocover/pkg/annotation",
"github.com/Azure/gocover",
}
)

func TestParser(t *testing.T) {
t.Run("buildPackageCache", func(t *testing.T) {
profiles, err := cover.ParseProfiles("testdata/cover.out")
assert.NoError(t, err)

parser := &Parser{
coverProfiles: profiles,
coverProfileFiles: []string{"testdata/cover.out"},
packages: make(map[string]*Package),
packagesCache: make(packagesCache),
logger: logrus.New(),
}

parser.buildPackageCache()
for _, pkg := range []string{
"github.com/Azure/gocover/pkg/parser",
"github.com/Azure/gocover/pkg/report",
"github.com/Azure/gocover/pkg/gocover",
"github.com/Azure/gocover/pkg/gittool",
"github.com/Azure/gocover/pkg/dbclient",
"github.com/Azure/gocover/pkg/cmd",
"github.com/Azure/gocover/pkg/annotation",
"github.com/Azure/gocover",
} {
for _, pkg := range allPackages {
if _, ok := parser.packagesCache[pkg]; !ok {
t.Errorf("package %s is not in packagesCache", pkg)
}
Expand All @@ -35,6 +45,66 @@ func TestParser(t *testing.T) {
}
}
})

t.Run("filterCoverProfiles with no changes", func(t *testing.T) {

t.Run("no changes", func(t *testing.T) {
parser := &Parser{
coverProfileFiles: []string{"testdata/cover.out"},
packages: make(map[string]*Package),
packagesCache: make(packagesCache),
logger: logrus.New(),
}

profiles, err := cover.ParseProfiles("testdata/cover.out")
assert.NoError(t, err)

err = parser.filterCoverProfiles(nil)
assert.NoError(t, err)

assert.Len(t, parser.coverProfiles, len(profiles))

var allFiles []string
for _, profile := range profiles {
allFiles = append(allFiles, profile.FileName)
}

for _, profile := range parser.coverProfiles {
assert.Contains(t, allFiles, profile.FileName)
}
})

t.Run("with changes", func(t *testing.T) {
parser := &Parser{
coverProfileFiles: []string{"testdata/cover.out"},
packages: make(map[string]*Package),
packagesCache: make(packagesCache),
logger: logrus.New(),
}

changes := []*gittool.Change{
{
FileName: "pkg/parser/parser.go",
},
{
FileName: "pkg/gocover/executor.go",
},
}

err := parser.filterCoverProfiles(changes)
assert.NoError(t, err)

expected := []string{
"github.com/Azure/gocover/pkg/parser/parser.go",
"github.com/Azure/gocover/pkg/gocover/executor.go",
}
assert.Len(t, parser.coverProfiles, len(expected))
for _, profile := range parser.coverProfiles {
assert.Contains(t, expected, profile.FileName)
}
})
})

}

func TestSetStatementsState(t *testing.T) {
Expand Down
Loading

0 comments on commit c109cf0

Please sign in to comment.