cloudflare/pint

Public

mirrored from https://github.com/cloudflare/pintAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v0.49.2

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

internal/discovery/discovery_test.go

338lines · modecode

1package discovery
2
3import (
4 "bytes"
5 "encoding/json"
6 "fmt"
7 "io"
8 "strings"
9 "testing"
10
11 "github.com/stretchr/testify/require"
12
13 "github.com/cloudflare/pint/internal/parser"
14)
15
16type failingReader struct {
17 err error
18}
19
20func (r failingReader) Read(_ []byte) (int, error) {
21 return 0, r.err
22}
23
24func TestReadRules(t *testing.T) {
25 mustParse := func(offset int, s string) parser.Rule {
26 p := parser.NewParser()
27 r, err := p.Parse([]byte(strings.Repeat("\n", offset) + s))
28 if err != nil {
29 panic(fmt.Sprintf("failed to parse rule:\n---\n%s\n---\nerror: %s", s, err))
30 }
31 if len(r) != 1 {
32 panic(fmt.Sprintf("wrong number of rules returned: %d\n---\n%s\n---", len(r), s))
33 }
34 return r[0]
35 }
36
37 type testCaseT struct {
38 title string
39 reportedPath string
40 sourcePath string
41 sourceFunc func(t *testing.T) io.Reader
42 isStrict bool
43 entries []Entry
44 err string
45 }
46
47 testCases := []testCaseT{
48 {
49 title: "nil input",
50 reportedPath: "rules.yml",
51 sourcePath: "rules.yml",
52 sourceFunc: func(t *testing.T) io.Reader {
53 return bytes.NewBuffer(nil)
54 },
55 isStrict: false,
56 },
57 {
58 title: "nil input",
59 reportedPath: "rules.yml",
60 sourcePath: "rules.yml",
61 sourceFunc: func(t *testing.T) io.Reader {
62 return bytes.NewBuffer(nil)
63 },
64 isStrict: true,
65 },
66 {
67 title: "empty input",
68 reportedPath: "rules.yml",
69 sourcePath: "rules.yml",
70 sourceFunc: func(t *testing.T) io.Reader {
71 return bytes.NewBuffer([]byte(" "))
72 },
73 isStrict: false,
74 },
75 {
76 title: "empty input",
77 reportedPath: "rules.yml",
78 sourcePath: "rules.yml",
79 sourceFunc: func(t *testing.T) io.Reader {
80 return bytes.NewBuffer([]byte(" "))
81 },
82 isStrict: true,
83 },
84 {
85 title: "reader error",
86 reportedPath: "rules.yml",
87 sourcePath: "rules.yml",
88 sourceFunc: func(t *testing.T) io.Reader {
89 return failingReader{
90 err: io.ErrClosedPipe,
91 }
92 },
93 isStrict: false,
94 err: io.ErrClosedPipe.Error(),
95 },
96 {
97 title: "reader error",
98 reportedPath: "rules.yml",
99 sourcePath: "rules.yml",
100 sourceFunc: func(t *testing.T) io.Reader {
101 return failingReader{
102 err: io.ErrClosedPipe,
103 }
104 },
105 isStrict: true,
106 err: io.ErrClosedPipe.Error(),
107 },
108 {
109 title: "no rules, just a comment",
110 reportedPath: "rules.yml",
111 sourcePath: "rules.yml",
112 sourceFunc: func(t *testing.T) io.Reader {
113 return bytes.NewBuffer([]byte("\n\n # pint file/disable \n\n"))
114 },
115 isStrict: false,
116 },
117 {
118 title: "file/disable comment",
119 reportedPath: "rules.yml",
120 sourcePath: "rules.yml",
121 sourceFunc: func(t *testing.T) io.Reader {
122 return bytes.NewBuffer([]byte(`
123# pint file/disable promql/series
124
125- record: foo
126 expr: bar
127`))
128 },
129 isStrict: false,
130 entries: []Entry{
131 {
132 State: Unknown,
133 ReportedPath: "rules.yml",
134 SourcePath: "rules.yml",
135 ModifiedLines: []int{4, 5},
136 Rule: mustParse(3, "- record: foo\n expr: bar\n"),
137 DisabledChecks: []string{"promql/series"},
138 },
139 },
140 },
141 {
142 title: "file/disable comment",
143 reportedPath: "rules.yml",
144 sourcePath: "rules.yml",
145 sourceFunc: func(t *testing.T) io.Reader {
146 return bytes.NewBuffer([]byte(`
147# pint file/disable promql/series
148
149groups:
150- name: foo
151 rules:
152 - record: foo
153 expr: bar
154`))
155 },
156 isStrict: true,
157 entries: []Entry{
158 {
159 State: Unknown,
160 ReportedPath: "rules.yml",
161 SourcePath: "rules.yml",
162 ModifiedLines: []int{7, 8},
163 Rule: mustParse(6, "- record: foo\n expr: bar\n"),
164 DisabledChecks: []string{"promql/series"},
165 },
166 },
167 },
168 {
169 title: "single expired snooze comment",
170 reportedPath: "rules.yml",
171 sourcePath: "rules.yml",
172 sourceFunc: func(t *testing.T) io.Reader {
173 return bytes.NewBuffer([]byte(`
174# pint file/snooze 2000-01-01T00:00:00Z promql/series
175
176- record: foo
177 expr: bar
178`))
179 },
180 isStrict: false,
181 entries: []Entry{
182 {
183 State: Unknown,
184 ReportedPath: "rules.yml",
185 SourcePath: "rules.yml",
186 ModifiedLines: []int{4, 5},
187 Rule: mustParse(3, "- record: foo\n expr: bar\n"),
188 },
189 },
190 },
191 {
192 title: "single expired snooze comment",
193 reportedPath: "rules.yml",
194 sourcePath: "rules.yml",
195 sourceFunc: func(t *testing.T) io.Reader {
196 return bytes.NewBuffer([]byte(`
197# pint file/snooze 2000-01-01T00:00:00Z promql/series
198
199groups:
200- name: foo
201 rules:
202 - record: foo
203 expr: bar
204`))
205 },
206 isStrict: true,
207 entries: []Entry{
208 {
209 State: Unknown,
210 ReportedPath: "rules.yml",
211 SourcePath: "rules.yml",
212 ModifiedLines: []int{7, 8},
213 Rule: mustParse(6, "- record: foo\n expr: bar\n"),
214 },
215 },
216 },
217 {
218 title: "single valid snooze comment",
219 reportedPath: "rules.yml",
220 sourcePath: "rules.yml",
221 sourceFunc: func(t *testing.T) io.Reader {
222 return bytes.NewBuffer([]byte(`
223# pint file/snooze 2099-01-01T00:00:00Z promql/series
224
225- record: foo
226 expr: bar
227`))
228 },
229 isStrict: false,
230 entries: []Entry{
231 {
232 State: Unknown,
233 ReportedPath: "rules.yml",
234 SourcePath: "rules.yml",
235 ModifiedLines: []int{4, 5},
236 Rule: mustParse(3, "- record: foo\n expr: bar\n"),
237 DisabledChecks: []string{"promql/series"},
238 },
239 },
240 },
241 {
242 title: "single valid snooze comment",
243 reportedPath: "rules.yml",
244 sourcePath: "rules.yml",
245 sourceFunc: func(t *testing.T) io.Reader {
246 return bytes.NewBuffer([]byte(`
247# pint file/snooze 2099-01-01T00:00:00Z promql/series
248
249groups:
250- name: foo
251 rules:
252 - record: foo
253 expr: bar
254`))
255 },
256 isStrict: true,
257 entries: []Entry{
258 {
259 State: Unknown,
260 ReportedPath: "rules.yml",
261 SourcePath: "rules.yml",
262 ModifiedLines: []int{7, 8},
263 Rule: mustParse(6, "- record: foo\n expr: bar\n"),
264 DisabledChecks: []string{"promql/series"},
265 },
266 },
267 },
268 {
269 title: "ignore/file",
270 reportedPath: "rules.yml",
271 sourcePath: "rules.yml",
272 sourceFunc: func(t *testing.T) io.Reader {
273 return bytes.NewBuffer([]byte(`
274# pint ignore/file
275
276- record: foo
277 expr: bar
278`))
279 },
280 isStrict: false,
281 entries: []Entry{
282 {
283 State: Unknown,
284 ReportedPath: "rules.yml",
285 SourcePath: "rules.yml",
286 ModifiedLines: []int{1, 2, 3, 4, 5},
287 PathError: ErrFileIsIgnored,
288 },
289 },
290 },
291 {
292 title: "ignore/file",
293 reportedPath: "rules.yml",
294 sourcePath: "rules.yml",
295 sourceFunc: func(t *testing.T) io.Reader {
296 return bytes.NewBuffer([]byte(`
297# pint ignore/file
298
299groups:
300- name: foo
301 rules:
302 - record: foo
303 expr: bar
304`))
305 },
306 isStrict: true,
307 entries: []Entry{
308 {
309 State: Unknown,
310 ReportedPath: "rules.yml",
311 SourcePath: "rules.yml",
312 ModifiedLines: []int{1, 2, 3, 4, 5, 6, 7, 8},
313 PathError: ErrFileIsIgnored,
314 },
315 },
316 },
317 }
318
319 for _, tc := range testCases {
320 t.Run(
321 fmt.Sprintf("rPath=%s sPath=%s strict=%v title=%s", tc.reportedPath, tc.sourcePath, tc.isStrict, tc.title),
322 func(t *testing.T) {
323 r := tc.sourceFunc(t)
324 entries, err := readRules(tc.reportedPath, tc.sourcePath, r, tc.isStrict)
325 if tc.err != "" {
326 require.EqualError(t, err, tc.err)
327 } else {
328 require.NoError(t, err)
329
330 expected, err := json.MarshalIndent(tc.entries, "", " ")
331 require.NoError(t, err, "json(expected)")
332 got, err := json.MarshalIndent(entries, "", " ")
333 require.NoError(t, err, "json(got)")
334 require.Equal(t, string(expected), string(got))
335 }
336 })
337 }
338}