cloudflare/pint

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v0.80.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

internal/parser/promql_test.go

222lines · modecode

1package parser_test
2
3import (
4 "testing"
5
6 promParser "github.com/prometheus/prometheus/promql/parser"
7 "github.com/stretchr/testify/require"
8
9 "github.com/cloudflare/pint/internal/parser"
10)
11
12func TestWalkUpExpr(t *testing.T) {
13 type testCaseT struct {
14 walkFromChild func(*parser.PromQLNode) *parser.PromQLNode
15 name string
16 expr string
17 expected int
18 }
19
20 testCases := []testCaseT{
21 {
22 name: "nil node returns empty",
23 expr: "",
24 walkFromChild: nil,
25 expected: 0,
26 },
27 {
28 name: "single VectorSelector matches itself",
29 expr: "foo",
30 walkFromChild: func(n *parser.PromQLNode) *parser.PromQLNode {
31 return n
32 },
33 expected: 1,
34 },
35 {
36 name: "VectorSelector inside rate - walk from selector finds both",
37 expr: "rate(foo[5m])",
38 walkFromChild: func(n *parser.PromQLNode) *parser.PromQLNode {
39 // rate -> MatrixSelector -> VectorSelector, walk from deepest
40 return n.Children[0].Children[0]
41 },
42 expected: 1, // only VectorSelector matches
43 },
44 {
45 name: "sum(rate(foo[5m])) - walk from VectorSelector",
46 expr: "sum(rate(foo[5m]))",
47 walkFromChild: func(n *parser.PromQLNode) *parser.PromQLNode {
48 // sum(AggregateExpr) -> rate(Call) -> MatrixSelector -> VectorSelector
49 return n.Children[0].Children[0].Children[0]
50 },
51 expected: 1, // only the VectorSelector matches
52 },
53 {
54 name: "binary expr - walk from left side",
55 expr: "foo + bar",
56 walkFromChild: func(n *parser.PromQLNode) *parser.PromQLNode {
57 // BinaryExpr -> left VectorSelector
58 return n.Children[0]
59 },
60 expected: 1, // left VectorSelector
61 },
62 {
63 name: "nested aggregation - walk from innermost",
64 expr: "sum(avg(foo))",
65 walkFromChild: func(n *parser.PromQLNode) *parser.PromQLNode {
66 // sum -> avg -> foo, walk from foo
67 return n.Children[0].Children[0]
68 },
69 expected: 1, // only foo is VectorSelector
70 },
71 {
72 name: "no match in tree",
73 expr: "1 + 2",
74 walkFromChild: func(n *parser.PromQLNode) *parser.PromQLNode {
75 return n
76 },
77 expected: 0, // no VectorSelector in numeric expression
78 },
79 }
80
81 for _, tc := range testCases {
82 t.Run(tc.name, func(t *testing.T) {
83 if tc.walkFromChild == nil {
84 // Test nil node case
85 nodes := parser.WalkUpExpr[*promParser.VectorSelector](nil)
86 require.Len(t, nodes, tc.expected)
87 return
88 }
89
90 query, err := parser.DecodeExpr(tc.expr)
91 require.NoError(t, err)
92
93 startNode := tc.walkFromChild(query)
94 nodes := parser.WalkUpExpr[*promParser.VectorSelector](startNode)
95 require.Len(t, nodes, tc.expected)
96 })
97 }
98}
99
100func TestWalkUpExprForCallNodes(t *testing.T) {
101 type testCaseT struct {
102 walkFromChild func(*parser.PromQLNode) *parser.PromQLNode
103 name string
104 expr string
105 expected int
106 }
107
108 testCases := []testCaseT{
109 {
110 name: "rate(foo[5m]) - walk from selector finds one Call",
111 expr: "rate(foo[5m])",
112 walkFromChild: func(n *parser.PromQLNode) *parser.PromQLNode {
113 // rate(Call) -> MatrixSelector -> VectorSelector
114 return n.Children[0].Children[0]
115 },
116 expected: 1,
117 },
118 {
119 name: "sum(rate(foo[5m])) - walk from selector finds one Call (sum is AggregateExpr)",
120 expr: "sum(rate(foo[5m]))",
121 walkFromChild: func(n *parser.PromQLNode) *parser.PromQLNode {
122 // sum(AggregateExpr) -> rate(Call) -> MatrixSelector -> VectorSelector
123 return n.Children[0].Children[0].Children[0]
124 },
125 expected: 1, // only rate is Call, sum is AggregateExpr
126 },
127 {
128 name: "histogram_quantile(0.9, sum(rate(foo[5m]))) - two Calls",
129 expr: "histogram_quantile(0.9, sum(rate(foo[5m])))",
130 walkFromChild: func(n *parser.PromQLNode) *parser.PromQLNode {
131 // histogram_quantile(Call) -> sum(AggregateExpr) -> rate(Call) -> MatrixSelector -> VectorSelector
132 return n.Children[1].Children[0].Children[0].Children[0]
133 },
134 expected: 2, // histogram_quantile and rate are Calls
135 },
136 {
137 name: "plain metric - no Call nodes",
138 expr: "foo",
139 walkFromChild: func(n *parser.PromQLNode) *parser.PromQLNode {
140 return n
141 },
142 expected: 0,
143 },
144 {
145 name: "clamp(foo, 0, 1) - walk from root finds Call",
146 expr: "clamp(foo, 0, 1)",
147 walkFromChild: func(n *parser.PromQLNode) *parser.PromQLNode {
148 return n
149 },
150 expected: 1,
151 },
152 }
153
154 for _, tc := range testCases {
155 t.Run(tc.name, func(t *testing.T) {
156 query, err := parser.DecodeExpr(tc.expr)
157 require.NoError(t, err)
158
159 startNode := tc.walkFromChild(query)
160 nodes := parser.WalkUpExpr[*promParser.Call](startNode)
161 require.Len(t, nodes, tc.expected)
162 })
163 }
164}
165
166func TestWalkUpExprForAggregateExpr(t *testing.T) {
167 type testCaseT struct {
168 walkFromChild func(*parser.PromQLNode) *parser.PromQLNode
169 name string
170 expr string
171 expected int
172 }
173
174 testCases := []testCaseT{
175 {
176 name: "sum(foo) - walk from selector finds one AggregateExpr",
177 expr: "sum(foo)",
178 walkFromChild: func(n *parser.PromQLNode) *parser.PromQLNode {
179 // sum(AggregateExpr) -> VectorSelector
180 return n.Children[0]
181 },
182 expected: 1,
183 },
184 {
185 name: "sum(avg(foo)) - walk from selector finds two AggregateExprs",
186 expr: "sum(avg(foo))",
187 walkFromChild: func(n *parser.PromQLNode) *parser.PromQLNode {
188 // sum -> avg -> foo
189 return n.Children[0].Children[0]
190 },
191 expected: 2,
192 },
193 {
194 name: "rate(foo[5m]) - no AggregateExpr",
195 expr: "rate(foo[5m])",
196 walkFromChild: func(n *parser.PromQLNode) *parser.PromQLNode {
197 return n.Children[0].Children[0]
198 },
199 expected: 0,
200 },
201 {
202 name: "sum by (job) (rate(foo[5m])) - walk from selector",
203 expr: "sum by (job) (rate(foo[5m]))",
204 walkFromChild: func(n *parser.PromQLNode) *parser.PromQLNode {
205 // sum -> rate -> MatrixSelector -> VectorSelector
206 return n.Children[0].Children[0].Children[0]
207 },
208 expected: 1,
209 },
210 }
211
212 for _, tc := range testCases {
213 t.Run(tc.name, func(t *testing.T) {
214 query, err := parser.DecodeExpr(tc.expr)
215 require.NoError(t, err)
216
217 startNode := tc.walkFromChild(query)
218 nodes := parser.WalkUpExpr[*promParser.AggregateExpr](startNode)
219 require.Len(t, nodes, tc.expected)
220 })
221 }
222}
223