cloudflare/pint

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
54b27fc0f57b73e6dcb368dee4a1bbdd9eb8bdaf

Branches

Tags

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

Clone

HTTPS

Download ZIP

internal/parser/parser_test.go

878lines · modecode

1package parser_test
2
3import (
4 "fmt"
5 "strconv"
6 "testing"
7
8 "github.com/cloudflare/pint/internal/parser"
9
10 "github.com/google/go-cmp/cmp"
11 promparser "github.com/prometheus/prometheus/promql/parser"
12)
13
14func TestParse(t *testing.T) {
15 type testCaseT struct {
16 content []byte
17 output []parser.Rule
18 shouldError bool
19 }
20
21 testCases := []testCaseT{
22 {
23 content: nil,
24 output: nil,
25 shouldError: false,
26 },
27 {
28 content: []byte{},
29 output: nil,
30 shouldError: false,
31 },
32 {
33 content: []byte("- record: |\n multiline\n"),
34 output: []parser.Rule{
35 {Error: parser.ParseError{Err: fmt.Errorf("missing expr key"), Line: 1}},
36 },
37 },
38 {
39 content: []byte("- expr: foo\n"),
40 output: []parser.Rule{
41 {Error: parser.ParseError{Err: fmt.Errorf("incomplete rule, no alert or record key"), Line: 1}},
42 },
43 },
44 {
45 content: []byte("- alert: foo\n"),
46 output: []parser.Rule{
47 {Error: parser.ParseError{Err: fmt.Errorf("missing expr key"), Line: 1}},
48 },
49 },
50 {
51 content: []byte("- alert: foo\n record: foo\n"),
52 output: []parser.Rule{
53 {Error: parser.ParseError{Err: fmt.Errorf("got both record and alert keys in a single rule"), Line: 1}},
54 },
55 },
56 {
57 content: []byte("- record: foo\n labels:\n foo: bar\n"),
58 output: []parser.Rule{
59 {Error: parser.ParseError{Err: fmt.Errorf("missing expr key"), Line: 1}},
60 },
61 },
62 {
63 content: []byte("- record: - foo\n"),
64 shouldError: true,
65 },
66 {
67 content: []byte("- record: foo expr: sum(\n"),
68 shouldError: true,
69 },
70 {
71 content: []byte("- record\n\texpr: foo\n"),
72 shouldError: true,
73 },
74 {
75 content: []byte(`
76- record: foo
77 expr: bar
78 expr: bar
79`),
80 output: []parser.Rule{
81 {Error: parser.ParseError{Err: fmt.Errorf("duplicated expr key"), Line: 4}},
82 },
83 },
84 {
85 content: []byte(`
86- record: foo
87 expr: bar
88 record: bar
89`),
90 output: []parser.Rule{
91 {Error: parser.ParseError{Err: fmt.Errorf("duplicated record key"), Line: 4}},
92 },
93 },
94 {
95 content: []byte(`
96- alert: foo
97 alert: bar
98 expr: bar
99`),
100 output: []parser.Rule{
101 {Error: parser.ParseError{Err: fmt.Errorf("duplicated alert key"), Line: 3}},
102 },
103 },
104 {
105 content: []byte(`
106- alert: foo
107 for: 5m
108 expr: bar
109 for: 1m
110`),
111 output: []parser.Rule{
112 {Error: parser.ParseError{Err: fmt.Errorf("duplicated for key"), Line: 5}},
113 },
114 },
115 {
116 content: []byte(`
117- alert: foo
118 labels: {}
119 expr: bar
120 labels: {}
121`),
122 output: []parser.Rule{
123 {Error: parser.ParseError{Err: fmt.Errorf("duplicated labels key"), Line: 5}},
124 },
125 },
126 {
127 content: []byte(`
128- record: foo
129 labels: {}
130 expr: bar
131 labels: {}
132`),
133 output: []parser.Rule{
134 {Error: parser.ParseError{Err: fmt.Errorf("duplicated labels key"), Line: 5}},
135 },
136 },
137 {
138 content: []byte(`
139- alert: foo
140 annotations: {}
141 expr: bar
142 annotations: {}
143`),
144 output: []parser.Rule{
145 {Error: parser.ParseError{Err: fmt.Errorf("duplicated annotations key"), Line: 5}},
146 },
147 },
148 {
149 content: []byte("- record: foo\n expr: foo\n extra: true\n"),
150 output: []parser.Rule{
151 {Error: parser.ParseError{Err: fmt.Errorf("invalid key(s) found: extra"), Line: 3}},
152 },
153 },
154 {
155 content: []byte("- record: foo\n expr: foo offset 10m\n"),
156 output: []parser.Rule{
157 {
158 RecordingRule: &parser.RecordingRule{
159 Record: parser.YamlKeyValue{
160 Key: &parser.YamlNode{
161 Position: parser.FilePosition{Lines: []int{1}},
162 Value: "record",
163 },
164 Value: &parser.YamlNode{
165 Position: parser.FilePosition{Lines: []int{1}},
166 Value: "foo",
167 },
168 },
169 Expr: parser.PromQLExpr{
170 Key: &parser.YamlNode{
171 Position: parser.FilePosition{Lines: []int{2}},
172 Value: "expr",
173 },
174 Value: &parser.YamlNode{
175 Position: parser.FilePosition{Lines: []int{2}},
176 Value: "foo offset 10m",
177 },
178 Query: &parser.PromQLNode{
179 Expr: "foo offset 10m",
180 },
181 },
182 },
183 },
184 },
185 },
186 {
187 content: []byte("- record: foo\n expr: foo offset -10m\n"),
188 output: []parser.Rule{
189 {
190 RecordingRule: &parser.RecordingRule{
191 Record: parser.YamlKeyValue{
192 Key: &parser.YamlNode{
193 Position: parser.FilePosition{Lines: []int{1}},
194 Value: "record",
195 },
196 Value: &parser.YamlNode{
197 Position: parser.FilePosition{Lines: []int{1}},
198 Value: "foo",
199 },
200 },
201 Expr: parser.PromQLExpr{
202 Key: &parser.YamlNode{
203 Position: parser.FilePosition{Lines: []int{2}},
204 Value: "expr",
205 },
206 Value: &parser.YamlNode{
207 Position: parser.FilePosition{Lines: []int{2}},
208 Value: "foo offset -10m",
209 },
210 Query: &parser.PromQLNode{
211 Expr: "foo offset -10m",
212 },
213 },
214 },
215 },
216 },
217 },
218 {
219 content: []byte(`
220# head comment
221- record: foo # record comment
222 expr: foo offset 10m # expr comment
223 # pre-labels comment
224 labels:
225 # pre-foo comment
226 foo: bar
227 # post-foo comment
228 bob: alice
229# foot comment
230`),
231 output: []parser.Rule{
232 {
233 RecordingRule: &parser.RecordingRule{
234 Record: parser.YamlKeyValue{
235 Key: &parser.YamlNode{
236 Position: parser.FilePosition{Lines: []int{3}},
237 Value: "record",
238 Comments: []string{"# head comment"},
239 },
240 Value: &parser.YamlNode{
241 Position: parser.FilePosition{Lines: []int{3}},
242 Value: "foo",
243 Comments: []string{"# record comment"},
244 },
245 },
246 Expr: parser.PromQLExpr{
247 Key: &parser.YamlNode{
248 Position: parser.FilePosition{Lines: []int{4}},
249 Value: "expr",
250 },
251 Value: &parser.YamlNode{
252 Position: parser.FilePosition{Lines: []int{4}},
253 Value: "foo offset 10m",
254 Comments: []string{"# expr comment"},
255 },
256 Query: &parser.PromQLNode{
257 Expr: "foo offset 10m",
258 },
259 },
260 Labels: &parser.YamlMap{
261 Key: &parser.YamlNode{
262 Position: parser.FilePosition{Lines: []int{6}},
263 Value: "labels",
264 Comments: []string{"# pre-labels comment"},
265 },
266 Items: []*parser.YamlKeyValue{
267 {
268 Key: &parser.YamlNode{
269 Position: parser.FilePosition{Lines: []int{8}},
270 Value: "foo",
271 Comments: []string{"# pre-foo comment"},
272 },
273 Value: &parser.YamlNode{
274 Position: parser.FilePosition{Lines: []int{8}},
275 Value: "bar",
276 },
277 },
278 {
279 Key: &parser.YamlNode{
280 Position: parser.FilePosition{Lines: []int{10}},
281 Value: "bob",
282 Comments: []string{"# post-foo comment"},
283 },
284 Value: &parser.YamlNode{
285 Position: parser.FilePosition{Lines: []int{10}},
286 Value: "alice",
287 },
288 },
289 },
290 },
291 },
292 },
293 },
294 },
295 {
296 content: []byte("- record: foo\n expr: foo[5m] offset 10m\n"),
297 output: []parser.Rule{
298 {
299 RecordingRule: &parser.RecordingRule{
300 Record: parser.YamlKeyValue{
301 Key: &parser.YamlNode{
302 Position: parser.FilePosition{Lines: []int{1}},
303 Value: "record",
304 },
305 Value: &parser.YamlNode{
306 Position: parser.FilePosition{Lines: []int{1}},
307 Value: "foo",
308 },
309 },
310 Expr: parser.PromQLExpr{
311 Key: &parser.YamlNode{
312 Position: parser.FilePosition{Lines: []int{2}},
313 Value: "expr",
314 },
315 Value: &parser.YamlNode{
316 Position: parser.FilePosition{Lines: []int{2}},
317 Value: "foo[5m] offset 10m",
318 },
319 Query: &parser.PromQLNode{
320 Expr: "foo[5m] offset 10m",
321 Children: []*parser.PromQLNode{
322 {Expr: "foo offset 10m"},
323 },
324 },
325 },
326 },
327 },
328 },
329 },
330 {
331 content: []byte(`
332- record: name
333 expr: sum(foo)
334 labels:
335 foo: bar
336 bob: alice
337`),
338 output: []parser.Rule{
339 {
340 RecordingRule: &parser.RecordingRule{
341 Record: parser.YamlKeyValue{
342 Key: &parser.YamlNode{
343 Position: parser.FilePosition{Lines: []int{2}},
344 Value: "record",
345 },
346 Value: &parser.YamlNode{
347 Position: parser.FilePosition{Lines: []int{2}},
348 Value: "name",
349 },
350 },
351 Expr: parser.PromQLExpr{
352 Key: &parser.YamlNode{
353 Position: parser.FilePosition{Lines: []int{3}},
354 Value: "expr",
355 },
356 Value: &parser.YamlNode{
357 Position: parser.FilePosition{Lines: []int{3}},
358 Value: "sum(foo)",
359 },
360 Query: &parser.PromQLNode{
361 Expr: "sum(foo)",
362 Children: []*parser.PromQLNode{
363 {Expr: "foo"},
364 },
365 },
366 },
367 Labels: &parser.YamlMap{
368 Key: &parser.YamlNode{
369 Position: parser.FilePosition{Lines: []int{4}},
370 Value: "labels",
371 },
372 Items: []*parser.YamlKeyValue{
373 {
374 Key: &parser.YamlNode{
375 Position: parser.FilePosition{Lines: []int{5}},
376 Value: "foo",
377 },
378 Value: &parser.YamlNode{
379 Position: parser.FilePosition{Lines: []int{5}},
380 Value: "bar",
381 },
382 },
383 {
384 Key: &parser.YamlNode{
385 Position: parser.FilePosition{Lines: []int{6}},
386 Value: "bob",
387 },
388 Value: &parser.YamlNode{
389 Position: parser.FilePosition{Lines: []int{6}},
390 Value: "alice",
391 },
392 },
393 },
394 },
395 },
396 },
397 },
398 shouldError: false,
399 },
400 {
401 content: []byte(`
402groups:
403- name: custom_rules
404 rules:
405 - record: name
406 expr: sum(foo)
407 labels:
408 foo: bar
409 bob: alice
410`),
411 output: []parser.Rule{
412 {
413 RecordingRule: &parser.RecordingRule{
414 Record: parser.YamlKeyValue{
415 Key: &parser.YamlNode{
416 Position: parser.FilePosition{Lines: []int{5}},
417 Value: "record",
418 },
419 Value: &parser.YamlNode{
420 Position: parser.FilePosition{Lines: []int{5}},
421 Value: "name",
422 },
423 },
424 Expr: parser.PromQLExpr{
425 Key: &parser.YamlNode{
426 Position: parser.FilePosition{Lines: []int{6}},
427 Value: "expr",
428 },
429 Value: &parser.YamlNode{
430 Position: parser.FilePosition{Lines: []int{6}},
431 Value: "sum(foo)",
432 },
433 Query: &parser.PromQLNode{
434 Expr: "sum(foo)",
435 Children: []*parser.PromQLNode{
436 {Expr: "foo"},
437 },
438 },
439 },
440 Labels: &parser.YamlMap{
441 Key: &parser.YamlNode{
442 Position: parser.FilePosition{Lines: []int{7}},
443 Value: "labels",
444 },
445 Items: []*parser.YamlKeyValue{
446 {
447 Key: &parser.YamlNode{
448 Position: parser.FilePosition{Lines: []int{8}},
449 Value: "foo",
450 },
451 Value: &parser.YamlNode{
452 Position: parser.FilePosition{Lines: []int{8}},
453 Value: "bar",
454 },
455 },
456 {
457 Key: &parser.YamlNode{
458 Position: parser.FilePosition{Lines: []int{9}},
459 Value: "bob",
460 },
461 Value: &parser.YamlNode{
462 Position: parser.FilePosition{Lines: []int{9}},
463 Value: "alice",
464 },
465 },
466 },
467 },
468 },
469 },
470 },
471 shouldError: false,
472 },
473 {
474 content: []byte(`- alert: Down
475 expr: |
476 up == 0
477 for: |+
478 11m
479 labels:
480 severity: critical
481 annotations:
482 uri: https://docs.example.com/down.html
483
484- record: >
485 foo
486 expr: |-
487 bar
488 /
489 baz > 1
490 labels: {}
491`),
492 output: []parser.Rule{
493 {
494 AlertingRule: &parser.AlertingRule{
495 Alert: parser.YamlKeyValue{
496 Key: &parser.YamlNode{
497 Position: parser.FilePosition{Lines: []int{1}},
498 Value: "alert",
499 },
500 Value: &parser.YamlNode{
501 Position: parser.FilePosition{Lines: []int{1}},
502 Value: "Down",
503 },
504 },
505 Expr: parser.PromQLExpr{
506 Key: &parser.YamlNode{
507 Position: parser.FilePosition{Lines: []int{2}},
508 Value: "expr",
509 },
510 Value: &parser.YamlNode{
511 Position: parser.FilePosition{Lines: []int{3}},
512 Value: "up == 0\n",
513 },
514 Query: &parser.PromQLNode{
515 Expr: "up == 0\n",
516 Children: []*parser.PromQLNode{
517 {Expr: "up"},
518 {Expr: "0"},
519 },
520 },
521 },
522 For: &parser.YamlKeyValue{
523 Key: &parser.YamlNode{
524 Position: parser.FilePosition{Lines: []int{4}},
525 Value: "for",
526 },
527 Value: &parser.YamlNode{
528 Position: parser.FilePosition{Lines: []int{5}},
529 Value: "11m\n",
530 },
531 },
532 Labels: &parser.YamlMap{
533 Key: &parser.YamlNode{
534 Position: parser.FilePosition{Lines: []int{6}},
535 Value: "labels",
536 },
537 Items: []*parser.YamlKeyValue{
538 {
539 Key: &parser.YamlNode{
540 Position: parser.FilePosition{Lines: []int{7}},
541 Value: "severity",
542 },
543 Value: &parser.YamlNode{
544 Position: parser.FilePosition{Lines: []int{7}},
545 Value: "critical",
546 },
547 },
548 },
549 },
550 Annotations: &parser.YamlMap{
551 Key: &parser.YamlNode{
552 Position: parser.FilePosition{Lines: []int{8}},
553 Value: "annotations",
554 },
555 Items: []*parser.YamlKeyValue{
556 {
557 Key: &parser.YamlNode{
558 Position: parser.FilePosition{Lines: []int{9}},
559 Value: "uri",
560 },
561 Value: &parser.YamlNode{
562 Position: parser.FilePosition{Lines: []int{9}},
563 Value: "https://docs.example.com/down.html",
564 },
565 },
566 },
567 },
568 },
569 },
570 {
571 RecordingRule: &parser.RecordingRule{
572 Record: parser.YamlKeyValue{
573 Key: &parser.YamlNode{
574 Position: parser.FilePosition{Lines: []int{11}},
575 Value: "record",
576 },
577 Value: &parser.YamlNode{
578 Position: parser.FilePosition{Lines: []int{12}},
579 Value: "foo\n",
580 },
581 },
582 Expr: parser.PromQLExpr{
583 Key: &parser.YamlNode{
584 Position: parser.FilePosition{Lines: []int{13}},
585 Value: "expr",
586 },
587 Value: &parser.YamlNode{
588 Position: parser.FilePosition{Lines: []int{14, 15, 16}},
589 Value: "bar\n/\nbaz > 1",
590 },
591 Query: &parser.PromQLNode{
592 Expr: "bar\n/\nbaz > 1",
593 Children: []*parser.PromQLNode{
594 {
595 Expr: "bar / baz", Children: []*parser.PromQLNode{
596 {Expr: "bar"},
597 {Expr: "baz"},
598 },
599 },
600 {Expr: "1"},
601 },
602 },
603 },
604 Labels: &parser.YamlMap{
605 Key: &parser.YamlNode{
606 Position: parser.FilePosition{Lines: []int{17}},
607 Value: "labels",
608 },
609 },
610 },
611 },
612 },
613 shouldError: false,
614 },
615 {
616 content: []byte(`- alert: Foo
617 expr:
618 (
619 xxx
620 -
621 yyy
622 ) * bar > 0
623 and on(instance, device) baz
624 for: 30m
625`),
626 output: []parser.Rule{
627 {
628 AlertingRule: &parser.AlertingRule{
629 Alert: parser.YamlKeyValue{
630 Key: &parser.YamlNode{
631 Position: parser.FilePosition{Lines: []int{1}},
632 Value: "alert",
633 },
634 Value: &parser.YamlNode{
635 Position: parser.FilePosition{Lines: []int{1}},
636 Value: "Foo",
637 },
638 },
639 Expr: parser.PromQLExpr{
640 Key: &parser.YamlNode{
641 Position: parser.FilePosition{Lines: []int{2}},
642 Value: "expr",
643 },
644 Value: &parser.YamlNode{
645 Position: parser.FilePosition{Lines: []int{3, 4, 5, 6, 7, 8}},
646 Value: "( xxx - yyy ) * bar > 0 and on(instance, device) baz",
647 },
648 Query: &parser.PromQLNode{
649 Expr: "( xxx - yyy ) * bar > 0 and on(instance, device) baz",
650 Children: []*parser.PromQLNode{
651 {
652 Expr: "(xxx - yyy) * bar > 0",
653 Children: []*parser.PromQLNode{
654 {
655 Expr: "(xxx - yyy) * bar",
656 Children: []*parser.PromQLNode{
657 {
658 Expr: "(xxx - yyy)",
659 Children: []*parser.PromQLNode{
660 {
661 Expr: "xxx - yyy",
662 Children: []*parser.PromQLNode{
663 {Expr: "xxx"},
664 {Expr: "yyy"},
665 },
666 },
667 },
668 },
669 {
670 Expr: "bar",
671 },
672 },
673 },
674 {
675 Expr: "0",
676 },
677 },
678 },
679 {Expr: "baz"},
680 },
681 },
682 },
683 For: &parser.YamlKeyValue{
684 Key: &parser.YamlNode{
685 Position: parser.FilePosition{Lines: []int{9}},
686 Value: "for",
687 },
688 Value: &parser.YamlNode{
689 Position: parser.FilePosition{Lines: []int{9}},
690 Value: "30m",
691 },
692 },
693 },
694 },
695 },
696 },
697 {
698 content: []byte(`---
699kind: ConfigMap
700apiVersion: v1
701metadata:
702 name: example-app-alerts
703 labels:
704 app: example-app
705data:
706 alerts: |
707 groups:
708 - name: example-app-alerts
709 rules:
710 - alert: Example_Is_Down
711 expr: kube_deployment_status_replicas_available{namespace="example-app"} < 1
712 for: 5m
713 labels:
714 priority: "2"
715 environment: production
716 annotations:
717 summary: "No replicas for Example have been running for 5 minutes"
718
719 - alert: Example_High_Restart_Rate
720 expr: sum(rate(kube_pod_container_status_restarts_total{namespace="example-app"}[5m])) > ( 3/60 )
721`),
722 output: nil,
723 },
724 /*
725 FIXME https://github.com/cloudflare/pint/issues/20
726 {
727 content: []byte(`groups:
728 - name: "haproxy.api_server.rules"
729 rules:
730 - alert: HaproxyServerHealthcheckFailure
731 expr: increase(haproxy_server_check_failures_total[15m]) > 100
732 for: 5m
733 labels:
734 severity: 24x7
735 annotations:
736 summary: "HAProxy server healthcheck failure (instance {{ $labels.instance }})"
737 description: "Some server healthcheck are failing on {{ $labels.server }}\n VALUE = {{ $value }}\n LABELS: {{ $labels }}"
738 `),
739 output: []parser.Rule{
740 {
741 AlertingRule: &parser.AlertingRule{
742 Alert: parser.YamlKeyValue{
743 Key: &parser.YamlNode{
744 Position: parser.FilePosition{Lines: []int{4}},
745 Value: "alert",
746 },
747 Value: &parser.YamlNode{
748 Position: parser.FilePosition{Lines: []int{4}},
749 Value: "HaproxyServerHealthcheckFailure",
750 },
751 },
752 Expr: parser.PromQLExpr{
753 Key: &parser.YamlNode{
754 Position: parser.FilePosition{Lines: []int{5}},
755 Value: "expr",
756 },
757 Value: &parser.YamlNode{
758 Position: parser.FilePosition{Lines: []int{5}},
759 Value: "increase(haproxy_server_check_failures_total[15m]) > 100",
760 },
761 Query: &parser.PromQLNode{
762 Expr: "increase(haproxy_server_check_failures_total[15m]) > 100",
763 Children: []*parser.PromQLNode{
764 {
765 Expr: "increase(haproxy_server_check_failures_total[15m])",
766 Children: []*parser.PromQLNode{
767 {
768 Expr: "haproxy_server_check_failures_total[15m]",
769 Children: []*parser.PromQLNode{
770 {
771 Expr: "haproxy_server_check_failures_total",
772 },
773 },
774 },
775 },
776 },
777 {Expr: "100"},
778 },
779 },
780 },
781 For: &parser.YamlKeyValue{
782 Key: &parser.YamlNode{
783 Position: parser.FilePosition{Lines: []int{6}},
784 Value: "for",
785 },
786 Value: &parser.YamlNode{Position: parser.FilePosition{Lines: []int{6}},
787 Value: "5m",
788 },
789 },
790 Labels: &parser.YamlMap{
791 Key: &parser.YamlNode{
792 Position: parser.FilePosition{Lines: []int{7}},
793 Value: "labels",
794 },
795 Items: []*parser.YamlKeyValue{
796 {
797 Key: &parser.YamlNode{
798 Position: parser.FilePosition{Lines: []int{8}},
799 Value: "severity",
800 },
801 Value: &parser.YamlNode{
802 Position: parser.FilePosition{Lines: []int{8}},
803 Value: "24x7",
804 },
805 },
806 },
807 },
808 Annotations: &parser.YamlMap{
809 Key: &parser.YamlNode{
810 Position: parser.FilePosition{Lines: []int{9}},
811 Value: "annotations",
812 },
813 Items: []*parser.YamlKeyValue{
814 {
815 Key: &parser.YamlNode{
816 Position: parser.FilePosition{Lines: []int{10}},
817 Value: "summary",
818 },
819 Value: &parser.YamlNode{
820 Position: parser.FilePosition{Lines: []int{10}},
821 Value: "HAProxy server healthcheck failure (instance {{ $labels.instance }})",
822 },
823 },
824 {
825 Key: &parser.YamlNode{
826 Position: parser.FilePosition{Lines: []int{11}},
827 Value: "description",
828 },
829 Value: &parser.YamlNode{
830 Position: parser.FilePosition{Lines: []int{11}},
831 Value: `Some server healthcheck are failing on {{ $labels.server }}\n VALUE = {{ $value }}\n LABELS: {{ $labels }}`,
832 },
833 },
834 },
835 },
836 },
837 },
838 },
839 },
840 */
841 }
842
843 alwaysEqual := cmp.Comparer(func(_, _ interface{}) bool { return true })
844 ignorePrometheusExpr := cmp.FilterValues(func(x, y interface{}) bool {
845 _, xe := x.(promparser.Expr)
846 _, ye := y.(promparser.Expr)
847 return xe || ye
848 }, alwaysEqual)
849
850 cmpErrorText := cmp.Comparer(func(x, y interface{}) bool {
851 xe := x.(error)
852 ye := y.(error)
853 return xe.Error() == ye.Error()
854 })
855 sameErrorText := cmp.FilterValues(func(x, y interface{}) bool {
856 _, xe := x.(error)
857 _, ye := y.(error)
858 return xe && ye
859 }, cmpErrorText)
860
861 for i, tc := range testCases {
862 t.Run(strconv.Itoa(i+1), func(t *testing.T) {
863 p := parser.NewParser()
864 output, err := p.Parse(tc.content)
865
866 hadError := err != nil
867 if hadError != tc.shouldError {
868 t.Errorf("Parse() returned err=%v, expected=%v", err, tc.shouldError)
869 return
870 }
871
872 if diff := cmp.Diff(tc.output, output, ignorePrometheusExpr, sameErrorText); diff != "" {
873 t.Errorf("Parse() returned wrong output (-want +got):\n%s", diff)
874 return
875 }
876 })
877 }
878}