1use crate::parser::{lex, Expr, INVALID_QUERY_INFO};
16
17pub fn parse(input: &str) -> Result<Expr, String> {
19 match lex::lexer(input) {
20 Err(e) => Err(e),
21 Ok(lexer) => {
22 let (res, _errs) = crate::promql_y::parse(&lexer);
24 res.ok_or_else(|| String::from(INVALID_QUERY_INFO))?
25 }
26 }
27}
28
29#[cfg(test)]
36mod tests {
37 use regex::Regex;
38
39 use crate::parser;
40 use crate::parser::function::get_function;
41 use crate::parser::{
42 token, AtModifier as At, BinModifier, Expr, FunctionArgs, LabelModifier, Offset,
43 VectorMatchCardinality, VectorSelector, INVALID_QUERY_INFO,
44 };
45 use crate::util::duration;
46 use crate::{
47 label::{Labels, MatchOp, Matcher, Matchers, METRIC_NAME},
48 util::duration::{DAY_DURATION, HOUR_DURATION, MINUTE_DURATION, YEAR_DURATION},
49 };
50 use std::time::Duration;
51 use std::vec;
52
53 struct Case {
54 input: String,
55 expected: Result<Expr, String>,
56 }
57
58 impl Case {
59 fn new(input: &str, expected: Result<Expr, String>) -> Self {
60 Case {
61 input: String::from(input),
62 expected,
63 }
64 }
65
66 fn new_result_cases(cases: Vec<(&str, Result<Expr, String>)>) -> Vec<Case> {
67 cases
68 .into_iter()
69 .map(|(input, expected)| Case::new(input, expected))
70 .collect()
71 }
72
73 fn new_expr_cases(cases: Vec<(&str, Expr)>) -> Vec<Case> {
74 cases
75 .into_iter()
76 .map(|(input, expected)| Case::new(input, Ok(expected)))
77 .collect()
78 }
79
80 fn new_fail_cases(cases: Vec<(&str, &str)>) -> Vec<Case> {
81 cases
82 .into_iter()
83 .map(|(input, expected)| Case::new(input, Err(expected.into())))
84 .collect()
85 }
86 }
87
88 fn assert_cases(cases: Vec<Case>) {
89 for Case { input, expected } in cases {
90 assert_eq!(expected, crate::parser::parse(&input));
91 }
92 }
93
94 #[test]
95 fn test_number_literal() {
96 let cases = vec![
97 ("1", Expr::from(1.0)),
98 ("Inf", Expr::from(f64::INFINITY)),
99 ("+Inf", Expr::from(f64::INFINITY)),
100 ("-Inf", Expr::from(f64::NEG_INFINITY)),
101 (".5", Expr::from(0.5)),
102 ("5.", Expr::from(5.0)),
103 ("123.4567", Expr::from(123.4567)),
104 ("5e-3", Expr::from(0.005)),
105 ("5e3", Expr::from(5000.0)),
106 ("0xc", Expr::from(12.0)),
107 ("0755", Expr::from(493.0)),
108 ("08", Expr::from(8.0)),
109 ("+5.5e-3", Expr::from(0.0055)),
110 ("-0755", Expr::from(-493.0)),
111
112 ("NaN", Expr::from(f64::NAN)),
114 (
115 "999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999",
116 Expr::from(f64::INFINITY)
117 ),
118 ];
119 assert_cases(Case::new_expr_cases(cases));
120 }
121
122 #[test]
123 fn test_string_literal() {
124 let cases = vec![
125 (
126 "\"double-quoted string \\\" with escaped quote\"",
127 Expr::from("double-quoted string \" with escaped quote"),
128 ),
129 (
130 r#""double-quoted raw string \" with escaped quote""#,
131 Expr::from(r#"double-quoted raw string " with escaped quote"#),
132 ),
133 (
134 r#"'single-quoted string \' with escaped quote'"#,
135 Expr::from("single-quoted string ' with escaped quote"),
136 ),
137 (
138 "`backtick-quoted string`",
139 Expr::from("backtick-quoted string"),
140 ),
141 (
143 r#""\a\b\f\n\r\t\v\\\" - \xFF\377\u1234\U00010111\U0001011111☺""#,
144 Expr::from("\u{7}\u{8}\u{c}\n\r\t\u{b}\\\" - ÿÿሴ𐄑𐄑11☺"),
145 ),
146 (
147 r"'\a\b\f\n\r\t\v\\\' - \xFF\377\u1234\U00010111\U0001011111☺'",
148 Expr::from("\u{7}\u{8}\u{c}\n\r\t\u{b}\\' - ÿÿሴ𐄑𐄑11☺"),
149 ),
150 (
152 r"`\a\b\f\n\r\t\v\\ - \xFF\377\u1234\U00010111\U0001011111☺`",
153 Expr::from(r"\a\b\f\n\r\t\v\\ - \xFF\377\u1234\U00010111\U0001011111☺"),
154 ),
155 ];
156 assert_cases(Case::new_expr_cases(cases));
157
158 let fail_cases = vec![
159 (r"`\\``", "unterminated quoted string `"),
160 (r#""\"#, "escape sequence not terminated"),
161 (r#""\c""#, "unknown escape sequence 'c'"),
162 ];
164 assert_cases(Case::new_fail_cases(fail_cases));
165 }
166
167 #[test]
168 fn test_duration_literal() {
169 let cases = vec![
170 ("1ms", Expr::from(Duration::from_millis(1).as_secs_f64())),
171 ("1s", Expr::from(Duration::from_secs(1).as_secs_f64())),
172 ("1m", Expr::from(MINUTE_DURATION.as_secs_f64())),
173 ("1h", Expr::from(HOUR_DURATION.as_secs_f64())),
174 ("1d", Expr::from(DAY_DURATION.as_secs_f64())),
175 ("1y", Expr::from(YEAR_DURATION.as_secs_f64())),
176 (
177 "1y2d4h8m16s32ms",
178 Expr::from(
179 (YEAR_DURATION
180 + DAY_DURATION * 2
181 + HOUR_DURATION * 4
182 + MINUTE_DURATION * 8
183 + Duration::from_secs(16)
184 + Duration::from_millis(32))
185 .as_secs_f64(),
186 ),
187 ),
188 ];
189 assert_cases(Case::new_expr_cases(cases));
190 }
191
192 #[test]
193 fn test_vector_binary_expr() {
194 let cases = vec![
195 (
196 "1 + 1",
197 Expr::new_binary_expr(Expr::from(1.0), token::T_ADD, None, Expr::from(1.0)),
198 ),
199 (
200 "1 - 1",
201 Expr::new_binary_expr(Expr::from(1.0), token::T_SUB, None, Expr::from(1.0)),
202 ),
203 (
204 "1 * 1",
205 Expr::new_binary_expr(Expr::from(1.0), token::T_MUL, None, Expr::from(1.0)),
206 ),
207 (
208 "1 / 1",
209 Expr::new_binary_expr(Expr::from(1.0), token::T_DIV, None, Expr::from(1.0)),
210 ),
211 (
212 "1 % 1",
213 Expr::new_binary_expr(Expr::from(1.0), token::T_MOD, None, Expr::from(1.0)),
214 ),
215 (
216 "1 == bool 1",
217 Expr::new_binary_expr(
218 Expr::from(1.0),
219 token::T_EQLC,
220 Some(BinModifier::default().with_return_bool(true)),
221 Expr::from(1.0),
222 ),
223 ),
224 (
225 "1 != bool 1",
226 Expr::new_binary_expr(
227 Expr::from(1.0),
228 token::T_NEQ,
229 Some(BinModifier::default().with_return_bool(true)),
230 Expr::from(1.0),
231 ),
232 ),
233 (
234 "1 > bool 1",
235 Expr::new_binary_expr(
236 Expr::from(1.0),
237 token::T_GTR,
238 Some(BinModifier::default().with_return_bool(true)),
239 Expr::from(1.0),
240 ),
241 ),
242 (
243 "1 >= bool 1",
244 Expr::new_binary_expr(
245 Expr::from(1.0),
246 token::T_GTE,
247 Some(BinModifier::default().with_return_bool(true)),
248 Expr::from(1.0),
249 ),
250 ),
251 (
252 "1 < bool 1",
253 Expr::new_binary_expr(
254 Expr::from(1.0),
255 token::T_LSS,
256 Some(BinModifier::default().with_return_bool(true)),
257 Expr::from(1.0),
258 ),
259 ),
260 (
261 "1 <= bool 1",
262 Expr::new_binary_expr(
263 Expr::from(1.0),
264 token::T_LTE,
265 Some(BinModifier::default().with_return_bool(true)),
266 Expr::from(1.0),
267 ),
268 ),
269 (
270 "-1^2",
271 Expr::new_binary_expr(Expr::from(1.0), token::T_POW, None, Expr::from(2.0))
272 .map(|ex| -ex),
273 ),
274 (
275 "-1*2",
276 Expr::new_binary_expr(Expr::from(-1.0), token::T_MUL, None, Expr::from(2.0)),
277 ),
278 (
279 "-1+2",
280 Expr::new_binary_expr(Expr::from(-1.0), token::T_ADD, None, Expr::from(2.0)),
281 ),
282 (
283 "-1^-2",
284 Expr::new_binary_expr(Expr::from(1.0), token::T_POW, None, Expr::from(-2.0))
285 .map(|ex| -ex),
286 ),
287 (
288 "+1 + -2 * 1",
289 Expr::new_binary_expr(Expr::from(-2.0), token::T_MUL, None, Expr::from(1.0))
290 .and_then(|ex| Expr::new_binary_expr(Expr::from(1.0), token::T_ADD, None, ex)),
291 ),
292 (
293 "1 + 2/(3*1)",
294 Expr::new_binary_expr(Expr::from(3.0), token::T_MUL, None, Expr::from(1.0))
295 .and_then(Expr::new_paren_expr)
296 .and_then(|ex| Expr::new_binary_expr(Expr::from(2.0), token::T_DIV, None, ex))
297 .and_then(|ex| Expr::new_binary_expr(Expr::from(1.0), token::T_ADD, None, ex)),
298 ),
299 (
300 "1 < bool 2 - 1 * 2",
301 Expr::new_binary_expr(Expr::from(1.0), token::T_MUL, None, Expr::from(2.0))
302 .and_then(|ex| Expr::new_binary_expr(Expr::from(2.0), token::T_SUB, None, ex))
303 .and_then(|ex| {
304 Expr::new_binary_expr(
305 Expr::from(1.0),
306 token::T_LSS,
307 Some(BinModifier::default().with_return_bool(true)),
308 ex,
309 )
310 }),
311 ),
312 (
313 "foo * bar",
314 Expr::new_binary_expr(
315 Expr::from(VectorSelector::from("foo")),
316 token::T_MUL,
317 None,
318 Expr::from(VectorSelector::from("bar")),
319 ),
320 ),
321 (
322 "foo * sum",
323 Expr::new_binary_expr(
324 Expr::from(VectorSelector::from("foo")),
325 token::T_MUL,
326 None,
327 Expr::from(VectorSelector::from("sum")),
328 ),
329 ),
330 (
331 "foo == 1",
332 Expr::new_binary_expr(
333 Expr::from(VectorSelector::from("foo")),
334 token::T_EQLC,
335 None,
336 Expr::from(1.0),
337 ),
338 ),
339 (
340 "foo == bool 1",
341 Expr::new_binary_expr(
342 Expr::from(VectorSelector::from("foo")),
343 token::T_EQLC,
344 Some(BinModifier::default().with_return_bool(true)),
345 Expr::from(1.0),
346 ),
347 ),
348 (
349 "2.5 / bar",
350 Expr::new_binary_expr(
351 Expr::from(2.5),
352 token::T_DIV,
353 None,
354 Expr::from(VectorSelector::from("bar")),
355 ),
356 ),
357 (
358 "foo and bar",
359 Expr::new_binary_expr(
360 Expr::from(VectorSelector::from("foo")),
361 token::T_LAND,
362 Some(BinModifier::default().with_card(VectorMatchCardinality::ManyToMany)),
363 Expr::from(VectorSelector::from("bar")),
364 ),
365 ),
366 (
367 "foo or bar",
368 Expr::new_binary_expr(
369 Expr::from(VectorSelector::from("foo")),
370 token::T_LOR,
371 Some(BinModifier::default().with_card(VectorMatchCardinality::ManyToMany)),
372 Expr::from(VectorSelector::from("bar")),
373 ),
374 ),
375 (
376 "foo unless bar",
377 Expr::new_binary_expr(
378 Expr::from(VectorSelector::from("foo")),
379 token::T_LUNLESS,
380 Some(BinModifier::default().with_card(VectorMatchCardinality::ManyToMany)),
381 Expr::from(VectorSelector::from("bar")),
382 ),
383 ),
384 (
385 "foo + bar or bla and blub",
387 {
388 let lhs = Expr::new_binary_expr(
389 Expr::from(VectorSelector::from("foo")),
390 token::T_ADD,
391 None,
392 Expr::from(VectorSelector::from("bar")),
393 );
394 let rhs = Expr::new_binary_expr(
395 Expr::from(VectorSelector::from("bla")),
396 token::T_LAND,
397 Some(BinModifier::default().with_card(VectorMatchCardinality::ManyToMany)),
398 Expr::from(VectorSelector::from("blub")),
399 );
400 Expr::new_binary_expr(
401 lhs.unwrap(),
402 token::T_LOR,
403 Some(BinModifier::default().with_card(VectorMatchCardinality::ManyToMany)),
404 rhs.unwrap(),
405 )
406 },
407 ),
408 (
409 "foo and bar unless baz or qux",
411 Expr::new_binary_expr(
412 Expr::from(VectorSelector::from("foo")),
413 token::T_LAND,
414 Some(BinModifier::default().with_card(VectorMatchCardinality::ManyToMany)),
415 Expr::from(VectorSelector::from("bar")),
416 )
417 .and_then(|ex| {
418 Expr::new_binary_expr(
419 ex,
420 token::T_LUNLESS,
421 Some(BinModifier::default().with_card(VectorMatchCardinality::ManyToMany)),
422 Expr::from(VectorSelector::from("baz")),
423 )
424 })
425 .and_then(|ex| {
426 Expr::new_binary_expr(
427 ex,
428 token::T_LOR,
429 Some(BinModifier::default().with_card(VectorMatchCardinality::ManyToMany)),
430 Expr::from(VectorSelector::from("qux")),
431 )
432 }),
433 ),
434 (
435 "bar + on(foo) bla / on(baz, buz) group_right(test) blub",
437 Expr::new_binary_expr(
438 Expr::from(VectorSelector::from("bla")),
439 token::T_DIV,
440 Some(
441 BinModifier::default()
442 .with_card(VectorMatchCardinality::one_to_many(vec!["test"]))
443 .with_matching(Some(LabelModifier::include(vec!["baz", "buz"]))),
444 ),
445 Expr::from(VectorSelector::from("blub")),
446 )
447 .and_then(|ex| {
448 Expr::new_binary_expr(
449 Expr::from(VectorSelector::from("bar")),
450 token::T_ADD,
451 Some(
452 BinModifier::default()
453 .with_matching(Some(LabelModifier::include(vec!["foo"]))),
454 ),
455 ex,
456 )
457 }),
458 ),
459 (
460 "foo * on(test,blub) bar",
461 Expr::new_binary_expr(
462 Expr::from(VectorSelector::from("foo")),
463 token::T_MUL,
464 Some(
465 BinModifier::default()
466 .with_matching(Some(LabelModifier::include(vec!["test", "blub"]))),
467 ),
468 Expr::from(VectorSelector::from("bar")),
469 ),
470 ),
471 (
472 "foo * on(test,blub) group_left bar",
473 Expr::new_binary_expr(
474 Expr::from(VectorSelector::from("foo")),
475 token::T_MUL,
476 Some(
477 BinModifier::default()
478 .with_matching(Some(LabelModifier::include(vec!["test", "blub"])))
479 .with_card(VectorMatchCardinality::many_to_one(vec![])),
480 ),
481 Expr::from(VectorSelector::from("bar")),
482 ),
483 ),
484 ("foo and on(test,blub) bar", {
485 let matching = LabelModifier::include(vec!["test", "blub"]);
486 let card = VectorMatchCardinality::ManyToMany;
487 Expr::new_binary_expr(
488 Expr::from(VectorSelector::from("foo")),
489 token::T_LAND,
490 Some(
491 BinModifier::default()
492 .with_matching(Some(matching))
493 .with_card(card),
494 ),
495 Expr::from(VectorSelector::from("bar")),
496 )
497 }),
498 ("foo and on() bar", {
499 let matching = LabelModifier::include(vec![]);
500 let card = VectorMatchCardinality::ManyToMany;
501 Expr::new_binary_expr(
502 Expr::from(VectorSelector::from("foo")),
503 token::T_LAND,
504 Some(
505 BinModifier::default()
506 .with_matching(Some(matching))
507 .with_card(card),
508 ),
509 Expr::from(VectorSelector::from("bar")),
510 )
511 }),
512 ("foo and ignoring(test,blub) bar", {
513 let matching = LabelModifier::exclude(vec!["test", "blub"]);
514 let card = VectorMatchCardinality::ManyToMany;
515 Expr::new_binary_expr(
516 Expr::from(VectorSelector::from("foo")),
517 token::T_LAND,
518 Some(
519 BinModifier::default()
520 .with_matching(Some(matching))
521 .with_card(card),
522 ),
523 Expr::from(VectorSelector::from("bar")),
524 )
525 }),
526 ("foo and ignoring() bar", {
527 let matching = LabelModifier::exclude(vec![]);
528 let card = VectorMatchCardinality::ManyToMany;
529 Expr::new_binary_expr(
530 Expr::from(VectorSelector::from("foo")),
531 token::T_LAND,
532 Some(
533 BinModifier::default()
534 .with_matching(Some(matching))
535 .with_card(card),
536 ),
537 Expr::from(VectorSelector::from("bar")),
538 )
539 }),
540 ("foo unless on(bar) baz", {
541 let matching = LabelModifier::include(vec!["bar"]);
542 let card = VectorMatchCardinality::ManyToMany;
543 Expr::new_binary_expr(
544 Expr::from(VectorSelector::from("foo")),
545 token::T_LUNLESS,
546 Some(
547 BinModifier::default()
548 .with_matching(Some(matching))
549 .with_card(card),
550 ),
551 Expr::from(VectorSelector::from("baz")),
552 )
553 }),
554 (
555 "foo / on(test,blub) group_left(bar) bar",
556 Expr::new_binary_expr(
557 Expr::from(VectorSelector::from("foo")),
558 token::T_DIV,
559 Some(
560 BinModifier::default()
561 .with_matching(Some(LabelModifier::include(vec!["test", "blub"])))
562 .with_card(VectorMatchCardinality::many_to_one(vec!["bar"])),
563 ),
564 Expr::from(VectorSelector::from("bar")),
565 ),
566 ),
567 (
568 "foo / ignoring(test,blub) group_left(blub) bar",
569 Expr::new_binary_expr(
570 Expr::from(VectorSelector::from("foo")),
571 token::T_DIV,
572 Some(
573 BinModifier::default()
574 .with_matching(Some(LabelModifier::exclude(vec!["test", "blub"])))
575 .with_card(VectorMatchCardinality::many_to_one(vec!["blub"])),
576 ),
577 Expr::from(VectorSelector::from("bar")),
578 ),
579 ),
580 (
581 "foo / ignoring(test,blub) group_left(bar) bar",
582 Expr::new_binary_expr(
583 Expr::from(VectorSelector::from("foo")),
584 token::T_DIV,
585 Some(
586 BinModifier::default()
587 .with_matching(Some(LabelModifier::exclude(vec!["test", "blub"])))
588 .with_card(VectorMatchCardinality::many_to_one(vec!["bar"])),
589 ),
590 Expr::from(VectorSelector::from("bar")),
591 ),
592 ),
593 (
594 "foo - on(test,blub) group_right(bar,foo) bar",
595 Expr::new_binary_expr(
596 Expr::from(VectorSelector::from("foo")),
597 token::T_SUB,
598 Some(
599 BinModifier::default()
600 .with_matching(Some(LabelModifier::include(vec!["test", "blub"])))
601 .with_card(VectorMatchCardinality::one_to_many(vec!["bar", "foo"])),
602 ),
603 Expr::from(VectorSelector::from("bar")),
604 ),
605 ),
606 (
607 "foo - ignoring(test,blub) group_right(bar,foo) bar",
608 Expr::new_binary_expr(
609 Expr::from(VectorSelector::from("foo")),
610 token::T_SUB,
611 Some(
612 BinModifier::default()
613 .with_matching(Some(LabelModifier::exclude(vec!["test", "blub"])))
614 .with_card(VectorMatchCardinality::one_to_many(vec!["bar", "foo"])),
615 ),
616 Expr::from(VectorSelector::from("bar")),
617 ),
618 ),
619 (
620 "a + sum",
621 Expr::new_binary_expr(
622 Expr::from(VectorSelector::from("a")),
623 token::T_ADD,
624 None,
625 Expr::from(VectorSelector::from("sum")),
626 ),
627 ),
628 (
630 r#"method_code:http_errors:rate5m{code="500"} / ignoring(code) method:http_requests:rate5m"#,
631 {
632 let name = String::from("method_code:http_errors:rate5m");
633 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "code", "500"));
634 let lhs = Expr::new_vector_selector(Some(name), matchers).unwrap();
635 Expr::new_binary_expr(
636 lhs,
637 token::T_DIV,
638 Some(
639 BinModifier::default()
640 .with_matching(Some(LabelModifier::exclude(vec!["code"]))),
641 ),
642 Expr::from(VectorSelector::from("method:http_requests:rate5m")),
643 )
644 },
645 ),
646 (
647 r#"method_code:http_errors:rate5m / ignoring(code) group_left method:http_requests:rate5m"#,
648 Expr::new_binary_expr(
649 Expr::from(VectorSelector::from("method_code:http_errors:rate5m")),
650 token::T_DIV,
651 Some(
652 BinModifier::default()
653 .with_matching(Some(LabelModifier::exclude(vec!["code"])))
654 .with_card(VectorMatchCardinality::ManyToOne(Labels::new(vec![]))),
655 ),
656 Expr::from(VectorSelector::from("method:http_requests:rate5m")),
657 ),
658 ),
659 ];
660 assert_cases(Case::new_result_cases(cases));
661
662 let fail_cases = vec![
663 (
664 "foo and 1",
665 "set operator 'and' not allowed in binary scalar expression",
666 ),
667 (
668 "1 and foo",
669 "set operator 'and' not allowed in binary scalar expression",
670 ),
671 (
672 "foo or 1",
673 "set operator 'or' not allowed in binary scalar expression",
674 ),
675 (
676 "1 or foo",
677 "set operator 'or' not allowed in binary scalar expression",
678 ),
679 (
680 "foo unless 1",
681 "set operator 'unless' not allowed in binary scalar expression",
682 ),
683 (
684 "1 unless foo",
685 "set operator 'unless' not allowed in binary scalar expression",
686 ),
687 (
688 "1 or on(bar) foo",
689 "set operator 'or' not allowed in binary scalar expression",
690 ),
691 (
692 "foo == on(bar) 10",
693 "vector matching only allowed between vectors",
694 ),
695 ("foo + group_left(baz) bar", "unexpected <group_left>"),
697 (
698 "foo and on(bar) group_left(baz) bar",
699 "no grouping allowed for 'and' operation",
700 ),
701 (
702 "foo and on(bar) group_right(baz) bar",
703 "no grouping allowed for 'and' operation",
704 ),
705 (
706 "foo or on(bar) group_left(baz) bar",
707 "no grouping allowed for 'or' operation",
708 ),
709 (
710 "foo or on(bar) group_right(baz) bar",
711 "no grouping allowed for 'or' operation",
712 ),
713 (
714 "foo unless on(bar) group_left(baz) bar",
715 "no grouping allowed for 'unless' operation",
716 ),
717 (
718 "foo unless on(bar) group_right(baz) bar",
719 "no grouping allowed for 'unless' operation",
720 ),
721 (
722 r#"http_requests{group="production"} + on(instance) group_left(job,instance) cpu_count{type="smp"}"#,
723 "label 'instance' must not occur in ON and GROUP clause at once",
724 ),
725 (
726 "foo + bool bar",
727 "bool modifier can only be used on comparison operators",
728 ),
729 (
730 "foo + bool 10",
731 "bool modifier can only be used on comparison operators",
732 ),
733 (
734 "foo and bool 10",
735 "bool modifier can only be used on comparison operators",
736 ),
737 (
738 "1 and 1",
739 "set operator 'and' not allowed in binary scalar expression",
740 ),
741 (
742 "1 == 1",
743 "comparisons between scalars must use BOOL modifier",
744 ),
745 (
746 "1 or 1",
747 "set operator 'or' not allowed in binary scalar expression",
748 ),
749 (
750 "1 unless 1",
751 "set operator 'unless' not allowed in binary scalar expression",
752 ),
753 ];
754 assert_cases(Case::new_fail_cases(fail_cases));
755 }
756
757 #[test]
758 fn test_unary_expr() {
759 let cases = vec![
760 (
761 "-some_metric",
762 Expr::new_unary_expr(Expr::from(VectorSelector::from("some_metric"))).unwrap(),
763 ),
764 (
765 "+some_metric",
766 Expr::from(VectorSelector::from("some_metric")),
767 ),
768 (
769 " +some_metric",
770 Expr::from(VectorSelector::from("some_metric")),
771 ),
772 ];
773 assert_cases(Case::new_expr_cases(cases));
774
775 let cases = vec![
776 (r#"-"string""#, "unary expression only allowed on expressions of type scalar or vector, got: string"),
777 ("-test[5m]", "unary expression only allowed on expressions of type scalar or vector, got: matrix"),
778 (r#"-"foo""#, "unary expression only allowed on expressions of type scalar or vector, got: string"),
779 ];
780 assert_cases(Case::new_fail_cases(cases));
781 }
782
783 #[test]
784 fn test_vector_selector() {
785 let cases = vec![
786 ("foo", Ok(Expr::from(VectorSelector::from("foo")))),
787 ("min", Ok(Expr::from(VectorSelector::from("min")))),
788 (
789 "foo offset 5m",
790 Expr::from(VectorSelector::from("foo"))
791 .offset_expr(Offset::Pos(Duration::from_secs(60 * 5))),
792 ),
793 (
794 "foo offset -7m",
795 Expr::from(VectorSelector::from("foo"))
796 .offset_expr(Offset::Neg(Duration::from_secs(60 * 7))),
797 ),
798 (
799 "foo OFFSET 1h30m",
800 Expr::from(VectorSelector::from("foo"))
801 .offset_expr(Offset::Pos(Duration::from_secs(60 * 90))),
802 ),
803 (
804 "foo OFFSET 1h30ms",
805 Expr::from(VectorSelector::from("foo")).offset_expr(Offset::Pos(
806 Duration::from_secs(60 * 60) + Duration::from_millis(30),
807 )),
808 ),
809 (
810 "foo @ 1603774568",
811 Expr::from(VectorSelector::from("foo"))
812 .at_expr(At::try_from(1603774568f64).unwrap()),
813 ),
814 (
815 "foo @ -100",
816 Expr::from(VectorSelector::from("foo")).at_expr(At::try_from(-100f64).unwrap()),
817 ),
818 (
819 "foo @ .3",
820 Expr::from(VectorSelector::from("foo")).at_expr(At::try_from(0.3f64).unwrap()),
821 ),
822 (
823 "foo @ 3.",
824 Expr::from(VectorSelector::from("foo")).at_expr(At::try_from(3.0f64).unwrap()),
825 ),
826 (
827 "foo @ 3.33",
828 Expr::from(VectorSelector::from("foo")).at_expr(At::try_from(3.33f64).unwrap()),
829 ),
830 (
831 "foo @ 3.3333",
832 Expr::from(VectorSelector::from("foo")).at_expr(At::try_from(3.333f64).unwrap()),
833 ),
834 (
835 "foo @ 3.3335",
836 Expr::from(VectorSelector::from("foo")).at_expr(At::try_from(3.334f64).unwrap()),
837 ),
838 (
839 "foo @ 3e2",
840 Expr::from(VectorSelector::from("foo")).at_expr(At::try_from(300f64).unwrap()),
841 ),
842 (
843 "foo @ 3e-1",
844 Expr::from(VectorSelector::from("foo")).at_expr(At::try_from(0.3f64).unwrap()),
845 ),
846 (
847 "foo @ 0xA",
848 Expr::from(VectorSelector::from("foo")).at_expr(At::try_from(10f64).unwrap()),
849 ),
850 (
851 "foo @ -3.3e1",
852 Expr::from(VectorSelector::from("foo")).at_expr(At::try_from(-33f64).unwrap()),
853 ),
854 (r#"foo:bar{a="bc"}"#, {
855 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "a", "bc"));
856 Expr::new_vector_selector(Some(String::from("foo:bar")), matchers)
857 }),
858 (r#"foo{NaN='bc'}"#, {
859 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "NaN", "bc"));
860 Expr::new_vector_selector(Some(String::from("foo")), matchers)
861 }),
862 (r#"foo{bar='}'}"#, {
863 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "bar", "}"));
864 Expr::new_vector_selector(Some(String::from("foo")), matchers)
865 }),
866 (r#"foo{a="b", foo!="bar", test=~"test", bar!~"baz"}"#, {
867 let matchers = Matchers::new(vec![
868 Matcher::new(MatchOp::Equal, "a", "b"),
869 Matcher::new(MatchOp::NotEqual, "foo", "bar"),
870 Matcher::new_matcher(
871 token::T_EQL_REGEX,
872 String::from("test"),
873 String::from("test"),
874 )
875 .unwrap(),
876 Matcher::new_matcher(
877 token::T_NEQ_REGEX,
878 String::from("bar"),
879 String::from("baz"),
880 )
881 .unwrap(),
882 ]);
883 Expr::new_vector_selector(Some(String::from("foo")), matchers)
884 }),
885 (r#"foo{a="b", foo!="bar", test=~"test", bar!~"baz",}"#, {
886 let name = String::from("foo");
887 let matchers = Matchers::new(vec![
888 Matcher::new(MatchOp::Equal, "a", "b"),
889 Matcher::new(MatchOp::NotEqual, "foo", "bar"),
890 Matcher::new_matcher(
891 token::T_EQL_REGEX,
892 String::from("test"),
893 String::from("test"),
894 )
895 .unwrap(),
896 Matcher::new_matcher(
897 token::T_NEQ_REGEX,
898 String::from("bar"),
899 String::from("baz"),
900 )
901 .unwrap(),
902 ]);
903 Expr::new_vector_selector(Some(name), matchers)
904 }),
905 (r#"{__name__="foo",__name__="bar"}"#, {
907 let matchers = Matchers::new(vec![
908 Matcher::new(MatchOp::Equal, METRIC_NAME, "foo"),
909 Matcher::new(MatchOp::Equal, METRIC_NAME, "bar"),
910 ]);
911 Expr::new_vector_selector(None, matchers)
912 }),
913 (r#"{__name__=~"foo.+",__name__=~".*bar"}"#, {
914 let matchers = Matchers::new(vec![
915 Matcher::new_matcher(
916 token::T_EQL_REGEX,
917 String::from(METRIC_NAME),
918 String::from("foo.+"),
919 )
920 .unwrap(),
921 Matcher::new_matcher(
922 token::T_EQL_REGEX,
923 String::from(METRIC_NAME),
924 String::from(".*bar"),
925 )
926 .unwrap(),
927 ]);
928 Expr::new_vector_selector(None, matchers)
929 }),
930 (r#"foo:bar{a=~"bc{9}"}"#, {
931 let matchers = Matchers::one(Matcher::new(
932 MatchOp::Re(Regex::new("^(?:bc{9})$").unwrap()),
933 "a",
934 "bc{9}",
935 ));
936 Expr::new_vector_selector(Some(String::from("foo:bar")), matchers)
937 }),
938 (r#"foo:bar{a=~"bc{abc}"}"#, {
939 let matchers = Matchers::one(Matcher::new(
940 MatchOp::Re(Regex::new("^(?:bc\\{abc})$").unwrap()),
941 "a",
942 "bc{abc}",
943 ));
944 Expr::new_vector_selector(Some(String::from("foo:bar")), matchers)
945 }),
946 ];
947 assert_cases(Case::new_result_cases(cases));
948
949 let fail_cases = vec![
950 ("foo @ +Inf", "timestamp out of bounds for @ modifier: inf"),
951 ("foo @ -Inf", "timestamp out of bounds for @ modifier: -inf"),
952 ("foo @ NaN", "timestamp out of bounds for @ modifier: NaN"),
953 ("{", "unexpected end of input inside braces"),
954 ("}", "unexpected right brace '}'"),
955 ("some{", "unexpected end of input inside braces"),
956 ("some}", "unexpected right brace '}'"),
957 (
958 "some_metric{a=b}",
959 "unexpected identifier 'b' in label matching, expected string",
960 ),
961 (
962 r#"some_metric{a:b="b"}"#,
963 "unexpected character inside braces: ':'",
964 ),
965 (r#"foo{a*"b"}"#, "unexpected character inside braces: '*'"),
966 (r#"foo{a>="b"}"#, "unexpected character inside braces: '>'"),
967 (
972 "foo{gibberish}",
973 "invalid label matcher, expected label matching operator after 'gibberish'",
974 ),
975 ("foo{1}", "unexpected character inside braces: '1'"),
976 (
977 "{}",
978 "vector selector must contain at least one non-empty matcher",
979 ),
980 (
981 r#"{x=""}"#,
982 "vector selector must contain at least one non-empty matcher",
983 ),
984 (
985 r#"{x=~".*"}"#,
986 "vector selector must contain at least one non-empty matcher",
987 ),
988 (
989 r#"{x!~".+"}"#,
990 "vector selector must contain at least one non-empty matcher",
991 ),
992 (
993 r#"{x!="a"}"#,
994 "vector selector must contain at least one non-empty matcher",
995 ),
996 (
997 r#"foo{__name__="bar"}"#,
998 "metric name must not be set twice: 'foo' or 'bar'",
999 ),
1000 (
1001 "foo{__name__= =}",
1002 "unexpected '=' in label matching, expected string",
1003 ),
1004 (
1005 "foo{,}",
1006 r#"unexpected ',' in label matching, expected identifier or right_brace"#,
1007 ),
1008 (
1009 r#"foo{__name__ == "bar"}"#,
1010 "unexpected '=' in label matching, expected string",
1011 ),
1012 (
1013 r#"foo{__name__="bar" lol}"#,
1014 INVALID_QUERY_INFO,
1016 ),
1017 ];
1018 assert_cases(Case::new_fail_cases(fail_cases));
1019
1020 let fail_cases = vec![
1021 {
1022 let num = f64::MAX - 1f64;
1023 let input = format!("foo @ {num}");
1024 let expected = Err(format!("timestamp out of bounds for @ modifier: {num}"));
1025 Case { input, expected }
1026 },
1027 {
1028 let num = f64::MIN - 1f64;
1029 let input = format!("foo @ {num}");
1030 let expected = Err(format!("timestamp out of bounds for @ modifier: {num}"));
1031 Case { input, expected }
1032 },
1033 ];
1034 assert_cases(fail_cases);
1035 }
1036
1037 #[test]
1038 fn test_matrix_selector() {
1039 let cases = vec![
1040 (
1041 "test[5s]",
1042 Expr::new_matrix_selector(
1043 Expr::from(VectorSelector::from("test")),
1044 Duration::from_secs(5),
1045 ),
1046 ),
1047 (
1048 "test[5m]",
1049 Expr::new_matrix_selector(
1050 Expr::from(VectorSelector::from("test")),
1051 duration::MINUTE_DURATION * 5,
1052 ),
1053 ),
1054 (
1055 "test[5m30s]",
1056 Expr::new_matrix_selector(
1057 Expr::from(VectorSelector::from("test")),
1058 Duration::from_secs(330),
1059 ),
1060 ),
1061 (
1062 "test[5h] OFFSET 5m",
1063 Expr::new_matrix_selector(
1064 Expr::from(VectorSelector::from("test")),
1065 duration::HOUR_DURATION * 5,
1066 )
1067 .and_then(|ex| ex.offset_expr(Offset::Pos(duration::MINUTE_DURATION * 5))),
1068 ),
1069 (
1070 "test[5d] OFFSET 10s",
1071 Expr::new_matrix_selector(
1072 Expr::from(VectorSelector::from("test")),
1073 duration::DAY_DURATION * 5,
1074 )
1075 .and_then(|ex| ex.offset_expr(Offset::Pos(Duration::from_secs(10)))),
1076 ),
1077 (
1078 "test[5w] offset 2w",
1079 Expr::new_matrix_selector(
1080 Expr::from(VectorSelector::from("test")),
1081 duration::WEEK_DURATION * 5,
1082 )
1083 .and_then(|ex| ex.offset_expr(Offset::Pos(duration::WEEK_DURATION * 2))),
1084 ),
1085 (r#"test{a="b"}[5y] OFFSET 3d"#, {
1086 Expr::new_vector_selector(
1087 Some(String::from("test")),
1088 Matchers::one(Matcher::new(MatchOp::Equal, "a", "b")),
1089 )
1090 .and_then(|ex| Expr::new_matrix_selector(ex, duration::YEAR_DURATION * 5))
1091 .and_then(|ex| ex.offset_expr(Offset::Pos(duration::DAY_DURATION * 3)))
1092 }),
1093 (r#"test{a="b"}[5y] @ 1603774699"#, {
1094 Expr::new_vector_selector(
1095 Some(String::from("test")),
1096 Matchers::one(Matcher::new(MatchOp::Equal, "a", "b")),
1097 )
1098 .and_then(|ex| Expr::new_matrix_selector(ex, duration::YEAR_DURATION * 5))
1099 .and_then(|ex| ex.at_expr(At::try_from(1603774699_f64).unwrap()))
1100 }),
1101 ("foo[1]", {
1102 Expr::new_matrix_selector(
1103 Expr::from(VectorSelector::from("foo")),
1104 Duration::from_secs(1),
1105 )
1106 }),
1107 ("some_metric[5m] OFFSET 1", {
1108 Expr::new_matrix_selector(
1109 Expr::from(VectorSelector::from("some_metric")),
1110 duration::MINUTE_DURATION * 5,
1111 )
1112 .and_then(|ex| ex.offset_expr(Offset::Pos(Duration::from_secs(1))))
1113 }),
1114 ("some_metric[5m] @ 1m", {
1115 Expr::new_matrix_selector(
1116 Expr::from(VectorSelector::from("some_metric")),
1117 duration::MINUTE_DURATION * 5,
1118 )
1119 .and_then(|ex| {
1120 ex.at_expr(At::try_from(duration::MINUTE_DURATION.as_secs_f64()).unwrap())
1121 })
1122 }),
1123 ];
1124
1125 assert_cases(Case::new_result_cases(cases));
1126
1127 let fail_cases = vec![
1128 ("foo[5mm]", "bad number or duration syntax: 5mm"),
1129 ("foo[5m1]", "bad number or duration syntax: 5m1]"),
1130 ("foo[5m:1m1]", "bad number or duration syntax: 1m1]"),
1131 ("foo[5y1hs]", "not a valid duration string: 5y1hs"),
1132 ("foo[5m1h]", "not a valid duration string: 5m1h"),
1133 ("foo[5m1m]", "not a valid duration string: 5m1m"),
1134 ("foo[0m]", "duration must be greater than 0"),
1135 (
1136 r#"foo["5m"]"#,
1137 r#"unexpected character inside brackets: '"'"#,
1138 ),
1139 (r#"foo[]"#, "missing unit character in duration"),
1140 (
1141 "some_metric[5m] OFFSET 1mm",
1142 "bad number or duration syntax: 1mm",
1143 ),
1144 (
1145 "some_metric[5m] OFFSET",
1146 "unexpected end of input in offset, expected duration",
1147 ),
1148 (
1149 "some_metric OFFSET 1m[5m]",
1150 "no offset modifiers allowed before range",
1151 ),
1152 (
1153 "some_metric[5m] @",
1154 "unexpected end of input in @, expected timestamp",
1155 ),
1156 (
1157 "some_metric @ 1234 [5m]",
1158 "no @ modifiers allowed before range",
1159 ),
1160 (
1161 "(foo + bar)[5m]",
1162 "ranges only allowed for vector selectors",
1163 ),
1164 ];
1165 assert_cases(Case::new_fail_cases(fail_cases));
1166 }
1167
1168 #[test]
1169 fn test_aggregation_expr() {
1170 let cases = vec![
1171 ("sum by (foo) (some_metric)", {
1172 let ex = Expr::from(VectorSelector::from("some_metric"));
1173 let modifier = LabelModifier::include(vec!["foo"]);
1174 Expr::new_aggregate_expr(token::T_SUM, Some(modifier), FunctionArgs::new_args(ex))
1175 }),
1176 ("avg by (foo)(some_metric)", {
1177 let ex = Expr::from(VectorSelector::from("some_metric"));
1178 let modifier = LabelModifier::include(vec!["foo"]);
1179 Expr::new_aggregate_expr(token::T_AVG, Some(modifier), FunctionArgs::new_args(ex))
1180 }),
1181 ("max by (foo)(some_metric)", {
1182 let modifier = LabelModifier::include(vec!["foo"]);
1183 let ex = Expr::from(VectorSelector::from("some_metric"));
1184 Expr::new_aggregate_expr(token::T_MAX, Some(modifier), FunctionArgs::new_args(ex))
1185 }),
1186 ("sum without (foo) (some_metric)", {
1187 let modifier = LabelModifier::exclude(vec!["foo"]);
1188 let ex = Expr::from(VectorSelector::from("some_metric"));
1189 Expr::new_aggregate_expr(token::T_SUM, Some(modifier), FunctionArgs::new_args(ex))
1190 }),
1191 ("sum (some_metric) without (foo)", {
1192 let modifier = LabelModifier::exclude(vec!["foo"]);
1193 let ex = Expr::from(VectorSelector::from("some_metric"));
1194 Expr::new_aggregate_expr(token::T_SUM, Some(modifier), FunctionArgs::new_args(ex))
1195 }),
1196 ("stddev(some_metric)", {
1197 let ex = Expr::from(VectorSelector::from("some_metric"));
1198 Expr::new_aggregate_expr(token::T_STDDEV, None, FunctionArgs::new_args(ex))
1199 }),
1200 ("stdvar by (foo)(some_metric)", {
1201 let modifier = LabelModifier::include(vec!["foo"]);
1202 let ex = Expr::from(VectorSelector::from("some_metric"));
1203 Expr::new_aggregate_expr(
1204 token::T_STDVAR,
1205 Some(modifier),
1206 FunctionArgs::new_args(ex),
1207 )
1208 }),
1209 ("sum by ()(some_metric)", {
1210 let modifier = LabelModifier::include(vec![]);
1211 let ex = Expr::from(VectorSelector::from("some_metric"));
1212 Expr::new_aggregate_expr(token::T_SUM, Some(modifier), FunctionArgs::new_args(ex))
1213 }),
1214 ("sum by (foo,bar,)(some_metric)", {
1215 let modifier = LabelModifier::include(vec!["foo", "bar"]);
1216 let ex = Expr::from(VectorSelector::from("some_metric"));
1217 Expr::new_aggregate_expr(token::T_SUM, Some(modifier), FunctionArgs::new_args(ex))
1218 }),
1219 ("sum by (foo,)(some_metric)", {
1220 let modifier = LabelModifier::include(vec!["foo"]);
1221 let ex = Expr::from(VectorSelector::from("some_metric"));
1222 Expr::new_aggregate_expr(token::T_SUM, Some(modifier), FunctionArgs::new_args(ex))
1223 }),
1224 ("topk(5, some_metric)", {
1225 let ex = Expr::from(VectorSelector::from("some_metric"));
1226 let param = Expr::from(5.0);
1227 let args = FunctionArgs::new_args(param).append_args(ex);
1228 Expr::new_aggregate_expr(token::T_TOPK, None, args)
1229 }),
1230 (r#"count_values("value", some_metric)"#, {
1231 let ex = Expr::from(VectorSelector::from("some_metric"));
1232 let param = Expr::from("value");
1233 let args = FunctionArgs::new_args(param).append_args(ex);
1234 Expr::new_aggregate_expr(token::T_COUNT_VALUES, None, args)
1235 }),
1236 (
1237 "sum without(and, by, avg, count, alert, annotations)(some_metric)",
1238 {
1239 let modifier = LabelModifier::exclude(vec![
1240 "and",
1241 "by",
1242 "avg",
1243 "count",
1244 "alert",
1245 "annotations",
1246 ]);
1247 let ex = Expr::from(VectorSelector::from("some_metric"));
1248 Expr::new_aggregate_expr(
1249 token::T_SUM,
1250 Some(modifier),
1251 FunctionArgs::new_args(ex),
1252 )
1253 },
1254 ),
1255 ("sum(sum)", {
1256 let ex = Expr::from(VectorSelector::from("sum"));
1257 Expr::new_aggregate_expr(token::T_SUM, None, FunctionArgs::new_args(ex))
1258 }),
1259 ("limitk by (group) (-1, http_requests)", {
1260 let ex = Expr::from(VectorSelector::from("http_requests"));
1261 let modifier = LabelModifier::include(vec!["group"]);
1262 let param = Expr::from(-1.0);
1263 let args = FunctionArgs::new_args(param).append_args(ex);
1264 Expr::new_aggregate_expr(token::T_LIMITK, Some(modifier), args)
1265 }),
1266 ("limitk by (group) (1, http_requests)", {
1267 let ex = Expr::from(VectorSelector::from("http_requests"));
1268 let modifier = LabelModifier::include(vec!["group"]);
1269 let param = Expr::from(1.0);
1270 let args = FunctionArgs::new_args(param).append_args(ex);
1271 Expr::new_aggregate_expr(token::T_LIMITK, Some(modifier), args)
1272 }),
1273 ("limit_ratio(-1.1, http_requests)", {
1274 let ex = Expr::from(VectorSelector::from("http_requests"));
1275 let param = Expr::from(-1.1);
1276 let args = FunctionArgs::new_args(param).append_args(ex);
1277 Expr::new_aggregate_expr(token::T_LIMIT_RATIO, None, args)
1278 }),
1279 ("limit_ratio(0.2, http_requests)", {
1280 let ex = Expr::from(VectorSelector::from("http_requests"));
1281 let param = Expr::from(0.2);
1282 let args = FunctionArgs::new_args(param).append_args(ex);
1283 Expr::new_aggregate_expr(token::T_LIMIT_RATIO, None, args)
1284 }),
1285 ];
1286 assert_cases(Case::new_result_cases(cases));
1287
1288 let fail_cases = vec![
1289 ("sum without(==)(some_metric)", INVALID_QUERY_INFO),
1290 ("sum without(,)(some_metric)", INVALID_QUERY_INFO),
1291 ("sum without(foo,,)(some_metric)", INVALID_QUERY_INFO),
1292 ("sum some_metric by (test)", INVALID_QUERY_INFO),
1293 ("sum (some_metric) by test", INVALID_QUERY_INFO),
1294 (
1295 "sum () by (test)",
1296 "no arguments for aggregate expression 'sum' provided",
1297 ),
1298 ("MIN keep_common (some_metric)", INVALID_QUERY_INFO),
1299 ("MIN (some_metric) keep_common", INVALID_QUERY_INFO),
1300 ("sum (some_metric) without (test) by (test)", INVALID_QUERY_INFO),
1301 ("sum without (test) (some_metric) by (test)", INVALID_QUERY_INFO),
1302 (
1303 "topk(some_metric)",
1304 "wrong number of arguments for aggregate expression provided, expected 2, got 1",
1305 ),
1306 (
1307 "topk(some_metric,)",
1308 "trailing commas not allowed in function call args",
1309 ),
1310 (
1311 "topk(some_metric, other_metric)",
1312 "expected type scalar in aggregation expression, got vector",
1313 ),
1314 (
1315 "count_values(5, other_metric)",
1316 "expected type string in aggregation expression, got scalar",
1317 ),
1318 (
1319 "rate(some_metric[5m]) @ 1234",
1320 "@ modifier must be preceded by an vector selector or matrix selector or a subquery"
1321 ),
1322 ];
1323 assert_cases(Case::new_fail_cases(fail_cases));
1324 }
1325
1326 #[test]
1327 fn test_function_call() {
1328 let cases = vec![
1329 (
1330 "time()",
1331 Expr::new_call(get_function("time").unwrap(), FunctionArgs::empty_args()),
1332 ),
1333 (r#"floor(some_metric{foo!="bar"})"#, {
1334 let name = String::from("some_metric");
1335 let matchers = Matchers::one(Matcher::new(MatchOp::NotEqual, "foo", "bar"));
1336 let ex = Expr::new_vector_selector(Some(name), matchers).unwrap();
1337 Expr::new_call(get_function("floor").unwrap(), FunctionArgs::new_args(ex))
1338 }),
1339 ("rate(some_metric[5m])", {
1340 Expr::new_matrix_selector(
1341 Expr::from(VectorSelector::from("some_metric")),
1342 duration::MINUTE_DURATION * 5,
1343 )
1344 .and_then(|ex| {
1345 Expr::new_call(get_function("rate").unwrap(), FunctionArgs::new_args(ex))
1346 })
1347 }),
1348 ("round(some_metric)", {
1349 let ex = Expr::from(VectorSelector::from("some_metric"));
1350 Expr::new_call(get_function("round").unwrap(), FunctionArgs::new_args(ex))
1351 }),
1352 ("round(some_metric, 5)", {
1353 let ex = Expr::from(VectorSelector::from("some_metric"));
1354 Expr::new_call(
1355 get_function("round").unwrap(),
1356 FunctionArgs::new_args(ex).append_args(Expr::from(5.0)),
1357 )
1358 }),
1359 ("max_of(1, 2)", {
1360 Expr::new_call(
1361 get_function("max_of").unwrap(),
1362 FunctionArgs::new_args(Expr::from(1.0)).append_args(Expr::from(2.0)),
1363 )
1364 }),
1365 ("min_of(1, 2)", {
1366 Expr::new_call(
1367 get_function("min_of").unwrap(),
1368 FunctionArgs::new_args(Expr::from(1.0)).append_args(Expr::from(2.0)),
1369 )
1370 }),
1371 ("double_exponential_smoothing(some_metric[5m], 0.5, 0.1)", {
1372 Expr::new_matrix_selector(
1373 Expr::from(VectorSelector::from("some_metric")),
1374 duration::MINUTE_DURATION * 5,
1375 )
1376 .and_then(|ex| {
1377 Expr::new_call(
1378 get_function("double_exponential_smoothing").unwrap(),
1379 FunctionArgs::new_args(ex)
1380 .append_args(Expr::from(0.5))
1381 .append_args(Expr::from(0.1)),
1382 )
1383 })
1384 }),
1385 (r#"absent(nonexistent{job="myjob"})"#, {
1387 let name = String::from("nonexistent");
1388 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "job", "myjob"));
1389 let ex = Expr::new_vector_selector(Some(name), matchers).unwrap();
1390 Expr::new_call(get_function("absent").unwrap(), FunctionArgs::new_args(ex))
1391 }),
1392 (r#"absent(nonexistent{job="myjob",instance=~".*"})"#, {
1393 let name = String::from("nonexistent");
1394 let matchers = Matchers::new(vec![
1395 Matcher::new(MatchOp::Equal, "job", "myjob"),
1396 Matcher::new(
1397 MatchOp::Re(Regex::new("^(?:.*)$").unwrap()),
1398 "instance",
1399 ".*",
1400 ),
1401 ]);
1402 Expr::new_vector_selector(Some(name), matchers).and_then(|ex| {
1403 Expr::new_call(get_function("absent").unwrap(), FunctionArgs::new_args(ex))
1404 })
1405 }),
1406 (r#"absent(sum(nonexistent{job="myjob"}))"#, {
1407 let name = String::from("nonexistent");
1408 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "job", "myjob"));
1409 Expr::new_vector_selector(Some(name), matchers)
1410 .and_then(|ex| {
1411 Expr::new_aggregate_expr(token::T_SUM, None, FunctionArgs::new_args(ex))
1412 })
1413 .and_then(|ex| {
1414 Expr::new_call(get_function("absent").unwrap(), FunctionArgs::new_args(ex))
1415 })
1416 }),
1417 (r#"absent_over_time(nonexistent{job="myjob"}[1h])"#, {
1418 let name = String::from("nonexistent");
1419 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "job", "myjob"));
1420 Expr::new_vector_selector(Some(name), matchers)
1421 .and_then(|ex| Expr::new_matrix_selector(ex, duration::HOUR_DURATION))
1422 .and_then(|ex| {
1423 Expr::new_call(
1424 get_function("absent_over_time").unwrap(),
1425 FunctionArgs::new_args(ex),
1426 )
1427 })
1428 }),
1429 (
1430 r#"absent_over_time(nonexistent{job="myjob",instance=~".*"}[1h])"#,
1431 {
1432 let name = String::from("nonexistent");
1433 let matchers = Matchers::new(vec![
1434 Matcher::new(MatchOp::Equal, "job", "myjob"),
1435 Matcher::new(
1436 MatchOp::Re(Regex::new("^(?:.*)$").unwrap()),
1437 "instance",
1438 ".*",
1439 ),
1440 ]);
1441 Expr::new_vector_selector(Some(name), matchers)
1442 .and_then(|ex| Expr::new_matrix_selector(ex, duration::HOUR_DURATION))
1443 .and_then(|ex| {
1444 Expr::new_call(
1445 get_function("absent_over_time").unwrap(),
1446 FunctionArgs::new_args(ex),
1447 )
1448 })
1449 },
1450 ),
1451 (r#"delta(cpu_temp_celsius{host="zeus"}[2h])"#, {
1452 let name = String::from("cpu_temp_celsius");
1453 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "host", "zeus"));
1454 Expr::new_vector_selector(Some(name), matchers)
1455 .and_then(|ex| Expr::new_matrix_selector(ex, duration::HOUR_DURATION * 2))
1456 .and_then(|ex| {
1457 Expr::new_call(get_function("delta").unwrap(), FunctionArgs::new_args(ex))
1458 })
1459 }),
1460 (
1461 r#"histogram_count(rate(http_request_duration_seconds[10m]))"#,
1462 Expr::new_matrix_selector(
1463 Expr::from(VectorSelector::from("http_request_duration_seconds")),
1464 duration::MINUTE_DURATION * 10,
1465 )
1466 .and_then(|ex| {
1467 Expr::new_call(get_function("rate").unwrap(), FunctionArgs::new_args(ex))
1468 })
1469 .and_then(|ex| {
1470 Expr::new_call(
1471 get_function("histogram_count").unwrap(),
1472 FunctionArgs::new_args(ex),
1473 )
1474 }),
1475 ),
1476 (
1477 r#"histogram_sum(rate(http_request_duration_seconds[10m])) / histogram_count(rate(http_request_duration_seconds[10m]))"#,
1478 {
1479 let rate = Expr::new_matrix_selector(
1480 Expr::from(VectorSelector::from("http_request_duration_seconds")),
1481 duration::MINUTE_DURATION * 10,
1482 )
1483 .and_then(|ex| {
1484 Expr::new_call(get_function("rate").unwrap(), FunctionArgs::new_args(ex))
1485 })
1486 .unwrap();
1487 let lhs = Expr::new_call(
1488 get_function("histogram_sum").unwrap(),
1489 FunctionArgs::new_args(rate.clone()),
1490 )
1491 .unwrap();
1492 let rhs = Expr::new_call(
1493 get_function("histogram_count").unwrap(),
1494 FunctionArgs::new_args(rate),
1495 )
1496 .unwrap();
1497 Expr::new_binary_expr(lhs, token::T_DIV, None, rhs)
1498 },
1499 ),
1500 (
1501 r#"histogram_fraction(0, 0.2, rate(http_request_duration_seconds[1h]))"#,
1502 Expr::new_matrix_selector(
1503 Expr::from(VectorSelector::from("http_request_duration_seconds")),
1504 duration::HOUR_DURATION,
1505 )
1506 .and_then(|ex| {
1507 Expr::new_call(get_function("rate").unwrap(), FunctionArgs::new_args(ex))
1508 })
1509 .and_then(|ex| {
1510 Expr::new_call(
1511 get_function("histogram_fraction").unwrap(),
1512 FunctionArgs::new_args(Expr::from(0.0_f64))
1513 .append_args(Expr::from(0.2))
1514 .append_args(ex),
1515 )
1516 }),
1517 ),
1518 (
1519 r#"histogram_avg(rate(http_request_duration_seconds[10m]))"#,
1520 Expr::new_matrix_selector(
1521 Expr::from(VectorSelector::from("http_request_duration_seconds")),
1522 duration::MINUTE_DURATION * 10,
1523 )
1524 .and_then(|ex| {
1525 Expr::new_call(get_function("rate").unwrap(), FunctionArgs::new_args(ex))
1526 })
1527 .and_then(|ex| {
1528 Expr::new_call(
1529 get_function("histogram_avg").unwrap(),
1530 FunctionArgs::new_args(ex),
1531 )
1532 }),
1533 ),
1534 (
1535 r#"histogram_quantile(0.9, rate(http_request_duration_seconds_bucket[10m]))"#,
1536 Expr::new_matrix_selector(
1537 Expr::from(VectorSelector::from("http_request_duration_seconds_bucket")),
1538 duration::MINUTE_DURATION * 10,
1539 )
1540 .and_then(|ex| {
1541 Expr::new_call(get_function("rate").unwrap(), FunctionArgs::new_args(ex))
1542 })
1543 .and_then(|ex| {
1544 Expr::new_call(
1545 get_function("histogram_quantile").unwrap(),
1546 FunctionArgs::new_args(Expr::from(0.9_f64)).append_args(ex),
1547 )
1548 }),
1549 ),
1550 (
1551 r#"histogram_quantile(0.9, sum by (job, le) (rate(http_request_duration_seconds_bucket[10m])))"#,
1552 Expr::new_matrix_selector(
1553 Expr::from(VectorSelector::from("http_request_duration_seconds_bucket")),
1554 duration::MINUTE_DURATION * 10,
1555 )
1556 .and_then(|ex| {
1557 Expr::new_call(get_function("rate").unwrap(), FunctionArgs::new_args(ex))
1558 })
1559 .and_then(|ex| {
1560 Expr::new_aggregate_expr(
1561 token::T_SUM,
1562 Some(LabelModifier::include(vec!["job", "le"])),
1563 FunctionArgs::new_args(ex),
1564 )
1565 })
1566 .and_then(|ex| {
1567 Expr::new_call(
1568 get_function("histogram_quantile").unwrap(),
1569 FunctionArgs::new_args(Expr::from(0.9_f64)).append_args(ex),
1570 )
1571 }),
1572 ),
1573 (
1574 r#"histogram_stddev(rate(http_request_duration_seconds[10m]))"#,
1575 Expr::new_matrix_selector(
1576 Expr::from(VectorSelector::from("http_request_duration_seconds")),
1577 duration::MINUTE_DURATION * 10,
1578 )
1579 .and_then(|ex| {
1580 Expr::new_call(get_function("rate").unwrap(), FunctionArgs::new_args(ex))
1581 })
1582 .and_then(|ex| {
1583 Expr::new_call(
1584 get_function("histogram_stddev").unwrap(),
1585 FunctionArgs::new_args(ex),
1586 )
1587 }),
1588 ),
1589 (
1590 r#"histogram_stdvar(rate(http_request_duration_seconds[10m]))"#,
1591 Expr::new_matrix_selector(
1592 Expr::from(VectorSelector::from("http_request_duration_seconds")),
1593 duration::MINUTE_DURATION * 10,
1594 )
1595 .and_then(|ex| {
1596 Expr::new_call(get_function("rate").unwrap(), FunctionArgs::new_args(ex))
1597 })
1598 .and_then(|ex| {
1599 Expr::new_call(
1600 get_function("histogram_stdvar").unwrap(),
1601 FunctionArgs::new_args(ex),
1602 )
1603 }),
1604 ),
1605 (r#"increase(http_requests_total{job="api-server"}[5m])"#, {
1606 let name = String::from("http_requests_total");
1607 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "job", "api-server"));
1608 Expr::new_vector_selector(Some(name), matchers)
1609 .and_then(|ex| Expr::new_matrix_selector(ex, duration::MINUTE_DURATION * 5))
1610 .and_then(|ex| {
1611 Expr::new_call(
1612 get_function("increase").unwrap(),
1613 FunctionArgs::new_args(ex),
1614 )
1615 })
1616 }),
1617 (r#"irate(http_requests_total{job="api-server"}[5m])"#, {
1618 let name = String::from("http_requests_total");
1619 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "job", "api-server"));
1620 Expr::new_vector_selector(Some(name), matchers)
1621 .and_then(|ex| Expr::new_matrix_selector(ex, duration::MINUTE_DURATION * 5))
1622 .and_then(|ex| {
1623 Expr::new_call(get_function("irate").unwrap(), FunctionArgs::new_args(ex))
1624 })
1625 }),
1626 (
1627 r#"label_join(up{job="api-server",src1="a",src2="b",src3="c"}, "foo", ",", "src1", "src2", "src3")"#,
1628 {
1629 let name = String::from("up");
1630 let matchers = Matchers::new(vec![
1631 Matcher::new(MatchOp::Equal, "job", "api-server"),
1632 Matcher::new(MatchOp::Equal, "src1", "a"),
1633 Matcher::new(MatchOp::Equal, "src2", "b"),
1634 Matcher::new(MatchOp::Equal, "src3", "c"),
1635 ]);
1636 Expr::new_vector_selector(Some(name), matchers).and_then(|ex| {
1637 Expr::new_call(
1638 get_function("label_join").unwrap(),
1639 FunctionArgs::new_args(ex)
1640 .append_args(Expr::from("foo"))
1641 .append_args(Expr::from(","))
1642 .append_args(Expr::from("src1"))
1643 .append_args(Expr::from("src2"))
1644 .append_args(Expr::from("src3")),
1645 )
1646 })
1647 },
1648 ),
1649 (
1650 r#"label_replace(up{job="api-server",service="a:c"}, "foo", "$1", "service", "(.*):.*")"#,
1651 {
1652 let name = String::from("up");
1653 let matchers = Matchers::new(vec![
1654 Matcher::new(MatchOp::Equal, "job", "api-server"),
1655 Matcher::new(MatchOp::Equal, "service", "a:c"),
1656 ]);
1657 Expr::new_vector_selector(Some(name), matchers).and_then(|ex| {
1658 Expr::new_call(
1659 get_function("label_replace").unwrap(),
1660 FunctionArgs::new_args(ex)
1661 .append_args(Expr::from("foo"))
1662 .append_args(Expr::from("$1"))
1663 .append_args(Expr::from("service"))
1664 .append_args(Expr::from("(.*):.*")),
1665 )
1666 })
1667 },
1668 ),
1669 (
1670 r#"sort_by_label(sum(up{job="api-server",src1="a",src2="b",src3="c"}) by (job), "src1","src2")"#,
1671 {
1672 let name = String::from("up");
1673 let matchers = Matchers::new(vec![
1674 Matcher::new(MatchOp::Equal, "job", "api-server"),
1675 Matcher::new(MatchOp::Equal, "src1", "a"),
1676 Matcher::new(MatchOp::Equal, "src2", "b"),
1677 Matcher::new(MatchOp::Equal, "src3", "c"),
1678 ]);
1679
1680 Expr::new_vector_selector(Some(name), matchers)
1681 .and_then(|ex| {
1682 let modifier = LabelModifier::include(vec!["job"]);
1683 Expr::new_aggregate_expr(
1684 token::T_SUM,
1685 Some(modifier),
1686 FunctionArgs::new_args(ex),
1687 )
1688 })
1689 .and_then(|ex| {
1690 Expr::new_call(
1691 get_function("sort_by_label").unwrap(),
1692 FunctionArgs::new_args(ex)
1693 .append_args(Expr::from("src1"))
1694 .append_args(Expr::from("src2")),
1695 )
1696 })
1697 },
1698 ),
1699 (
1700 r#"sort_by_label_desc(sum(up{job="api-server",src1="a",src2="b",src3="c"}) by (job), "src1","src2")"#,
1701 {
1702 let name = String::from("up");
1703 let matchers = Matchers::new(vec![
1704 Matcher::new(MatchOp::Equal, "job", "api-server"),
1705 Matcher::new(MatchOp::Equal, "src1", "a"),
1706 Matcher::new(MatchOp::Equal, "src2", "b"),
1707 Matcher::new(MatchOp::Equal, "src3", "c"),
1708 ]);
1709
1710 Expr::new_vector_selector(Some(name), matchers)
1711 .and_then(|ex| {
1712 let modifier = LabelModifier::include(vec!["job"]);
1713 Expr::new_aggregate_expr(
1714 token::T_SUM,
1715 Some(modifier),
1716 FunctionArgs::new_args(ex),
1717 )
1718 })
1719 .and_then(|ex| {
1720 Expr::new_call(
1721 get_function("sort_by_label_desc").unwrap(),
1722 FunctionArgs::new_args(ex)
1723 .append_args(Expr::from("src1"))
1724 .append_args(Expr::from("src2")),
1725 )
1726 })
1727 },
1728 ),
1729 (
1731 r#"exp(+Inf)"#,
1732 Expr::new_call(
1733 get_function("exp").unwrap(),
1734 FunctionArgs::new_args(Expr::from(f64::INFINITY)),
1735 ),
1736 ),
1737 (
1738 r#"exp(NaN)"#,
1739 Expr::new_call(
1740 get_function("exp").unwrap(),
1741 FunctionArgs::new_args(Expr::from(f64::NAN)),
1742 ),
1743 ),
1744 (
1745 r#"ln(+Inf)"#,
1746 Expr::new_call(
1747 get_function("ln").unwrap(),
1748 FunctionArgs::new_args(Expr::from(f64::INFINITY)),
1749 ),
1750 ),
1751 (
1752 r#"ln(NaN)"#,
1753 Expr::new_call(
1754 get_function("ln").unwrap(),
1755 FunctionArgs::new_args(Expr::from(f64::NAN)),
1756 ),
1757 ),
1758 (
1759 r#"ln(0)"#,
1760 Expr::new_call(
1761 get_function("ln").unwrap(),
1762 FunctionArgs::new_args(Expr::from(0.0)),
1763 ),
1764 ),
1765 (
1766 r#"ln(-1)"#,
1767 Expr::new_call(
1768 get_function("ln").unwrap(),
1769 FunctionArgs::new_args(Expr::from(-1.0)),
1770 ),
1771 ),
1772 (
1773 r#"log2(+Inf)"#,
1774 Expr::new_call(
1775 get_function("log2").unwrap(),
1776 FunctionArgs::new_args(Expr::from(f64::INFINITY)),
1777 ),
1778 ),
1779 (
1780 r#"log2(NaN)"#,
1781 Expr::new_call(
1782 get_function("log2").unwrap(),
1783 FunctionArgs::new_args(Expr::from(f64::NAN)),
1784 ),
1785 ),
1786 (
1787 r#"log2(0)"#,
1788 Expr::new_call(
1789 get_function("log2").unwrap(),
1790 FunctionArgs::new_args(Expr::from(0.0)),
1791 ),
1792 ),
1793 (
1794 r#"log2(-1)"#,
1795 Expr::new_call(
1796 get_function("log2").unwrap(),
1797 FunctionArgs::new_args(Expr::from(-1.0)),
1798 ),
1799 ),
1800 (
1801 r#"log10(+Inf)"#,
1802 Expr::new_call(
1803 get_function("log10").unwrap(),
1804 FunctionArgs::new_args(Expr::from(f64::INFINITY)),
1805 ),
1806 ),
1807 (
1808 r#"log10(NaN)"#,
1809 Expr::new_call(
1810 get_function("log10").unwrap(),
1811 FunctionArgs::new_args(Expr::from(f64::NAN)),
1812 ),
1813 ),
1814 (
1815 r#"log10(0)"#,
1816 Expr::new_call(
1817 get_function("log10").unwrap(),
1818 FunctionArgs::new_args(Expr::from(0.0)),
1819 ),
1820 ),
1821 (
1822 r#"log10(-1)"#,
1823 Expr::new_call(
1824 get_function("log10").unwrap(),
1825 FunctionArgs::new_args(Expr::from(-1.0)),
1826 ),
1827 ),
1828 ];
1829
1830 assert_cases(Case::new_result_cases(cases));
1831
1832 let fail_cases = vec![
1833 (
1834 "floor()",
1835 "expected 1 argument(s) in call to 'floor', got 0",
1836 ),
1837 (
1838 "floor(some_metric, other_metric)",
1839 "expected 1 argument(s) in call to 'floor', got 2",
1840 ),
1841 (
1842 "floor(some_metric, 1)",
1843 "expected 1 argument(s) in call to 'floor', got 2",
1844 ),
1845 (
1846 "floor(1)",
1847 "expected type vector in call to function 'floor', got scalar",
1848 ),
1849 (
1850 "hour(some_metric, some_metric, some_metric)",
1851 "expected at most 1 argument(s) in call to 'hour', got 3",
1852 ),
1853 (
1854 "time(some_metric)",
1855 "expected 0 argument(s) in call to 'time', got 1",
1856 ),
1857 (
1858 "non_existent_function_far_bar()",
1859 "unknown function with name 'non_existent_function_far_bar'",
1860 ),
1861 (
1862 "rate(some_metric)",
1863 "expected type matrix in call to function 'rate', got vector",
1864 ),
1865 (
1866 "ln(1)",
1867 "expected type vector in call to function 'ln', got scalar",
1868 ),
1869 ("ln()", "expected 1 argument(s) in call to 'ln', got 0"),
1870 (
1871 "exp(1)",
1872 "expected type vector in call to function 'exp', got scalar",
1873 ),
1874 ("exp()", "expected 1 argument(s) in call to 'exp', got 0"),
1875 (
1876 "label_join()",
1877 "expected at least 3 argument(s) in call to 'label_join', got 0",
1878 ),
1879 (
1880 "sort_by_label()",
1881 "expected at least 1 argument(s) in call to 'sort_by_label', got 0",
1882 ),
1883 (
1884 "sort_by_label_desc()",
1885 "expected at least 1 argument(s) in call to 'sort_by_label_desc', got 0",
1886 ),
1887 ];
1889 assert_cases(Case::new_fail_cases(fail_cases));
1890 }
1891
1892 #[test]
1893 fn test_subquery() {
1894 let cases = vec![
1895 (r#"foo{bar="baz"}[10m:6s]"#, {
1896 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "bar", "baz"));
1897 Expr::new_vector_selector(Some(String::from("foo")), matchers).and_then(|ex| {
1898 Expr::new_subquery_expr(
1899 ex,
1900 duration::MINUTE_DURATION * 10,
1901 Some(duration::SECOND_DURATION * 6),
1902 )
1903 })
1904 }),
1905 (r#"foo{bar="baz"}[10m5s:1h6ms]"#, {
1906 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "bar", "baz"));
1907 Expr::new_vector_selector(Some(String::from("foo")), matchers).and_then(|ex| {
1908 Expr::new_subquery_expr(
1909 ex,
1910 duration::MINUTE_DURATION * 10 + duration::SECOND_DURATION * 5,
1911 Some(duration::HOUR_DURATION + duration::MILLI_DURATION * 6),
1912 )
1913 })
1914 }),
1915 ("foo[10m:]", {
1916 let ex = Expr::from(VectorSelector::from("foo"));
1917 Expr::new_subquery_expr(ex, duration::MINUTE_DURATION * 10, None)
1918 }),
1919 (r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:5s])"#, {
1920 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "bar", "baz"));
1921 Expr::new_vector_selector(Some(String::from("foo")), matchers)
1922 .and_then(|ex| Expr::new_matrix_selector(ex, Duration::from_secs(2)))
1923 .and_then(|ex| {
1924 Expr::new_call(get_function("rate").unwrap(), FunctionArgs::new_args(ex))
1925 })
1926 .and_then(|ex| {
1927 Expr::new_subquery_expr(
1928 ex,
1929 duration::MINUTE_DURATION * 5,
1930 Some(Duration::from_secs(5)),
1931 )
1932 })
1933 .and_then(|ex| {
1934 Expr::new_call(
1935 get_function("min_over_time").unwrap(),
1936 FunctionArgs::new_args(ex),
1937 )
1938 })
1939 }),
1940 (r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:])[4m:3s]"#, {
1941 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "bar", "baz"));
1942 Expr::new_vector_selector(Some(String::from("foo")), matchers)
1943 .and_then(|ex| Expr::new_matrix_selector(ex, Duration::from_secs(2)))
1944 .and_then(|ex| {
1945 Expr::new_call(get_function("rate").unwrap(), FunctionArgs::new_args(ex))
1946 })
1947 .and_then(|ex| Expr::new_subquery_expr(ex, duration::MINUTE_DURATION * 5, None))
1948 .and_then(|ex| {
1949 Expr::new_call(
1950 get_function("min_over_time").unwrap(),
1951 FunctionArgs::new_args(ex),
1952 )
1953 })
1954 .and_then(|ex| {
1955 Expr::new_subquery_expr(
1956 ex,
1957 duration::MINUTE_DURATION * 4,
1958 Some(Duration::from_secs(3)),
1959 )
1960 })
1961 }),
1962 (
1963 r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:] offset 4m)[4m:3s]"#,
1964 {
1965 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "bar", "baz"));
1966 Expr::new_vector_selector(Some(String::from("foo")), matchers)
1967 .and_then(|ex| Expr::new_matrix_selector(ex, Duration::from_secs(2)))
1968 .and_then(|ex| {
1969 Expr::new_call(
1970 get_function("rate").unwrap(),
1971 FunctionArgs::new_args(ex),
1972 )
1973 })
1974 .and_then(|ex| {
1975 Expr::new_subquery_expr(ex, duration::MINUTE_DURATION * 5, None)
1976 })
1977 .and_then(|ex| ex.offset_expr(Offset::Pos(duration::MINUTE_DURATION * 4)))
1978 .and_then(|ex| {
1979 Expr::new_call(
1980 get_function("min_over_time").unwrap(),
1981 FunctionArgs::new_args(ex),
1982 )
1983 })
1984 .and_then(|ex| {
1985 Expr::new_subquery_expr(
1986 ex,
1987 duration::MINUTE_DURATION * 4,
1988 Some(Duration::from_secs(3)),
1989 )
1990 })
1991 },
1992 ),
1993 (
1994 r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:] @ 1603775091)[4m:3s]"#,
1995 {
1996 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "bar", "baz"));
1997 Expr::new_vector_selector(Some(String::from("foo")), matchers)
1998 .and_then(|ex| Expr::new_matrix_selector(ex, Duration::from_secs(2)))
1999 .and_then(|ex| {
2000 Expr::new_call(
2001 get_function("rate").unwrap(),
2002 FunctionArgs::new_args(ex),
2003 )
2004 })
2005 .and_then(|ex| {
2006 Expr::new_subquery_expr(ex, duration::MINUTE_DURATION * 5, None)
2007 })
2008 .and_then(|ex| ex.at_expr(At::try_from(1603775091_f64).unwrap()))
2009 .and_then(|ex| {
2010 Expr::new_call(
2011 get_function("min_over_time").unwrap(),
2012 FunctionArgs::new_args(ex),
2013 )
2014 })
2015 .and_then(|ex| {
2016 Expr::new_subquery_expr(
2017 ex,
2018 duration::MINUTE_DURATION * 4,
2019 Some(Duration::from_secs(3)),
2020 )
2021 })
2022 },
2023 ),
2024 (
2025 r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:] @ -160377509)[4m:3s]"#,
2026 {
2027 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "bar", "baz"));
2028 Expr::new_vector_selector(Some(String::from("foo")), matchers)
2029 .and_then(|ex| Expr::new_matrix_selector(ex, Duration::from_secs(2)))
2030 .and_then(|ex| {
2031 Expr::new_call(
2032 get_function("rate").unwrap(),
2033 FunctionArgs::new_args(ex),
2034 )
2035 })
2036 .and_then(|ex| {
2037 Expr::new_subquery_expr(ex, duration::MINUTE_DURATION * 5, None)
2038 })
2039 .and_then(|ex| ex.at_expr(At::try_from(-160377509_f64).unwrap()))
2040 .and_then(|ex| {
2041 Expr::new_call(
2042 get_function("min_over_time").unwrap(),
2043 FunctionArgs::new_args(ex),
2044 )
2045 })
2046 .and_then(|ex| {
2047 Expr::new_subquery_expr(
2048 ex,
2049 duration::MINUTE_DURATION * 4,
2050 Some(Duration::from_secs(3)),
2051 )
2052 })
2053 },
2054 ),
2055 (
2056 "sum without(and, by, avg, count, alert, annotations)(some_metric) [30m:10s]",
2057 {
2058 let ex = Expr::from(VectorSelector::from("some_metric"));
2059 Expr::new_aggregate_expr(
2060 token::T_SUM,
2061 Some(LabelModifier::exclude(vec![
2062 "and",
2063 "by",
2064 "avg",
2065 "count",
2066 "alert",
2067 "annotations",
2068 ])),
2069 FunctionArgs::new_args(ex),
2070 )
2071 .and_then(|ex| {
2072 Expr::new_subquery_expr(
2073 ex,
2074 duration::MINUTE_DURATION * 30,
2075 Some(Duration::from_secs(10)),
2076 )
2077 })
2078 },
2079 ),
2080 (
2081 "some_metric OFFSET 1m [10m:5s]",
2082 Expr::from(VectorSelector::from("some_metric"))
2083 .offset_expr(Offset::Pos(duration::MINUTE_DURATION))
2084 .and_then(|ex| {
2085 Expr::new_subquery_expr(
2086 ex,
2087 duration::MINUTE_DURATION * 10,
2088 Some(Duration::from_secs(5)),
2089 )
2090 }),
2091 ),
2092 (
2093 "some_metric @ 123 [10m:5s]",
2094 Expr::from(VectorSelector::from("some_metric"))
2095 .at_expr(At::try_from(123_f64).unwrap())
2096 .and_then(|ex| {
2097 Expr::new_subquery_expr(
2098 ex,
2099 duration::MINUTE_DURATION * 10,
2100 Some(Duration::from_secs(5)),
2101 )
2102 }),
2103 ),
2104 (
2105 "some_metric @ 123 offset 1m [10m:5s]",
2106 Expr::from(VectorSelector::from("some_metric"))
2107 .at_expr(At::try_from(123_f64).unwrap())
2108 .and_then(|ex| ex.offset_expr(Offset::Pos(duration::MINUTE_DURATION)))
2109 .and_then(|ex| {
2110 Expr::new_subquery_expr(
2111 ex,
2112 duration::MINUTE_DURATION * 10,
2113 Some(Duration::from_secs(5)),
2114 )
2115 }),
2116 ),
2117 (
2118 "some_metric offset 1m @ 123 [10m:5s]",
2119 Expr::from(VectorSelector::from("some_metric"))
2120 .at_expr(At::try_from(123_f64).unwrap())
2121 .and_then(|ex| ex.offset_expr(Offset::Pos(duration::MINUTE_DURATION)))
2122 .and_then(|ex| {
2123 Expr::new_subquery_expr(
2124 ex,
2125 duration::MINUTE_DURATION * 10,
2126 Some(Duration::from_secs(5)),
2127 )
2128 }),
2129 ),
2130 (
2131 "some_metric[10m:5s] offset 1m @ 123",
2132 Expr::new_subquery_expr(
2133 Expr::from(VectorSelector::from("some_metric")),
2134 duration::MINUTE_DURATION * 10,
2135 Some(Duration::from_secs(5)),
2136 )
2137 .and_then(|ex| ex.at_expr(At::try_from(123_f64).unwrap()))
2138 .and_then(|ex| ex.offset_expr(Offset::Pos(duration::MINUTE_DURATION))),
2139 ),
2140 (r#"(foo + bar{nm="val"})[5m:]"#, {
2141 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "nm", "val"));
2142 Expr::new_binary_expr(
2143 Expr::from(VectorSelector::from("foo")),
2144 token::T_ADD,
2145 None,
2146 Expr::new_vector_selector(Some(String::from("bar")), matchers).unwrap(),
2147 )
2148 .and_then(Expr::new_paren_expr)
2149 .and_then(|ex| Expr::new_subquery_expr(ex, duration::MINUTE_DURATION * 5, None))
2150 }),
2151 (r#"(foo + bar{nm="val"})[5m:] offset 10m"#, {
2152 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "nm", "val"));
2153 Expr::new_binary_expr(
2154 Expr::from(VectorSelector::from("foo")),
2155 token::T_ADD,
2156 None,
2157 Expr::new_vector_selector(Some(String::from("bar")), matchers).unwrap(),
2158 )
2159 .and_then(Expr::new_paren_expr)
2160 .and_then(|ex| Expr::new_subquery_expr(ex, duration::MINUTE_DURATION * 5, None))
2161 .and_then(|ex| ex.offset_expr(Offset::Pos(duration::MINUTE_DURATION * 10)))
2162 }),
2163 (r#"(foo + bar{nm="val"} @ 1234)[5m:] @ 1603775019"#, {
2164 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "nm", "val"));
2165 let rhs = Expr::new_vector_selector(Some(String::from("bar")), matchers)
2166 .and_then(|ex| ex.at_expr(At::try_from(1234_f64).unwrap()))
2167 .unwrap();
2168
2169 Expr::new_binary_expr(
2170 Expr::from(VectorSelector::from("foo")),
2171 token::T_ADD,
2172 None,
2173 rhs,
2174 )
2175 .and_then(Expr::new_paren_expr)
2176 .and_then(|ex| Expr::new_subquery_expr(ex, duration::MINUTE_DURATION * 5, None))
2177 .and_then(|ex| ex.at_expr(At::try_from(1603775019_f64).unwrap()))
2178 }),
2179 ];
2180 assert_cases(Case::new_result_cases(cases));
2181
2182 let fail_cases = vec![
2183 (
2184 "test[5d] OFFSET 10s [10m:5s]",
2185 "subquery is only allowed on vector, got matrix instead",
2186 ),
2187 (
2188 r#"(foo + bar{nm="val"})[5m:][10m:5s]"#,
2189 "subquery is only allowed on vector, got matrix instead",
2190 ),
2191 (
2192 "rate(food[1m])[1h] offset 1h",
2193 "ranges only allowed for vector selectors",
2194 ),
2195 (
2196 "rate(food[1m])[1h] @ 100",
2197 "ranges only allowed for vector selectors",
2198 ),
2199 ];
2200 assert_cases(Case::new_fail_cases(fail_cases));
2201 }
2202
2203 #[test]
2204 fn test_preprocessors() {
2205 let cases = vec![
2206 (
2207 "foo @ start()",
2208 Expr::from(VectorSelector::from("foo")).at_expr(At::Start),
2209 ),
2210 (
2211 "foo @ end()",
2212 Expr::from(VectorSelector::from("foo")).at_expr(At::End),
2213 ),
2214 (
2215 "test[5y] @ start()",
2216 Expr::new_matrix_selector(
2217 Expr::from(VectorSelector::from("test")),
2218 duration::YEAR_DURATION * 5,
2219 )
2220 .and_then(|ex| ex.at_expr(At::Start)),
2221 ),
2222 (
2223 "test[5y] @ end()",
2224 Expr::new_matrix_selector(
2225 Expr::from(VectorSelector::from("test")),
2226 duration::YEAR_DURATION * 5,
2227 )
2228 .and_then(|ex| ex.at_expr(At::End)),
2229 ),
2230 (
2231 "foo[10m:6s] @ start()",
2232 Expr::new_subquery_expr(
2233 Expr::from(VectorSelector::from("foo")),
2234 duration::MINUTE_DURATION * 10,
2235 Some(Duration::from_secs(6)),
2236 )
2237 .and_then(|ex| ex.at_expr(At::Start)),
2238 ),
2239 ("start", Ok(Expr::from(VectorSelector::from("start")))),
2241 ("end", Ok(Expr::from(VectorSelector::from("end")))),
2242 (r#"start{end="foo"}"#, {
2243 let name = String::from("start");
2244 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "end", "foo"));
2245 Expr::new_vector_selector(Some(name), matchers)
2246 }),
2247 (r#"end{start="foo"}"#, {
2248 let name = String::from("end");
2249 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "start", "foo"));
2250 Expr::new_vector_selector(Some(name), matchers)
2251 }),
2252 ("foo unless on(start) bar", {
2253 let modifier = BinModifier::default()
2254 .with_matching(Some(LabelModifier::include(vec!["start"])))
2255 .with_card(VectorMatchCardinality::ManyToMany);
2256 Expr::new_binary_expr(
2257 Expr::from(VectorSelector::from("foo")),
2258 token::T_LUNLESS,
2259 Some(modifier),
2260 Expr::from(VectorSelector::from("bar")),
2261 )
2262 }),
2263 ("foo unless on(end) bar", {
2264 let modifier = BinModifier::default()
2265 .with_matching(Some(LabelModifier::include(vec!["end"])))
2266 .with_card(VectorMatchCardinality::ManyToMany);
2267 Expr::new_binary_expr(
2268 Expr::from(VectorSelector::from("foo")),
2269 token::T_LUNLESS,
2270 Some(modifier),
2271 Expr::from(VectorSelector::from("bar")),
2272 )
2273 }),
2274 ];
2275 assert_cases(Case::new_result_cases(cases));
2276
2277 let cases = vec![
2278 ("start()", INVALID_QUERY_INFO),
2279 ("end()", INVALID_QUERY_INFO),
2280 ];
2281 assert_cases(Case::new_fail_cases(cases));
2282 }
2283
2284 #[test]
2285 fn test_corner_fail_cases() {
2286 let fail_cases = vec![
2287 ("", "no expression found in input"),
2288 (
2289 "# just a comment\n\n",
2290 "no expression found in input",
2291 ),
2292 ("1+", INVALID_QUERY_INFO),
2293 (".", "unexpected character: '.'"),
2294 ("2.5.", "bad number or duration syntax: 2.5."),
2295 ("100..4", "bad number or duration syntax: 100.."),
2296 ("0deadbeef", "bad number or duration syntax: 0de"),
2297 ("1 /", INVALID_QUERY_INFO),
2298 ("*1", INVALID_QUERY_INFO),
2299 ("(1))", "unexpected right parenthesis ')'"),
2300 ("((1)", "unclosed left parenthesis"),
2301 ("(", "unclosed left parenthesis"),
2302 ("1 !~ 1", "unexpected character after '!': '~'"),
2303 ("1 =~ 1", "unexpected character after '=': '~'"),
2304 ("*test", INVALID_QUERY_INFO),
2305 (
2306 "1 offset 1d",
2307 "offset modifier must be preceded by an vector selector or matrix selector or a subquery"
2308 ),
2309 (
2310 "foo offset 1s offset 2s",
2311 "offset may not be set multiple times"
2312 ),
2313 ("a - on(b) ignoring(c) d", INVALID_QUERY_INFO),
2314
2315 ("-=", INVALID_QUERY_INFO),
2317 ("++-++-+-+-<", INVALID_QUERY_INFO),
2318 ("e-+=/(0)", INVALID_QUERY_INFO),
2319 ("a>b()", "unknown function with name 'b'"),
2320 (
2321 "rate(avg)",
2322 "expected type matrix in call to function 'rate', got vector"
2323 ),
2324 ];
2325 assert_cases(Case::new_fail_cases(fail_cases));
2326
2327 let fail_cases = vec![
2328 {
2330 let input = "(".to_string() + &"-{}-1".repeat(10_000) + ")" + &"[1m:]".repeat(1000);
2331 let expected =
2332 Err("vector selector must contain at least one non-empty matcher".into());
2333 Case { input, expected }
2334 },
2335 ];
2336 assert_cases(fail_cases);
2337 }
2338
2339 #[test]
2340 fn test_or_filters() {
2341 let cases = vec![
2342 (r#"foo{label1="1" or label1="2"}"#, {
2343 let matchers = Matchers::new(vec![]).with_or_matchers(vec![
2344 vec![Matcher::new(MatchOp::Equal, "label1", "1")],
2345 vec![Matcher::new(MatchOp::Equal, "label1", "2")],
2346 ]);
2347 Expr::new_vector_selector(Some(String::from("foo")), matchers)
2348 }),
2349 (r#"foo{label1="1" OR label1="2"}"#, {
2350 let matchers = Matchers::new(vec![]).with_or_matchers(vec![
2351 vec![Matcher::new(MatchOp::Equal, "label1", "1")],
2352 vec![Matcher::new(MatchOp::Equal, "label1", "2")],
2353 ]);
2354 Expr::new_vector_selector(Some(String::from("foo")), matchers)
2355 }),
2356 (r#"foo{label1="1" Or label1="2"}"#, {
2357 let matchers = Matchers::new(vec![]).with_or_matchers(vec![
2358 vec![Matcher::new(MatchOp::Equal, "label1", "1")],
2359 vec![Matcher::new(MatchOp::Equal, "label1", "2")],
2360 ]);
2361 Expr::new_vector_selector(Some(String::from("foo")), matchers)
2362 }),
2363 (r#"foo{label1="1" oR label1="2"}"#, {
2364 let matchers = Matchers::new(vec![]).with_or_matchers(vec![
2365 vec![Matcher::new(MatchOp::Equal, "label1", "1")],
2366 vec![Matcher::new(MatchOp::Equal, "label1", "2")],
2367 ]);
2368 Expr::new_vector_selector(Some(String::from("foo")), matchers)
2369 }),
2370 (r#"foo{label1="1" or or="or"}"#, {
2371 let matchers = Matchers::new(vec![]).with_or_matchers(vec![
2372 vec![Matcher::new(MatchOp::Equal, "label1", "1")],
2373 vec![Matcher::new(MatchOp::Equal, "or", "or")],
2374 ]);
2375 Expr::new_vector_selector(Some(String::from("foo")), matchers)
2376 }),
2377 (
2378 r#"foo{label1="1" or label1="2" or label1="3" or label1="4"}"#,
2379 {
2380 let matchers = Matchers::new(vec![]).with_or_matchers(vec![
2381 vec![Matcher::new(MatchOp::Equal, "label1", "1")],
2382 vec![Matcher::new(MatchOp::Equal, "label1", "2")],
2383 vec![Matcher::new(MatchOp::Equal, "label1", "3")],
2384 vec![Matcher::new(MatchOp::Equal, "label1", "4")],
2385 ]);
2386 Expr::new_vector_selector(Some(String::from("foo")), matchers)
2387 },
2388 ),
2389 (
2390 r#"foo{label1="1" or label1="2" or label1="3", label2="4"}"#,
2391 {
2392 let matchers = Matchers::new(vec![]).with_or_matchers(vec![
2393 vec![Matcher::new(MatchOp::Equal, "label1", "1")],
2394 vec![Matcher::new(MatchOp::Equal, "label1", "2")],
2395 vec![
2396 Matcher::new(MatchOp::Equal, "label1", "3"),
2397 Matcher::new(MatchOp::Equal, "label2", "4"),
2398 ],
2399 ]);
2400 Expr::new_vector_selector(Some(String::from("foo")), matchers)
2401 },
2402 ),
2403 (
2404 r#"foo{label1="1", label2="2" or label1="3" or label1="4"}"#,
2405 {
2406 let matchers = Matchers::new(vec![]).with_or_matchers(vec![
2407 vec![
2408 Matcher::new(MatchOp::Equal, "label1", "1"),
2409 Matcher::new(MatchOp::Equal, "label2", "2"),
2410 ],
2411 vec![Matcher::new(MatchOp::Equal, "label1", "3")],
2412 vec![Matcher::new(MatchOp::Equal, "label1", "4")],
2413 ]);
2414 Expr::new_vector_selector(Some(String::from("foo")), matchers)
2415 },
2416 ),
2417 ];
2418 assert_cases(Case::new_result_cases(cases));
2419
2420 let display_cases = [
2421 r#"a{label1="1"}"#,
2422 r#"a{label1="1" or label2="2"}"#,
2423 r#"a{label1="1" or label2="2" or label3="3" or label4="4"}"#,
2424 r#"a{label1="1", label2="2" or label3="3" or label4="4"}"#,
2425 r#"a{label1="1", label2="2" or label3="3", label4="4"}"#,
2426 ];
2427 display_cases
2428 .iter()
2429 .for_each(|expr| assert_eq!(parser::parse(expr).unwrap().to_string(), *expr));
2430
2431 let or_insensitive_cases = [
2432 r#"a{label1="1" or label2="2"}"#,
2433 r#"a{label1="1" OR label2="2"}"#,
2434 r#"a{label1="1" Or label2="2"}"#,
2435 r#"a{label1="1" oR label2="2"}"#,
2436 ];
2437
2438 or_insensitive_cases.iter().for_each(|expr| {
2439 assert_eq!(
2440 parser::parse(expr).unwrap().to_string(),
2441 r#"a{label1="1" or label2="2"}"#
2442 )
2443 });
2444
2445 let fail_cases = vec![
2446 (
2447 r#"foo{or}"#,
2448 r#"invalid label matcher, expected label matching operator after 'or'"#,
2449 ),
2450 (r#"foo{label1="1" or}"#, INVALID_QUERY_INFO),
2451 (r#"foo{or label1="1"}"#, INVALID_QUERY_INFO),
2452 (r#"foo{label1="1" or or label2="2"}"#, INVALID_QUERY_INFO),
2453 ];
2454 assert_cases(Case::new_fail_cases(fail_cases));
2455 }
2456
2457 #[test]
2458 fn test_prom3_string_identifier() {
2459 let case = r#"{"some.metric"}"#;
2460 assert_eq!(
2461 parser::parse(case).unwrap(),
2462 parser::parse(r#"{__name__="some.metric"}"#).unwrap()
2463 );
2464
2465 let case = r#"some_metric{"service.name"="api-server"}"#;
2466 assert_eq!(
2467 parser::parse(case).unwrap(),
2468 Expr::new_vector_selector(
2469 Some("some_metric".to_string()),
2470 Matchers::one(Matcher::new(MatchOp::Equal, "service.name", "api-server"))
2471 )
2472 .unwrap()
2473 );
2474
2475 let case = r#"sum by ("foo")(some_metric{})"#;
2476 assert_eq!(
2477 parser::parse(case).unwrap(),
2478 parser::parse(r#"sum by (foo)(some_metric{})"#).unwrap()
2479 );
2480
2481 let case = r#"test{host=~"10\\.0\\.160\\.237:808|nonexistence"}"#;
2482 parser::parse(case).unwrap();
2483 assert!(parser::parse(case).is_ok());
2484 }
2485}