forked from coredns/coredns
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreadme_test.go
184 lines (162 loc) · 4.3 KB
/
readme_test.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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
package test
import (
"bufio"
"fmt"
"os"
"path/filepath"
"strconv"
"strings"
"testing"
"github.com/coredns/caddy"
"github.com/coredns/coredns/core/dnsserver"
)
// As we use the filesystem as-is, these files need to exist ON DISK for the readme test to work. This is especially
// useful for the *file* and *dnssec* plugins as their Corefiles are now tested as well. We create files in the
// current dir for all these, meaning the example READMEs MUST use relative path in their READMEs.
var contents = map[string]string{
"Kexample.org.+013+45330.key": examplePub,
"Kexample.org.+013+45330.private": examplePriv,
"example.org.signed": exampleOrg, // not signed, but does not matter for this test.
}
const (
examplePub = `example.org. IN DNSKEY 256 3 13 eNMYFZYb6e0oJOV47IPo5f/UHy7wY9aBebotvcKakIYLyyGscBmXJQhbKLt/LhrMNDE2Q96hQnI5PdTBeOLzhQ==
`
examplePriv = `Private-key-format: v1.3
Algorithm: 13 (ECDSAP256SHA256)
PrivateKey: f03VplaIEA+KHI9uizlemUSbUJH86hPBPjmcUninPoM=
`
)
// TestReadme parses all README.mds of the plugins and checks if every example Corefile
// actually works. Each corefile snippet is only used if the language is set to 'corefile':
//
// ~~~ corefile
//
// . {
// # check-this-please
// }
//
// ~~~
//
// While we're at it - we also check the README.md itself. It should at least have the sections:
// Name, Description, Syntax and Examples. See plugin.md for more details.
func TestReadme(t *testing.T) {
port := 30053
caddy.Quiet = true
dnsserver.Quiet = true
create(contents)
defer remove(contents)
middle := filepath.Join("..", "plugin")
dirs, err := os.ReadDir(middle)
if err != nil {
t.Fatalf("Could not read %s: %q", middle, err)
}
for _, d := range dirs {
if !d.IsDir() {
continue
}
readme := filepath.Join(middle, d.Name())
readme = filepath.Join(readme, "README.md")
if err := sectionsFromReadme(readme); err != nil {
t.Fatal(err)
}
inputs, err := corefileFromReadme(readme)
if err != nil {
continue
}
// Test each snippet.
for _, in := range inputs {
dnsserver.Port = strconv.Itoa(port)
server, err := caddy.Start(in)
if err != nil {
t.Errorf("Failed to start server with %s, for input %q:\n%s", readme, err, in.Body())
}
server.Stop()
port++
}
}
}
// corefileFromReadme parses a readme and returns all fragments that
// have ~~~ corefile (or ``` corefile).
func corefileFromReadme(readme string) ([]*Input, error) {
f, err := os.Open(readme)
if err != nil {
return nil, err
}
defer f.Close()
s := bufio.NewScanner(f)
input := []*Input{}
corefile := false
temp := ""
for s.Scan() {
line := s.Text()
if line == "~~~ corefile" || line == "``` corefile" {
corefile = true
continue
}
if corefile && (line == "~~~" || line == "```") {
// last line
input = append(input, NewInput(temp))
temp = ""
corefile = false
continue
}
if corefile {
temp += line + "\n" // read newline stripped by s.Text()
}
}
if err := s.Err(); err != nil {
return nil, err
}
return input, nil
}
// sectionsFromReadme returns an error if the readme doesn't contains all
// mandatory sections. The check is basic, as we match each line, this mostly
// works, because markdown is such a simple format.
// We want: Name, Description, Syntax, Examples - in this order.
func sectionsFromReadme(readme string) error {
f, err := os.Open(readme)
if err != nil {
return nil // don't error when we can read the file
}
defer f.Close()
section := 0
s := bufio.NewScanner(f)
for s.Scan() {
line := s.Text()
if strings.HasPrefix(line, "## Also See") {
return fmt.Errorf("Please use %q instead of %q", "See Also", "Also See")
}
switch section {
case 0:
if strings.HasPrefix(line, "## Name") {
section++
}
case 1:
if strings.HasPrefix(line, "## Description") {
section++
}
case 2:
if strings.HasPrefix(line, "## Syntax") {
section++
}
case 3:
if strings.HasPrefix(line, "## Examples") {
section++
}
}
}
if section != 4 {
return fmt.Errorf("Sections incomplete or ordered wrong: %q, want (at least): Name, Descripion, Syntax and Examples", readme)
}
return nil
}
func create(c map[string]string) {
for name, content := range c {
os.WriteFile(name, []byte(content), 0644)
}
}
func remove(c map[string]string) {
for name := range c {
os.Remove(name)
}
}