Skip to content

Commit

Permalink
Refactor tests
Browse files Browse the repository at this point in the history
  • Loading branch information
prymitive committed Mar 11, 2022
1 parent 29253a0 commit 1be963a
Show file tree
Hide file tree
Showing 29 changed files with 3,571 additions and 2,081 deletions.
162 changes: 102 additions & 60 deletions internal/checks/alerts_annotation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,115 +11,157 @@ func TestAnnotationCheck(t *testing.T) {
{
description: "ignores recording rules",
content: "- record: foo\n expr: sum(foo) without(\n",
checker: checks.NewAnnotationCheck("severity", checks.MustTemplatedRegexp("critical"), true, checks.Warning),
checker: func(uri string) checks.RuleChecker {
return checks.NewAnnotationCheck("severity", checks.MustTemplatedRegexp("critical"), true, checks.Warning)
},
problems: noProblems,
},
{
description: "doesn't ignore rules with syntax errors",
content: "- alert: foo\n expr: sum(foo) without(\n",
checker: checks.NewAnnotationCheck("severity", checks.MustTemplatedRegexp("critical"), true, checks.Warning),
problems: []checks.Problem{
{
Fragment: "alert: foo",
Lines: []int{1, 2},
Reporter: "alerts/annotation",
Text: "severity annotation is required",
Severity: checks.Warning,
},
checker: func(uri string) checks.RuleChecker {
return checks.NewAnnotationCheck("severity", checks.MustTemplatedRegexp("critical"), true, checks.Warning)
},
problems: func(uri string) []checks.Problem {
return []checks.Problem{
{
Fragment: "alert: foo",
Lines: []int{1, 2},
Reporter: checks.AnnotationCheckName,
Text: "severity annotation is required",
Severity: checks.Warning,
},
}
},
},
{
description: "no annotations / required",
content: "- alert: foo\n expr: sum(foo)\n",
checker: checks.NewAnnotationCheck("severity", checks.MustTemplatedRegexp("critical"), true, checks.Warning),
problems: []checks.Problem{
{
Fragment: "alert: foo",
Lines: []int{1, 2},
Reporter: "alerts/annotation",
Text: "severity annotation is required",
Severity: checks.Warning,
},
checker: func(uri string) checks.RuleChecker {
return checks.NewAnnotationCheck("severity", checks.MustTemplatedRegexp("critical"), true, checks.Warning)
},
problems: func(uri string) []checks.Problem {
return []checks.Problem{
{
Fragment: "alert: foo",
Lines: []int{1, 2},
Reporter: checks.AnnotationCheckName,
Text: "severity annotation is required",
Severity: checks.Warning,
},
}
},
},
{
description: "no annotations / not required",
content: "- alert: foo\n expr: sum(foo)\n",
checker: checks.NewAnnotationCheck("severity", checks.MustTemplatedRegexp("critical"), false, checks.Warning),
checker: func(uri string) checks.RuleChecker {
return checks.NewAnnotationCheck("severity", checks.MustTemplatedRegexp("critical"), false, checks.Warning)
},
problems: noProblems,
},
{
description: "missing annotation / required",
content: "- alert: foo\n expr: sum(foo)\n annotations:\n foo: bar\n",
checker: checks.NewAnnotationCheck("severity", checks.MustTemplatedRegexp("critical"), true, checks.Warning),
problems: []checks.Problem{
{
Fragment: "annotations:",
Lines: []int{3, 4},
Reporter: "alerts/annotation",
Text: "severity annotation is required",
Severity: checks.Warning,
},
checker: func(uri string) checks.RuleChecker {
return checks.NewAnnotationCheck("severity", checks.MustTemplatedRegexp("critical"), true, checks.Warning)
},
problems: func(uri string) []checks.Problem {
return []checks.Problem{
{
Fragment: "annotations:",
Lines: []int{3, 4},
Reporter: checks.AnnotationCheckName,
Text: "severity annotation is required",
Severity: checks.Warning,
},
}
},
},
{
description: "missing annotation / not required",
content: "- alert: foo\n expr: sum(foo)\n annotations:\n foo: bar\n",
checker: checks.NewAnnotationCheck("severity", checks.MustTemplatedRegexp("critical"), false, checks.Warning),
checker: func(uri string) checks.RuleChecker {
return checks.NewAnnotationCheck("severity", checks.MustTemplatedRegexp("critical"), false, checks.Warning)
},
problems: noProblems,
},
{
description: "wrong annotation value / required",
content: "- alert: foo\n expr: sum(foo)\n annotations:\n severity: bar\n",
checker: checks.NewAnnotationCheck("severity", checks.MustTemplatedRegexp("critical"), true, checks.Warning),
problems: []checks.Problem{
{
Fragment: "severity: bar",
Lines: []int{4},
Reporter: "alerts/annotation",
Text: `severity annotation value must match "^critical$"`,
Severity: checks.Warning,
},
checker: func(uri string) checks.RuleChecker {
return checks.NewAnnotationCheck("severity", checks.MustTemplatedRegexp("critical"), true, checks.Warning)
},
problems: func(uri string) []checks.Problem {
return []checks.Problem{
{
Fragment: "severity: bar",
Lines: []int{4},
Reporter: checks.AnnotationCheckName,
Text: `severity annotation value must match "^critical$"`,
Severity: checks.Warning,
},
}
},
},
{
description: "wrong annotation value / not required",
content: "- alert: foo\n expr: sum(foo)\n annotations:\n severity: bar\n",
checker: checks.NewAnnotationCheck("severity", checks.MustTemplatedRegexp("critical"), false, checks.Warning),
problems: []checks.Problem{
{
Fragment: "severity: bar",
Lines: []int{4},
Reporter: "alerts/annotation",
Text: `severity annotation value must match "^critical$"`,
Severity: checks.Warning,
},
checker: func(uri string) checks.RuleChecker {
return checks.NewAnnotationCheck("severity", checks.MustTemplatedRegexp("critical"), false, checks.Warning)
},
problems: func(uri string) []checks.Problem {
return []checks.Problem{
{
Fragment: "severity: bar",
Lines: []int{4},
Reporter: checks.AnnotationCheckName,
Text: `severity annotation value must match "^critical$"`,
Severity: checks.Warning,
},
}
},
},
{
description: "valid annotation / required",
content: "- alert: foo\n expr: sum(foo)\n annotations:\n severity: info\n",
checker: checks.NewAnnotationCheck("severity", checks.MustTemplatedRegexp("critical|info|debug"), true, checks.Warning),
checker: func(uri string) checks.RuleChecker {
return checks.NewAnnotationCheck("severity", checks.MustTemplatedRegexp("critical|info|debug"), true, checks.Warning)
},
problems: noProblems,
},
{
description: "valid annotation / not required",
content: "- alert: foo\n expr: sum(foo)\n annotations:\n severity: info\n",
checker: checks.NewAnnotationCheck("severity", checks.MustTemplatedRegexp("critical|info|debug"), false, checks.Warning),
checker: func(uri string) checks.RuleChecker {
return checks.NewAnnotationCheck("severity", checks.MustTemplatedRegexp("critical|info|debug"), false, checks.Warning)
},
problems: noProblems,
},
{
description: "templated annotation value / passing",
content: "- alert: foo\n expr: sum(foo)\n for: 5m\n annotations:\n for: 5m\n",
checker: checks.NewAnnotationCheck("for", checks.MustTemplatedRegexp("{{ $for }}"), true, checks.Bug),
checker: func(uri string) checks.RuleChecker {
return checks.NewAnnotationCheck("for", checks.MustTemplatedRegexp("{{ $for }}"), true, checks.Bug)
},
problems: noProblems,
},
{
description: "templated annotation value / passing",
content: "- alert: foo\n expr: sum(foo)\n for: 5m\n annotations:\n for: 4m\n",
checker: checks.NewAnnotationCheck("for", checks.MustTemplatedRegexp("{{ $for }}"), true, checks.Bug),
problems: []checks.Problem{
{
Fragment: "for: 4m",
Lines: []int{5},
Reporter: "alerts/annotation",
Text: `for annotation value must match "^{{ $for }}$"`,
Severity: checks.Bug,
},
checker: func(uri string) checks.RuleChecker {
return checks.NewAnnotationCheck("for", checks.MustTemplatedRegexp("{{ $for }}"), true, checks.Bug)
},
problems: func(uri string) []checks.Problem {
return []checks.Problem{
{
Fragment: "for: 4m",
Lines: []int{5},
Reporter: checks.AnnotationCheckName,
Text: `for annotation value must match "^{{ $for }}$"`,
Severity: checks.Bug,
},
}
},
},
}
Expand Down
91 changes: 55 additions & 36 deletions internal/checks/alerts_comparison_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,45 +6,56 @@ import (
"github.com/cloudflare/pint/internal/checks"
)

func newComparisonCheck(_ string) checks.RuleChecker {
return checks.NewComparisonCheck()
}

func TestComparisonCheck(t *testing.T) {
testCases := []checkTest{
{
description: "ignores recording rules",
content: "- record: foo\n expr: up == 0\n",
checker: checks.NewComparisonCheck(),
checker: newComparisonCheck,
problems: noProblems,
},
{
description: "ignores rules with syntax errors",
content: "- alert: Foo Is Down\n expr: sum(\n",
checker: checks.NewComparisonCheck(),
checker: newComparisonCheck,
problems: noProblems,
},
{
description: "alert expr with > condition",
content: "- alert: Foo Is Down\n for: 10m\n expr: up{job=\"foo\"} > 0\n",
checker: checks.NewComparisonCheck(),
checker: newComparisonCheck,
problems: noProblems,
},
{
description: "alert expr with >= condition",
content: "- alert: Foo Is Down\n for: 10m\n expr: up{job=\"foo\"} >= 1\n",
checker: checks.NewComparisonCheck(),
checker: newComparisonCheck,
problems: noProblems,
},
{
description: "alert expr with == condition",
content: "- alert: Foo Is Down\n for: 10m\n expr: up{job=\"foo\"} == 1\n",
checker: checks.NewComparisonCheck(),
checker: newComparisonCheck,
problems: noProblems,
},
{
description: "alert expr without any condition",
content: "- alert: Foo Is Down\n expr: up{job=\"foo\"}\n",
checker: checks.NewComparisonCheck(),
problems: []checks.Problem{
{
Fragment: `up{job="foo"}`,
Lines: []int{2},
Reporter: "alerts/comparison",
Text: "alert query doesn't have any condition, it will always fire if the metric exists",
Severity: checks.Warning,
},
checker: newComparisonCheck,
problems: func(uri string) []checks.Problem {
return []checks.Problem{
{
Fragment: `up{job="foo"}`,
Lines: []int{2},
Reporter: checks.ComparisonCheckName,
Text: "alert query doesn't have any condition, it will always fire if the metric exists",
Severity: checks.Warning,
},
}
},
},
{
Expand All @@ -55,7 +66,8 @@ func TestComparisonCheck(t *testing.T) {
AND ON (instance)
(rate(node_netstat_Udp_RcvbufErrors[5m])+rate(node_netstat_Udp6_RcvbufErrors[5m])) > 200
`,
checker: checks.NewComparisonCheck(),
checker: newComparisonCheck,
problems: noProblems,
},
{
description: "deep level without comparison",
Expand All @@ -65,45 +77,52 @@ func TestComparisonCheck(t *testing.T) {
AND ON (instance)
rate(node_netstat_Udp_RcvbufErrors[5m])+rate(node_netstat_Udp6_RcvbufErrors[5m])
`,
checker: checks.NewComparisonCheck(),
problems: []checks.Problem{
{
Fragment: `quantile_over_time(0.7,(irate(udp_packets_drops[2m]))[10m:2m]) AND ON (instance) rate(node_netstat_Udp_RcvbufErrors[5m])+rate(node_netstat_Udp6_RcvbufErrors[5m])`,
Lines: []int{3},
Reporter: "alerts/comparison",
Text: "alert query doesn't have any condition, it will always fire if the metric exists",
Severity: checks.Warning,
},
checker: newComparisonCheck,
problems: func(uri string) []checks.Problem {
return []checks.Problem{
{
Fragment: `quantile_over_time(0.7,(irate(udp_packets_drops[2m]))[10m:2m]) AND ON (instance) rate(node_netstat_Udp_RcvbufErrors[5m])+rate(node_netstat_Udp6_RcvbufErrors[5m])`,
Lines: []int{3},
Reporter: checks.ComparisonCheckName,
Text: "alert query doesn't have any condition, it will always fire if the metric exists",
Severity: checks.Warning,
},
}
},
},
{
description: "alert unless condition",
content: "- alert: Foo Is Down\n for: 10m\n expr: foo unless bar\n",
checker: checks.NewComparisonCheck(),
checker: newComparisonCheck,
problems: noProblems,
},
{
description: "alert expr with bool",
content: "- alert: Error rate is high\n expr: rate(error_count[5m]) > bool 5\n",
checker: checks.NewComparisonCheck(),
problems: []checks.Problem{
{
Fragment: "rate(error_count[5m]) > bool 5",
Lines: []int{2},
Reporter: "alerts/comparison",
Text: "alert query uses bool modifier for comparison, this means it will always return a result and the alert will always fire",
Severity: checks.Bug,
},
checker: newComparisonCheck,
problems: func(uri string) []checks.Problem {
return []checks.Problem{
{
Fragment: "rate(error_count[5m]) > bool 5",
Lines: []int{2},
Reporter: checks.ComparisonCheckName,
Text: "alert query uses bool modifier for comparison, this means it will always return a result and the alert will always fire",
Severity: checks.Bug,
},
}
},
},
{
description: "alert expr with bool and condition",
content: "- alert: Error rate is high\n expr: rate(error_count[5m]) > bool 5 == 1\n",
checker: checks.NewComparisonCheck(),
checker: newComparisonCheck,
problems: noProblems,
},
{
description: "alert on absent",
content: "- alert: Foo Is Missing\n expr: absent(foo)\n",
checker: checks.NewComparisonCheck(),
checker: newComparisonCheck,
problems: noProblems,
},
}

Expand Down
Loading

0 comments on commit 1be963a

Please sign in to comment.