cloudflare/pint

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v0.72.1

Branches

Tags

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

Clone

HTTPS

Download ZIP

internal/discovery/discovery_test.go

346lines · modecode

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