Skip to content

Commit

Permalink
Merge pull request #177 from shogo82148/improve-merging-profiles
Browse files Browse the repository at this point in the history
improve merging profiles
  • Loading branch information
shogo82148 authored Sep 8, 2020
2 parents 769aead + b063ca2 commit 7f581cf
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 52 deletions.
91 changes: 56 additions & 35 deletions gocover.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,52 +32,73 @@ func findFile(file string) (string, error) {
// mergeProfs merges profiles for same target packages.
// It assumes each profiles have same sorted FileName and Blocks.
func mergeProfs(pfss [][]*cover.Profile) []*cover.Profile {
// skip empty profiles ([no test files])
for i := 0; i < len(pfss); i++ {
if len(pfss[i]) > 0 {
pfss = pfss[i:]
break
}
}
if len(pfss) == 0 {
return nil
} else if len(pfss) == 1 {
return pfss[0]
}
head, rest := pfss[0], pfss[1:]
ret := make([]*cover.Profile, 0, len(head))
for i, profile := range head {
for _, ps := range rest {
// find profiles
if len(ps) == 0 {
continue
} else if len(ps) < i+1 {
continue
} else if ps[i].FileName != profile.FileName {
continue
for len(pfss) > 1 {
i := 0
for ; 2*i+1 < len(pfss); i++ {
pfss[i] = mergeTwoProfs(pfss[2*i], pfss[2*i+1])
}
if 2*i < len(pfss) {
pfss[i] = pfss[2*i]
i++
}
pfss = pfss[:i]
}
return pfss[0]
}

func mergeTwoProfs(left, right []*cover.Profile) []*cover.Profile {
ret := make([]*cover.Profile, 0, len(left)+len(right))
for len(left) > 0 && len(right) > 0 {
if left[0].FileName == right[0].FileName {
profile := &cover.Profile{
FileName: left[0].FileName,
Mode: left[0].Mode,
Blocks: mergeTwoProfBlock(left[0].Blocks, right[0].Blocks),
}
profile.Blocks = mergeProfBlocks(profile.Blocks, ps[i].Blocks)
ret = append(ret, profile)
left = left[1:]
right = right[1:]
} else if left[0].FileName < right[0].FileName {
ret = append(ret, left[0])
left = left[1:]
} else {
ret = append(ret, right[0])
right = right[1:]
}
ret = append(ret, profile)
}
ret = append(ret, left...)
ret = append(ret, right...)
return ret
}

func mergeProfBlocks(as, bs []cover.ProfileBlock) []cover.ProfileBlock {
if len(as) != len(bs) {
log.Fatal("Two block length should be same")
}
// cover.ProfileBlock generated by cover.ParseProfiles() is sorted by
// StartLine and StartCol, so we can use index.
ret := make([]cover.ProfileBlock, 0, len(as))
for i, a := range as {
b := bs[i]
if a.StartLine != b.StartLine || a.StartCol != b.StartCol {
log.Fatal("Blocks are not sorted")
func mergeTwoProfBlock(left, right []cover.ProfileBlock) []cover.ProfileBlock {
ret := make([]cover.ProfileBlock, 0, len(left)+len(right))
for len(left) > 0 && len(right) > 0 {
a, b := left[0], right[0]
if a.StartLine == b.StartLine && a.StartCol == b.StartCol && a.EndLine == b.EndLine && a.EndCol == b.EndCol {
ret = append(ret, cover.ProfileBlock{
StartLine: a.StartLine,
StartCol: a.StartCol,
EndLine: a.EndLine,
EndCol: a.EndCol,
NumStmt: a.NumStmt,
Count: a.Count + b.Count,
})
left = left[1:]
right = right[1:]
} else if a.StartLine < b.StartLine || (a.StartLine == b.StartLine && a.StartCol < b.StartCol) {
ret = append(ret, a)
left = left[1:]
} else {
ret = append(ret, b)
right = right[1:]
}
a.Count += b.Count
ret = append(ret, a)
}
ret = append(ret, left...)
ret = append(ret, right...)
return ret
}

Expand Down
19 changes: 2 additions & 17 deletions goveralls_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@ func fakeServer() *httptest.Server {

func fakeServerWithPayloadChannel(payload chan Job) *httptest.Server {
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// this is a standard baked response
fmt.Fprintln(w, `{"error":false,"message":"Fake message","URL":"http://fake.url"}`)

body, err := ioutil.ReadAll(r.Body)
// query params are used for the body payload
vals, err := url.ParseQuery(string(body))
Expand All @@ -44,23 +41,11 @@ func fakeServerWithPayloadChannel(payload chan Job) *httptest.Server {
payload <- job

w.WriteHeader(http.StatusOK)
// this is a standard baked response
fmt.Fprintln(w, `{"error":false,"message":"Fake message","URL":"http://fake.url"}`)
}))
}

func TestUsage(t *testing.T) {
tmp := prepareTest(t)
defer os.RemoveAll(tmp)
cmd := exec.Command("goveralls", "-h")
b, err := cmd.CombinedOutput()
if err == nil {
t.Fatal("Expected exit code 1 bot 0")
}
s := strings.Split(string(b), "\n")[0]
if !strings.HasPrefix(s, "Usage: goveralls ") {
t.Fatalf("Expected %v, but %v", "Usage: ", s)
}
}

func TestCustomJobId(t *testing.T) {
tmp := prepareTest(t)
defer os.RemoveAll(tmp)
Expand Down
26 changes: 26 additions & 0 deletions usage_ge1.15_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// +build go1.15

package main

import (
"os"
"os/exec"
"runtime"
"strings"
"testing"
)

func TestUsage(t *testing.T) {
tmp := prepareTest(t)
defer os.RemoveAll(tmp)
cmd := exec.Command("goveralls", "-h")
b, err := cmd.CombinedOutput()
runtime.Version()
if err != nil {
t.Fatal(err)
}
s := strings.Split(string(b), "\n")[0]
if !strings.HasPrefix(s, "Usage: goveralls ") {
t.Fatalf("Expected %v, but %v", "Usage: ", s)
}
}
26 changes: 26 additions & 0 deletions usage_lt1.15_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// +build !go1.15

package main

import (
"os"
"os/exec"
"runtime"
"strings"
"testing"
)

func TestUsage(t *testing.T) {
tmp := prepareTest(t)
defer os.RemoveAll(tmp)
cmd := exec.Command("goveralls", "-h")
b, err := cmd.CombinedOutput()
runtime.Version()
if err == nil {
t.Fatal("Expected exit code 1 bot 0")
}
s := strings.Split(string(b), "\n")[0]
if !strings.HasPrefix(s, "Usage: goveralls ") {
t.Fatalf("Expected %v, but %v", "Usage: ", s)
}
}

0 comments on commit 7f581cf

Please sign in to comment.