-
-
Notifications
You must be signed in to change notification settings - Fork 55
Expand file tree
/
Copy pathcoverage_test.go
More file actions
123 lines (103 loc) · 3.17 KB
/
Copy pathcoverage_test.go
File metadata and controls
123 lines (103 loc) · 3.17 KB
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
package main
import (
"fmt"
"os"
"path/filepath"
"regexp"
"sort"
"strings"
"testing"
)
// The coverage/ directory tracks, topic by topic, which parts of the Microsoft
// Writing Style Guide this style implements. Each file mirrors one top-level
// section of the guide; each key is a subtopic (or an A-Z word list entry) set
// to true or false, optionally followed by a comment naming the rules that
// implement it.
//
// This test reports the resulting metric and enforces the invariants that keep
// it honest: values must be canonical booleans, and every rule named in a
// comment must still exist. A rule that gets renamed or merged away otherwise
// leaves the manifest silently claiming coverage it no longer has.
// wordListFile holds the A-Z word list, whose ~850 entries would otherwise
// dominate any single headline percentage, so it's reported separately.
const wordListFile = "a-z.yml"
var ruleRef = regexp.MustCompile(`([A-Za-z]+)\.yml`)
type tally struct{ covered, total int }
func (t tally) pct() float64 {
if t.total == 0 {
return 0
}
return 100 * float64(t.covered) / float64(t.total)
}
func parseManifest(t *testing.T, path string) tally {
t.Helper()
data, err := os.ReadFile(path)
if err != nil {
t.Fatalf("read %s: %v", path, err)
}
var got tally
for i, line := range strings.Split(string(data), "\n") {
lineNo := i + 1
// A comment names the implementing rules; check they still exist.
if idx := strings.Index(line, "#"); idx >= 0 {
for _, m := range ruleRef.FindAllStringSubmatch(line[idx:], -1) {
rule := filepath.Join("Microsoft", m[1]+".yml")
if _, err := os.Stat(rule); err != nil {
t.Errorf("%s:%d: names %s.yml, which doesn't exist", path, lineNo, m[1])
}
}
line = line[:idx]
}
line = strings.TrimSpace(line)
if line == "" {
continue
}
key, value, found := strings.Cut(line, ":")
if !found {
t.Errorf("%s:%d: not a key/value pair: %q", path, lineNo, line)
continue
}
switch strings.TrimSpace(value) {
case "true":
got.covered++
got.total++
case "false":
got.total++
default:
t.Errorf("%s:%d: %q must be exactly true or false, got %q",
path, lineNo, strings.TrimSpace(key), strings.TrimSpace(value))
}
}
return got
}
func TestCoverage(t *testing.T) {
paths, err := filepath.Glob(filepath.Join("coverage", "*.yml"))
if err != nil || len(paths) == 0 {
t.Fatalf("no coverage manifests found: %v", err)
}
sort.Strings(paths)
var guidelines, wordList tally
var report []string
width := 0
for _, p := range paths {
if n := len(filepath.Base(p)); n > width {
width = n
}
}
for _, p := range paths {
got := parseManifest(t, p)
report = append(report, fmt.Sprintf(" %-*s %3d/%-3d %5.1f%%",
width, filepath.Base(p), got.covered, got.total, got.pct()))
if filepath.Base(p) == wordListFile {
wordList = got
} else {
guidelines.covered += got.covered
guidelines.total += got.total
}
}
t.Log("style guide coverage\n" + strings.Join(report, "\n") +
fmt.Sprintf("\n\n guidelines: %d/%d (%.1f%%)"+
"\n A-Z word list: %d/%d (%.1f%%)",
guidelines.covered, guidelines.total, guidelines.pct(),
wordList.covered, wordList.total, wordList.pct()))
}