-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.go
143 lines (119 loc) · 3.42 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package main
import (
"bufio"
"log"
"math"
"os"
"github.com/urfave/cli"
"golang.org/x/tools/cover"
)
type coverage struct {
Statements int
StatementsCovered int
PercentageCovered float64
}
func main() {
var coverFile, businessLogicFile string
var minCoverageThreshold float64
app := cli.NewApp()
app.Name = "go-agg-cov"
app.Usage = "Calculates a single coverage percentage from a go coverage file and a an optional list of go files representing the business logic"
app.Version = "0.0.2"
app.Flags = []cli.Flag{
cli.StringFlag{
Name: "coverFile",
Value: "",
Usage: "Coverage file to scan",
Destination: &coverFile,
},
cli.StringFlag{
Name: "businessLogicFile",
Value: "",
Usage: "Optional file containing list of business logic files",
Destination: &businessLogicFile,
},
cli.Float64Flag{
Name: "minCoverageThreshold",
Value: 0,
Usage: "Optional minimum coverage threshold percentage (breaks if under this value)",
Destination: &minCoverageThreshold,
},
}
app.Action = func(c *cli.Context) error {
log.Printf("Analyzing file %s\n", coverFile)
log.Printf("Business Logic file %s\n", businessLogicFile)
log.Printf("Minimum coverage threshold percentage %f %%\n", minCoverageThreshold)
if coverFile == "" {
log.Fatal("CoverFile is mandatory")
}
if minCoverageThreshold < 0 || minCoverageThreshold > 100 {
log.Fatal("Minimum coverage threshold must be in range [0-100]")
}
business, errBusiness := parseBusinessLogicFile(businessLogicFile)
if errBusiness != nil {
log.Fatal(errBusiness)
}
profiles, err := cover.ParseProfiles(coverFile)
if err != nil {
log.Fatal(err)
}
coverage := &coverage{}
coverage.calculateCoverage(profiles, business)
log.Printf("Nb Statements: %d Coverage percentage: %f %%", coverage.Statements, coverage.PercentageCovered)
if math.IsNaN(coverage.PercentageCovered) {
log.Fatal("Wrong configuration: coverage percentage Not a Number")
}
if minCoverageThreshold > 0 && coverage.PercentageCovered < minCoverageThreshold {
log.Fatal("Minimum coverage threshold not reached")
}
return nil
}
err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
func (c *coverage) calculateCoverage(profiles []*cover.Profile, businessFiles map[string]struct{}) {
if len(businessFiles) == 0 {
// Calculate coverage on all coverage file
for _, profile := range profiles {
for _, block := range profile.Blocks {
c.Statements += block.NumStmt
if block.Count > 0 {
c.StatementsCovered += block.NumStmt
}
}
}
} else {
// Calculate coverage on business files from coverage file
for _, profile := range profiles {
_, isBusinessFile := businessFiles[profile.FileName]
if isBusinessFile {
for _, block := range profile.Blocks {
c.Statements += block.NumStmt
if block.Count > 0 {
c.StatementsCovered += block.NumStmt
}
}
}
}
}
c.PercentageCovered = (float64(c.StatementsCovered) / float64(c.Statements)) * 100.0
}
func parseBusinessLogicFile(businessLogicFile string) (map[string]struct{}, error) {
files := make(map[string]struct{}, 0)
if businessLogicFile == "" {
return files, nil
}
pf, err := os.Open(businessLogicFile)
if err != nil {
return nil, err
}
defer pf.Close()
buf := bufio.NewReader(pf)
s := bufio.NewScanner(buf)
for s.Scan() {
files[s.Text()] = struct{}{}
}
return files, nil
}