cloudflare/pint

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v0.57.3

Branches

Tags

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

Clone

HTTPS

Download ZIP

internal/discovery/discovery_test.go

339lines · modecode

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