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 ("double_exponential_smoothing(some_metric[5m], 0.5, 0.1)", {
1360 Expr::new_matrix_selector(
1361 Expr::from(VectorSelector::from("some_metric")),
1362 duration::MINUTE_DURATION * 5,
1363 )
1364 .and_then(|ex| {
1365 Expr::new_call(
1366 get_function("double_exponential_smoothing").unwrap(),
1367 FunctionArgs::new_args(ex)
1368 .append_args(Expr::from(0.5))
1369 .append_args(Expr::from(0.1)),
1370 )
1371 })
1372 }),
1373 ("holt_winters(some_metric[5m], 0.5, 0.1)", {
1374 Expr::new_matrix_selector(
1375 Expr::from(VectorSelector::from("some_metric")),
1376 duration::MINUTE_DURATION * 5,
1377 )
1378 .and_then(|ex| {
1379 Expr::new_call(
1380 get_function("holt_winters").unwrap(),
1381 FunctionArgs::new_args(ex)
1382 .append_args(Expr::from(0.5))
1383 .append_args(Expr::from(0.1)),
1384 )
1385 })
1386 }),
1387 (r#"absent(nonexistent{job="myjob"})"#, {
1389 let name = String::from("nonexistent");
1390 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "job", "myjob"));
1391 let ex = Expr::new_vector_selector(Some(name), matchers).unwrap();
1392 Expr::new_call(get_function("absent").unwrap(), FunctionArgs::new_args(ex))
1393 }),
1394 (r#"absent(nonexistent{job="myjob",instance=~".*"})"#, {
1395 let name = String::from("nonexistent");
1396 let matchers = Matchers::new(vec![
1397 Matcher::new(MatchOp::Equal, "job", "myjob"),
1398 Matcher::new(
1399 MatchOp::Re(Regex::new("^(?:.*)$").unwrap()),
1400 "instance",
1401 ".*",
1402 ),
1403 ]);
1404 Expr::new_vector_selector(Some(name), matchers).and_then(|ex| {
1405 Expr::new_call(get_function("absent").unwrap(), FunctionArgs::new_args(ex))
1406 })
1407 }),
1408 (r#"absent(sum(nonexistent{job="myjob"}))"#, {
1409 let name = String::from("nonexistent");
1410 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "job", "myjob"));
1411 Expr::new_vector_selector(Some(name), matchers)
1412 .and_then(|ex| {
1413 Expr::new_aggregate_expr(token::T_SUM, None, FunctionArgs::new_args(ex))
1414 })
1415 .and_then(|ex| {
1416 Expr::new_call(get_function("absent").unwrap(), FunctionArgs::new_args(ex))
1417 })
1418 }),
1419 (r#"absent_over_time(nonexistent{job="myjob"}[1h])"#, {
1420 let name = String::from("nonexistent");
1421 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "job", "myjob"));
1422 Expr::new_vector_selector(Some(name), matchers)
1423 .and_then(|ex| Expr::new_matrix_selector(ex, duration::HOUR_DURATION))
1424 .and_then(|ex| {
1425 Expr::new_call(
1426 get_function("absent_over_time").unwrap(),
1427 FunctionArgs::new_args(ex),
1428 )
1429 })
1430 }),
1431 (
1432 r#"absent_over_time(nonexistent{job="myjob",instance=~".*"}[1h])"#,
1433 {
1434 let name = String::from("nonexistent");
1435 let matchers = Matchers::new(vec![
1436 Matcher::new(MatchOp::Equal, "job", "myjob"),
1437 Matcher::new(
1438 MatchOp::Re(Regex::new("^(?:.*)$").unwrap()),
1439 "instance",
1440 ".*",
1441 ),
1442 ]);
1443 Expr::new_vector_selector(Some(name), matchers)
1444 .and_then(|ex| Expr::new_matrix_selector(ex, duration::HOUR_DURATION))
1445 .and_then(|ex| {
1446 Expr::new_call(
1447 get_function("absent_over_time").unwrap(),
1448 FunctionArgs::new_args(ex),
1449 )
1450 })
1451 },
1452 ),
1453 (r#"delta(cpu_temp_celsius{host="zeus"}[2h])"#, {
1454 let name = String::from("cpu_temp_celsius");
1455 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "host", "zeus"));
1456 Expr::new_vector_selector(Some(name), matchers)
1457 .and_then(|ex| Expr::new_matrix_selector(ex, duration::HOUR_DURATION * 2))
1458 .and_then(|ex| {
1459 Expr::new_call(get_function("delta").unwrap(), FunctionArgs::new_args(ex))
1460 })
1461 }),
1462 (
1463 r#"histogram_count(rate(http_request_duration_seconds[10m]))"#,
1464 Expr::new_matrix_selector(
1465 Expr::from(VectorSelector::from("http_request_duration_seconds")),
1466 duration::MINUTE_DURATION * 10,
1467 )
1468 .and_then(|ex| {
1469 Expr::new_call(get_function("rate").unwrap(), FunctionArgs::new_args(ex))
1470 })
1471 .and_then(|ex| {
1472 Expr::new_call(
1473 get_function("histogram_count").unwrap(),
1474 FunctionArgs::new_args(ex),
1475 )
1476 }),
1477 ),
1478 (
1479 r#"histogram_sum(rate(http_request_duration_seconds[10m])) / histogram_count(rate(http_request_duration_seconds[10m]))"#,
1480 {
1481 let rate = Expr::new_matrix_selector(
1482 Expr::from(VectorSelector::from("http_request_duration_seconds")),
1483 duration::MINUTE_DURATION * 10,
1484 )
1485 .and_then(|ex| {
1486 Expr::new_call(get_function("rate").unwrap(), FunctionArgs::new_args(ex))
1487 })
1488 .unwrap();
1489 let lhs = Expr::new_call(
1490 get_function("histogram_sum").unwrap(),
1491 FunctionArgs::new_args(rate.clone()),
1492 )
1493 .unwrap();
1494 let rhs = Expr::new_call(
1495 get_function("histogram_count").unwrap(),
1496 FunctionArgs::new_args(rate),
1497 )
1498 .unwrap();
1499 Expr::new_binary_expr(lhs, token::T_DIV, None, rhs)
1500 },
1501 ),
1502 (
1503 r#"histogram_fraction(0, 0.2, rate(http_request_duration_seconds[1h]))"#,
1504 Expr::new_matrix_selector(
1505 Expr::from(VectorSelector::from("http_request_duration_seconds")),
1506 duration::HOUR_DURATION,
1507 )
1508 .and_then(|ex| {
1509 Expr::new_call(get_function("rate").unwrap(), FunctionArgs::new_args(ex))
1510 })
1511 .and_then(|ex| {
1512 Expr::new_call(
1513 get_function("histogram_fraction").unwrap(),
1514 FunctionArgs::new_args(Expr::from(0.0_f64))
1515 .append_args(Expr::from(0.2))
1516 .append_args(ex),
1517 )
1518 }),
1519 ),
1520 (
1521 r#"histogram_avg(rate(http_request_duration_seconds[10m]))"#,
1522 Expr::new_matrix_selector(
1523 Expr::from(VectorSelector::from("http_request_duration_seconds")),
1524 duration::MINUTE_DURATION * 10,
1525 )
1526 .and_then(|ex| {
1527 Expr::new_call(get_function("rate").unwrap(), FunctionArgs::new_args(ex))
1528 })
1529 .and_then(|ex| {
1530 Expr::new_call(
1531 get_function("histogram_avg").unwrap(),
1532 FunctionArgs::new_args(ex),
1533 )
1534 }),
1535 ),
1536 (
1537 r#"histogram_quantile(0.9, rate(http_request_duration_seconds_bucket[10m]))"#,
1538 Expr::new_matrix_selector(
1539 Expr::from(VectorSelector::from("http_request_duration_seconds_bucket")),
1540 duration::MINUTE_DURATION * 10,
1541 )
1542 .and_then(|ex| {
1543 Expr::new_call(get_function("rate").unwrap(), FunctionArgs::new_args(ex))
1544 })
1545 .and_then(|ex| {
1546 Expr::new_call(
1547 get_function("histogram_quantile").unwrap(),
1548 FunctionArgs::new_args(Expr::from(0.9_f64)).append_args(ex),
1549 )
1550 }),
1551 ),
1552 (
1553 r#"histogram_quantile(0.9, sum by (job, le) (rate(http_request_duration_seconds_bucket[10m])))"#,
1554 Expr::new_matrix_selector(
1555 Expr::from(VectorSelector::from("http_request_duration_seconds_bucket")),
1556 duration::MINUTE_DURATION * 10,
1557 )
1558 .and_then(|ex| {
1559 Expr::new_call(get_function("rate").unwrap(), FunctionArgs::new_args(ex))
1560 })
1561 .and_then(|ex| {
1562 Expr::new_aggregate_expr(
1563 token::T_SUM,
1564 Some(LabelModifier::include(vec!["job", "le"])),
1565 FunctionArgs::new_args(ex),
1566 )
1567 })
1568 .and_then(|ex| {
1569 Expr::new_call(
1570 get_function("histogram_quantile").unwrap(),
1571 FunctionArgs::new_args(Expr::from(0.9_f64)).append_args(ex),
1572 )
1573 }),
1574 ),
1575 (
1576 r#"histogram_stddev(rate(http_request_duration_seconds[10m]))"#,
1577 Expr::new_matrix_selector(
1578 Expr::from(VectorSelector::from("http_request_duration_seconds")),
1579 duration::MINUTE_DURATION * 10,
1580 )
1581 .and_then(|ex| {
1582 Expr::new_call(get_function("rate").unwrap(), FunctionArgs::new_args(ex))
1583 })
1584 .and_then(|ex| {
1585 Expr::new_call(
1586 get_function("histogram_stddev").unwrap(),
1587 FunctionArgs::new_args(ex),
1588 )
1589 }),
1590 ),
1591 (
1592 r#"histogram_stdvar(rate(http_request_duration_seconds[10m]))"#,
1593 Expr::new_matrix_selector(
1594 Expr::from(VectorSelector::from("http_request_duration_seconds")),
1595 duration::MINUTE_DURATION * 10,
1596 )
1597 .and_then(|ex| {
1598 Expr::new_call(get_function("rate").unwrap(), FunctionArgs::new_args(ex))
1599 })
1600 .and_then(|ex| {
1601 Expr::new_call(
1602 get_function("histogram_stdvar").unwrap(),
1603 FunctionArgs::new_args(ex),
1604 )
1605 }),
1606 ),
1607 (r#"increase(http_requests_total{job="api-server"}[5m])"#, {
1608 let name = String::from("http_requests_total");
1609 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "job", "api-server"));
1610 Expr::new_vector_selector(Some(name), matchers)
1611 .and_then(|ex| Expr::new_matrix_selector(ex, duration::MINUTE_DURATION * 5))
1612 .and_then(|ex| {
1613 Expr::new_call(
1614 get_function("increase").unwrap(),
1615 FunctionArgs::new_args(ex),
1616 )
1617 })
1618 }),
1619 (r#"irate(http_requests_total{job="api-server"}[5m])"#, {
1620 let name = String::from("http_requests_total");
1621 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "job", "api-server"));
1622 Expr::new_vector_selector(Some(name), matchers)
1623 .and_then(|ex| Expr::new_matrix_selector(ex, duration::MINUTE_DURATION * 5))
1624 .and_then(|ex| {
1625 Expr::new_call(get_function("irate").unwrap(), FunctionArgs::new_args(ex))
1626 })
1627 }),
1628 (
1629 r#"label_join(up{job="api-server",src1="a",src2="b",src3="c"}, "foo", ",", "src1", "src2", "src3")"#,
1630 {
1631 let name = String::from("up");
1632 let matchers = Matchers::new(vec![
1633 Matcher::new(MatchOp::Equal, "job", "api-server"),
1634 Matcher::new(MatchOp::Equal, "src1", "a"),
1635 Matcher::new(MatchOp::Equal, "src2", "b"),
1636 Matcher::new(MatchOp::Equal, "src3", "c"),
1637 ]);
1638 Expr::new_vector_selector(Some(name), matchers).and_then(|ex| {
1639 Expr::new_call(
1640 get_function("label_join").unwrap(),
1641 FunctionArgs::new_args(ex)
1642 .append_args(Expr::from("foo"))
1643 .append_args(Expr::from(","))
1644 .append_args(Expr::from("src1"))
1645 .append_args(Expr::from("src2"))
1646 .append_args(Expr::from("src3")),
1647 )
1648 })
1649 },
1650 ),
1651 (
1652 r#"label_replace(up{job="api-server",service="a:c"}, "foo", "$1", "service", "(.*):.*")"#,
1653 {
1654 let name = String::from("up");
1655 let matchers = Matchers::new(vec![
1656 Matcher::new(MatchOp::Equal, "job", "api-server"),
1657 Matcher::new(MatchOp::Equal, "service", "a:c"),
1658 ]);
1659 Expr::new_vector_selector(Some(name), matchers).and_then(|ex| {
1660 Expr::new_call(
1661 get_function("label_replace").unwrap(),
1662 FunctionArgs::new_args(ex)
1663 .append_args(Expr::from("foo"))
1664 .append_args(Expr::from("$1"))
1665 .append_args(Expr::from("service"))
1666 .append_args(Expr::from("(.*):.*")),
1667 )
1668 })
1669 },
1670 ),
1671 (
1672 r#"sort_by_label(sum(up{job="api-server",src1="a",src2="b",src3="c"}) by (job), "src1","src2")"#,
1673 {
1674 let name = String::from("up");
1675 let matchers = Matchers::new(vec![
1676 Matcher::new(MatchOp::Equal, "job", "api-server"),
1677 Matcher::new(MatchOp::Equal, "src1", "a"),
1678 Matcher::new(MatchOp::Equal, "src2", "b"),
1679 Matcher::new(MatchOp::Equal, "src3", "c"),
1680 ]);
1681
1682 Expr::new_vector_selector(Some(name), matchers)
1683 .and_then(|ex| {
1684 let modifier = LabelModifier::include(vec!["job"]);
1685 Expr::new_aggregate_expr(
1686 token::T_SUM,
1687 Some(modifier),
1688 FunctionArgs::new_args(ex),
1689 )
1690 })
1691 .and_then(|ex| {
1692 Expr::new_call(
1693 get_function("sort_by_label").unwrap(),
1694 FunctionArgs::new_args(ex)
1695 .append_args(Expr::from("src1"))
1696 .append_args(Expr::from("src2")),
1697 )
1698 })
1699 },
1700 ),
1701 (
1702 r#"sort_by_label_desc(sum(up{job="api-server",src1="a",src2="b",src3="c"}) by (job), "src1","src2")"#,
1703 {
1704 let name = String::from("up");
1705 let matchers = Matchers::new(vec![
1706 Matcher::new(MatchOp::Equal, "job", "api-server"),
1707 Matcher::new(MatchOp::Equal, "src1", "a"),
1708 Matcher::new(MatchOp::Equal, "src2", "b"),
1709 Matcher::new(MatchOp::Equal, "src3", "c"),
1710 ]);
1711
1712 Expr::new_vector_selector(Some(name), matchers)
1713 .and_then(|ex| {
1714 let modifier = LabelModifier::include(vec!["job"]);
1715 Expr::new_aggregate_expr(
1716 token::T_SUM,
1717 Some(modifier),
1718 FunctionArgs::new_args(ex),
1719 )
1720 })
1721 .and_then(|ex| {
1722 Expr::new_call(
1723 get_function("sort_by_label_desc").unwrap(),
1724 FunctionArgs::new_args(ex)
1725 .append_args(Expr::from("src1"))
1726 .append_args(Expr::from("src2")),
1727 )
1728 })
1729 },
1730 ),
1731 (
1733 r#"exp(+Inf)"#,
1734 Expr::new_call(
1735 get_function("exp").unwrap(),
1736 FunctionArgs::new_args(Expr::from(f64::INFINITY)),
1737 ),
1738 ),
1739 (
1740 r#"exp(NaN)"#,
1741 Expr::new_call(
1742 get_function("exp").unwrap(),
1743 FunctionArgs::new_args(Expr::from(f64::NAN)),
1744 ),
1745 ),
1746 (
1747 r#"ln(+Inf)"#,
1748 Expr::new_call(
1749 get_function("ln").unwrap(),
1750 FunctionArgs::new_args(Expr::from(f64::INFINITY)),
1751 ),
1752 ),
1753 (
1754 r#"ln(NaN)"#,
1755 Expr::new_call(
1756 get_function("ln").unwrap(),
1757 FunctionArgs::new_args(Expr::from(f64::NAN)),
1758 ),
1759 ),
1760 (
1761 r#"ln(0)"#,
1762 Expr::new_call(
1763 get_function("ln").unwrap(),
1764 FunctionArgs::new_args(Expr::from(0.0)),
1765 ),
1766 ),
1767 (
1768 r#"ln(-1)"#,
1769 Expr::new_call(
1770 get_function("ln").unwrap(),
1771 FunctionArgs::new_args(Expr::from(-1.0)),
1772 ),
1773 ),
1774 (
1775 r#"log2(+Inf)"#,
1776 Expr::new_call(
1777 get_function("log2").unwrap(),
1778 FunctionArgs::new_args(Expr::from(f64::INFINITY)),
1779 ),
1780 ),
1781 (
1782 r#"log2(NaN)"#,
1783 Expr::new_call(
1784 get_function("log2").unwrap(),
1785 FunctionArgs::new_args(Expr::from(f64::NAN)),
1786 ),
1787 ),
1788 (
1789 r#"log2(0)"#,
1790 Expr::new_call(
1791 get_function("log2").unwrap(),
1792 FunctionArgs::new_args(Expr::from(0.0)),
1793 ),
1794 ),
1795 (
1796 r#"log2(-1)"#,
1797 Expr::new_call(
1798 get_function("log2").unwrap(),
1799 FunctionArgs::new_args(Expr::from(-1.0)),
1800 ),
1801 ),
1802 (
1803 r#"log10(+Inf)"#,
1804 Expr::new_call(
1805 get_function("log10").unwrap(),
1806 FunctionArgs::new_args(Expr::from(f64::INFINITY)),
1807 ),
1808 ),
1809 (
1810 r#"log10(NaN)"#,
1811 Expr::new_call(
1812 get_function("log10").unwrap(),
1813 FunctionArgs::new_args(Expr::from(f64::NAN)),
1814 ),
1815 ),
1816 (
1817 r#"log10(0)"#,
1818 Expr::new_call(
1819 get_function("log10").unwrap(),
1820 FunctionArgs::new_args(Expr::from(0.0)),
1821 ),
1822 ),
1823 (
1824 r#"log10(-1)"#,
1825 Expr::new_call(
1826 get_function("log10").unwrap(),
1827 FunctionArgs::new_args(Expr::from(-1.0)),
1828 ),
1829 ),
1830 ];
1831
1832 assert_cases(Case::new_result_cases(cases));
1833
1834 let fail_cases = vec![
1835 (
1836 "floor()",
1837 "expected 1 argument(s) in call to 'floor', got 0",
1838 ),
1839 (
1840 "floor(some_metric, other_metric)",
1841 "expected 1 argument(s) in call to 'floor', got 2",
1842 ),
1843 (
1844 "floor(some_metric, 1)",
1845 "expected 1 argument(s) in call to 'floor', got 2",
1846 ),
1847 (
1848 "floor(1)",
1849 "expected type vector in call to function 'floor', got scalar",
1850 ),
1851 (
1852 "hour(some_metric, some_metric, some_metric)",
1853 "expected at most 1 argument(s) in call to 'hour', got 3",
1854 ),
1855 (
1856 "time(some_metric)",
1857 "expected 0 argument(s) in call to 'time', got 1",
1858 ),
1859 (
1860 "non_existent_function_far_bar()",
1861 "unknown function with name 'non_existent_function_far_bar'",
1862 ),
1863 (
1864 "rate(some_metric)",
1865 "expected type matrix in call to function 'rate', got vector",
1866 ),
1867 (
1868 "ln(1)",
1869 "expected type vector in call to function 'ln', got scalar",
1870 ),
1871 ("ln()", "expected 1 argument(s) in call to 'ln', got 0"),
1872 (
1873 "exp(1)",
1874 "expected type vector in call to function 'exp', got scalar",
1875 ),
1876 ("exp()", "expected 1 argument(s) in call to 'exp', got 0"),
1877 (
1878 "label_join()",
1879 "expected at least 3 argument(s) in call to 'label_join', got 0",
1880 ),
1881 (
1882 "sort_by_label()",
1883 "expected at least 2 argument(s) in call to 'sort_by_label', got 0",
1884 ),
1885 (
1886 "sort_by_label_desc()",
1887 "expected at least 2 argument(s) in call to 'sort_by_label_desc', got 0",
1888 ),
1889 (
1890 "sort_by_label(sum(up) by (instance))",
1891 "expected at least 2 argument(s) in call to 'sort_by_label', got 1",
1892 ),
1893 (
1894 "sort_by_label_desc(sum(up) by (instance))",
1895 "expected at least 2 argument(s) in call to 'sort_by_label_desc', got 1",
1896 ),
1897 ];
1899 assert_cases(Case::new_fail_cases(fail_cases));
1900 }
1901
1902 #[test]
1903 fn test_subquery() {
1904 let cases = vec![
1905 (r#"foo{bar="baz"}[10m:6s]"#, {
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,
1911 Some(duration::SECOND_DURATION * 6),
1912 )
1913 })
1914 }),
1915 (r#"foo{bar="baz"}[10m5s:1h6ms]"#, {
1916 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "bar", "baz"));
1917 Expr::new_vector_selector(Some(String::from("foo")), matchers).and_then(|ex| {
1918 Expr::new_subquery_expr(
1919 ex,
1920 duration::MINUTE_DURATION * 10 + duration::SECOND_DURATION * 5,
1921 Some(duration::HOUR_DURATION + duration::MILLI_DURATION * 6),
1922 )
1923 })
1924 }),
1925 ("foo[10m:]", {
1926 let ex = Expr::from(VectorSelector::from("foo"));
1927 Expr::new_subquery_expr(ex, duration::MINUTE_DURATION * 10, None)
1928 }),
1929 (r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:5s])"#, {
1930 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "bar", "baz"));
1931 Expr::new_vector_selector(Some(String::from("foo")), matchers)
1932 .and_then(|ex| Expr::new_matrix_selector(ex, Duration::from_secs(2)))
1933 .and_then(|ex| {
1934 Expr::new_call(get_function("rate").unwrap(), FunctionArgs::new_args(ex))
1935 })
1936 .and_then(|ex| {
1937 Expr::new_subquery_expr(
1938 ex,
1939 duration::MINUTE_DURATION * 5,
1940 Some(Duration::from_secs(5)),
1941 )
1942 })
1943 .and_then(|ex| {
1944 Expr::new_call(
1945 get_function("min_over_time").unwrap(),
1946 FunctionArgs::new_args(ex),
1947 )
1948 })
1949 }),
1950 (r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:])[4m:3s]"#, {
1951 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "bar", "baz"));
1952 Expr::new_vector_selector(Some(String::from("foo")), matchers)
1953 .and_then(|ex| Expr::new_matrix_selector(ex, Duration::from_secs(2)))
1954 .and_then(|ex| {
1955 Expr::new_call(get_function("rate").unwrap(), FunctionArgs::new_args(ex))
1956 })
1957 .and_then(|ex| Expr::new_subquery_expr(ex, duration::MINUTE_DURATION * 5, None))
1958 .and_then(|ex| {
1959 Expr::new_call(
1960 get_function("min_over_time").unwrap(),
1961 FunctionArgs::new_args(ex),
1962 )
1963 })
1964 .and_then(|ex| {
1965 Expr::new_subquery_expr(
1966 ex,
1967 duration::MINUTE_DURATION * 4,
1968 Some(Duration::from_secs(3)),
1969 )
1970 })
1971 }),
1972 (
1973 r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:] offset 4m)[4m:3s]"#,
1974 {
1975 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "bar", "baz"));
1976 Expr::new_vector_selector(Some(String::from("foo")), matchers)
1977 .and_then(|ex| Expr::new_matrix_selector(ex, Duration::from_secs(2)))
1978 .and_then(|ex| {
1979 Expr::new_call(
1980 get_function("rate").unwrap(),
1981 FunctionArgs::new_args(ex),
1982 )
1983 })
1984 .and_then(|ex| {
1985 Expr::new_subquery_expr(ex, duration::MINUTE_DURATION * 5, None)
1986 })
1987 .and_then(|ex| ex.offset_expr(Offset::Pos(duration::MINUTE_DURATION * 4)))
1988 .and_then(|ex| {
1989 Expr::new_call(
1990 get_function("min_over_time").unwrap(),
1991 FunctionArgs::new_args(ex),
1992 )
1993 })
1994 .and_then(|ex| {
1995 Expr::new_subquery_expr(
1996 ex,
1997 duration::MINUTE_DURATION * 4,
1998 Some(Duration::from_secs(3)),
1999 )
2000 })
2001 },
2002 ),
2003 (
2004 r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:] @ 1603775091)[4m:3s]"#,
2005 {
2006 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "bar", "baz"));
2007 Expr::new_vector_selector(Some(String::from("foo")), matchers)
2008 .and_then(|ex| Expr::new_matrix_selector(ex, Duration::from_secs(2)))
2009 .and_then(|ex| {
2010 Expr::new_call(
2011 get_function("rate").unwrap(),
2012 FunctionArgs::new_args(ex),
2013 )
2014 })
2015 .and_then(|ex| {
2016 Expr::new_subquery_expr(ex, duration::MINUTE_DURATION * 5, None)
2017 })
2018 .and_then(|ex| ex.at_expr(At::try_from(1603775091_f64).unwrap()))
2019 .and_then(|ex| {
2020 Expr::new_call(
2021 get_function("min_over_time").unwrap(),
2022 FunctionArgs::new_args(ex),
2023 )
2024 })
2025 .and_then(|ex| {
2026 Expr::new_subquery_expr(
2027 ex,
2028 duration::MINUTE_DURATION * 4,
2029 Some(Duration::from_secs(3)),
2030 )
2031 })
2032 },
2033 ),
2034 (
2035 r#"min_over_time(rate(foo{bar="baz"}[2s])[5m:] @ -160377509)[4m:3s]"#,
2036 {
2037 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "bar", "baz"));
2038 Expr::new_vector_selector(Some(String::from("foo")), matchers)
2039 .and_then(|ex| Expr::new_matrix_selector(ex, Duration::from_secs(2)))
2040 .and_then(|ex| {
2041 Expr::new_call(
2042 get_function("rate").unwrap(),
2043 FunctionArgs::new_args(ex),
2044 )
2045 })
2046 .and_then(|ex| {
2047 Expr::new_subquery_expr(ex, duration::MINUTE_DURATION * 5, None)
2048 })
2049 .and_then(|ex| ex.at_expr(At::try_from(-160377509_f64).unwrap()))
2050 .and_then(|ex| {
2051 Expr::new_call(
2052 get_function("min_over_time").unwrap(),
2053 FunctionArgs::new_args(ex),
2054 )
2055 })
2056 .and_then(|ex| {
2057 Expr::new_subquery_expr(
2058 ex,
2059 duration::MINUTE_DURATION * 4,
2060 Some(Duration::from_secs(3)),
2061 )
2062 })
2063 },
2064 ),
2065 (
2066 "sum without(and, by, avg, count, alert, annotations)(some_metric) [30m:10s]",
2067 {
2068 let ex = Expr::from(VectorSelector::from("some_metric"));
2069 Expr::new_aggregate_expr(
2070 token::T_SUM,
2071 Some(LabelModifier::exclude(vec![
2072 "and",
2073 "by",
2074 "avg",
2075 "count",
2076 "alert",
2077 "annotations",
2078 ])),
2079 FunctionArgs::new_args(ex),
2080 )
2081 .and_then(|ex| {
2082 Expr::new_subquery_expr(
2083 ex,
2084 duration::MINUTE_DURATION * 30,
2085 Some(Duration::from_secs(10)),
2086 )
2087 })
2088 },
2089 ),
2090 (
2091 "some_metric OFFSET 1m [10m:5s]",
2092 Expr::from(VectorSelector::from("some_metric"))
2093 .offset_expr(Offset::Pos(duration::MINUTE_DURATION))
2094 .and_then(|ex| {
2095 Expr::new_subquery_expr(
2096 ex,
2097 duration::MINUTE_DURATION * 10,
2098 Some(Duration::from_secs(5)),
2099 )
2100 }),
2101 ),
2102 (
2103 "some_metric @ 123 [10m:5s]",
2104 Expr::from(VectorSelector::from("some_metric"))
2105 .at_expr(At::try_from(123_f64).unwrap())
2106 .and_then(|ex| {
2107 Expr::new_subquery_expr(
2108 ex,
2109 duration::MINUTE_DURATION * 10,
2110 Some(Duration::from_secs(5)),
2111 )
2112 }),
2113 ),
2114 (
2115 "some_metric @ 123 offset 1m [10m:5s]",
2116 Expr::from(VectorSelector::from("some_metric"))
2117 .at_expr(At::try_from(123_f64).unwrap())
2118 .and_then(|ex| ex.offset_expr(Offset::Pos(duration::MINUTE_DURATION)))
2119 .and_then(|ex| {
2120 Expr::new_subquery_expr(
2121 ex,
2122 duration::MINUTE_DURATION * 10,
2123 Some(Duration::from_secs(5)),
2124 )
2125 }),
2126 ),
2127 (
2128 "some_metric offset 1m @ 123 [10m:5s]",
2129 Expr::from(VectorSelector::from("some_metric"))
2130 .at_expr(At::try_from(123_f64).unwrap())
2131 .and_then(|ex| ex.offset_expr(Offset::Pos(duration::MINUTE_DURATION)))
2132 .and_then(|ex| {
2133 Expr::new_subquery_expr(
2134 ex,
2135 duration::MINUTE_DURATION * 10,
2136 Some(Duration::from_secs(5)),
2137 )
2138 }),
2139 ),
2140 (
2141 "some_metric[10m:5s] offset 1m @ 123",
2142 Expr::new_subquery_expr(
2143 Expr::from(VectorSelector::from("some_metric")),
2144 duration::MINUTE_DURATION * 10,
2145 Some(Duration::from_secs(5)),
2146 )
2147 .and_then(|ex| ex.at_expr(At::try_from(123_f64).unwrap()))
2148 .and_then(|ex| ex.offset_expr(Offset::Pos(duration::MINUTE_DURATION))),
2149 ),
2150 (r#"(foo + bar{nm="val"})[5m:]"#, {
2151 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "nm", "val"));
2152 Expr::new_binary_expr(
2153 Expr::from(VectorSelector::from("foo")),
2154 token::T_ADD,
2155 None,
2156 Expr::new_vector_selector(Some(String::from("bar")), matchers).unwrap(),
2157 )
2158 .and_then(Expr::new_paren_expr)
2159 .and_then(|ex| Expr::new_subquery_expr(ex, duration::MINUTE_DURATION * 5, None))
2160 }),
2161 (r#"(foo + bar{nm="val"})[5m:] offset 10m"#, {
2162 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "nm", "val"));
2163 Expr::new_binary_expr(
2164 Expr::from(VectorSelector::from("foo")),
2165 token::T_ADD,
2166 None,
2167 Expr::new_vector_selector(Some(String::from("bar")), matchers).unwrap(),
2168 )
2169 .and_then(Expr::new_paren_expr)
2170 .and_then(|ex| Expr::new_subquery_expr(ex, duration::MINUTE_DURATION * 5, None))
2171 .and_then(|ex| ex.offset_expr(Offset::Pos(duration::MINUTE_DURATION * 10)))
2172 }),
2173 (r#"(foo + bar{nm="val"} @ 1234)[5m:] @ 1603775019"#, {
2174 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "nm", "val"));
2175 let rhs = Expr::new_vector_selector(Some(String::from("bar")), matchers)
2176 .and_then(|ex| ex.at_expr(At::try_from(1234_f64).unwrap()))
2177 .unwrap();
2178
2179 Expr::new_binary_expr(
2180 Expr::from(VectorSelector::from("foo")),
2181 token::T_ADD,
2182 None,
2183 rhs,
2184 )
2185 .and_then(Expr::new_paren_expr)
2186 .and_then(|ex| Expr::new_subquery_expr(ex, duration::MINUTE_DURATION * 5, None))
2187 .and_then(|ex| ex.at_expr(At::try_from(1603775019_f64).unwrap()))
2188 }),
2189 ];
2190 assert_cases(Case::new_result_cases(cases));
2191
2192 let fail_cases = vec![
2193 (
2194 "test[5d] OFFSET 10s [10m:5s]",
2195 "subquery is only allowed on vector, got matrix instead",
2196 ),
2197 (
2198 r#"(foo + bar{nm="val"})[5m:][10m:5s]"#,
2199 "subquery is only allowed on vector, got matrix instead",
2200 ),
2201 (
2202 "rate(food[1m])[1h] offset 1h",
2203 "ranges only allowed for vector selectors",
2204 ),
2205 (
2206 "rate(food[1m])[1h] @ 100",
2207 "ranges only allowed for vector selectors",
2208 ),
2209 ];
2210 assert_cases(Case::new_fail_cases(fail_cases));
2211 }
2212
2213 #[test]
2214 fn test_preprocessors() {
2215 let cases = vec![
2216 (
2217 "foo @ start()",
2218 Expr::from(VectorSelector::from("foo")).at_expr(At::Start),
2219 ),
2220 (
2221 "foo @ end()",
2222 Expr::from(VectorSelector::from("foo")).at_expr(At::End),
2223 ),
2224 (
2225 "test[5y] @ start()",
2226 Expr::new_matrix_selector(
2227 Expr::from(VectorSelector::from("test")),
2228 duration::YEAR_DURATION * 5,
2229 )
2230 .and_then(|ex| ex.at_expr(At::Start)),
2231 ),
2232 (
2233 "test[5y] @ end()",
2234 Expr::new_matrix_selector(
2235 Expr::from(VectorSelector::from("test")),
2236 duration::YEAR_DURATION * 5,
2237 )
2238 .and_then(|ex| ex.at_expr(At::End)),
2239 ),
2240 (
2241 "foo[10m:6s] @ start()",
2242 Expr::new_subquery_expr(
2243 Expr::from(VectorSelector::from("foo")),
2244 duration::MINUTE_DURATION * 10,
2245 Some(Duration::from_secs(6)),
2246 )
2247 .and_then(|ex| ex.at_expr(At::Start)),
2248 ),
2249 ("start", Ok(Expr::from(VectorSelector::from("start")))),
2251 ("end", Ok(Expr::from(VectorSelector::from("end")))),
2252 (r#"start{end="foo"}"#, {
2253 let name = String::from("start");
2254 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "end", "foo"));
2255 Expr::new_vector_selector(Some(name), matchers)
2256 }),
2257 (r#"end{start="foo"}"#, {
2258 let name = String::from("end");
2259 let matchers = Matchers::one(Matcher::new(MatchOp::Equal, "start", "foo"));
2260 Expr::new_vector_selector(Some(name), matchers)
2261 }),
2262 ("foo unless on(start) bar", {
2263 let modifier = BinModifier::default()
2264 .with_matching(Some(LabelModifier::include(vec!["start"])))
2265 .with_card(VectorMatchCardinality::ManyToMany);
2266 Expr::new_binary_expr(
2267 Expr::from(VectorSelector::from("foo")),
2268 token::T_LUNLESS,
2269 Some(modifier),
2270 Expr::from(VectorSelector::from("bar")),
2271 )
2272 }),
2273 ("foo unless on(end) bar", {
2274 let modifier = BinModifier::default()
2275 .with_matching(Some(LabelModifier::include(vec!["end"])))
2276 .with_card(VectorMatchCardinality::ManyToMany);
2277 Expr::new_binary_expr(
2278 Expr::from(VectorSelector::from("foo")),
2279 token::T_LUNLESS,
2280 Some(modifier),
2281 Expr::from(VectorSelector::from("bar")),
2282 )
2283 }),
2284 ];
2285 assert_cases(Case::new_result_cases(cases));
2286
2287 let cases = vec![
2288 ("start()", INVALID_QUERY_INFO),
2289 ("end()", INVALID_QUERY_INFO),
2290 ];
2291 assert_cases(Case::new_fail_cases(cases));
2292 }
2293
2294 #[test]
2295 fn test_corner_fail_cases() {
2296 let fail_cases = vec![
2297 ("", "no expression found in input"),
2298 (
2299 "# just a comment\n\n",
2300 "no expression found in input",
2301 ),
2302 ("1+", INVALID_QUERY_INFO),
2303 (".", "unexpected character: '.'"),
2304 ("2.5.", "bad number or duration syntax: 2.5."),
2305 ("100..4", "bad number or duration syntax: 100.."),
2306 ("0deadbeef", "bad number or duration syntax: 0de"),
2307 ("1 /", INVALID_QUERY_INFO),
2308 ("*1", INVALID_QUERY_INFO),
2309 ("(1))", "unexpected right parenthesis ')'"),
2310 ("((1)", "unclosed left parenthesis"),
2311 ("(", "unclosed left parenthesis"),
2312 ("1 !~ 1", "unexpected character after '!': '~'"),
2313 ("1 =~ 1", "unexpected character after '=': '~'"),
2314 ("*test", INVALID_QUERY_INFO),
2315 (
2316 "1 offset 1d",
2317 "offset modifier must be preceded by an vector selector or matrix selector or a subquery"
2318 ),
2319 (
2320 "foo offset 1s offset 2s",
2321 "offset may not be set multiple times"
2322 ),
2323 ("a - on(b) ignoring(c) d", INVALID_QUERY_INFO),
2324
2325 ("-=", INVALID_QUERY_INFO),
2327 ("++-++-+-+-<", INVALID_QUERY_INFO),
2328 ("e-+=/(0)", INVALID_QUERY_INFO),
2329 ("a>b()", "unknown function with name 'b'"),
2330 (
2331 "rate(avg)",
2332 "expected type matrix in call to function 'rate', got vector"
2333 ),
2334 ];
2335 assert_cases(Case::new_fail_cases(fail_cases));
2336
2337 let fail_cases = vec![
2338 {
2340 let input = "(".to_string() + &"-{}-1".repeat(10_000) + ")" + &"[1m:]".repeat(1000);
2341 let expected =
2342 Err("vector selector must contain at least one non-empty matcher".into());
2343 Case { input, expected }
2344 },
2345 ];
2346 assert_cases(fail_cases);
2347 }
2348
2349 #[test]
2350 fn test_or_filters() {
2351 let cases = vec![
2352 (r#"foo{label1="1" or label1="2"}"#, {
2353 let matchers = Matchers::new(vec![]).with_or_matchers(vec![
2354 vec![Matcher::new(MatchOp::Equal, "label1", "1")],
2355 vec![Matcher::new(MatchOp::Equal, "label1", "2")],
2356 ]);
2357 Expr::new_vector_selector(Some(String::from("foo")), matchers)
2358 }),
2359 (r#"foo{label1="1" OR label1="2"}"#, {
2360 let matchers = Matchers::new(vec![]).with_or_matchers(vec![
2361 vec![Matcher::new(MatchOp::Equal, "label1", "1")],
2362 vec![Matcher::new(MatchOp::Equal, "label1", "2")],
2363 ]);
2364 Expr::new_vector_selector(Some(String::from("foo")), matchers)
2365 }),
2366 (r#"foo{label1="1" Or label1="2"}"#, {
2367 let matchers = Matchers::new(vec![]).with_or_matchers(vec![
2368 vec![Matcher::new(MatchOp::Equal, "label1", "1")],
2369 vec![Matcher::new(MatchOp::Equal, "label1", "2")],
2370 ]);
2371 Expr::new_vector_selector(Some(String::from("foo")), matchers)
2372 }),
2373 (r#"foo{label1="1" oR label1="2"}"#, {
2374 let matchers = Matchers::new(vec![]).with_or_matchers(vec![
2375 vec![Matcher::new(MatchOp::Equal, "label1", "1")],
2376 vec![Matcher::new(MatchOp::Equal, "label1", "2")],
2377 ]);
2378 Expr::new_vector_selector(Some(String::from("foo")), matchers)
2379 }),
2380 (r#"foo{label1="1" or or="or"}"#, {
2381 let matchers = Matchers::new(vec![]).with_or_matchers(vec![
2382 vec![Matcher::new(MatchOp::Equal, "label1", "1")],
2383 vec![Matcher::new(MatchOp::Equal, "or", "or")],
2384 ]);
2385 Expr::new_vector_selector(Some(String::from("foo")), matchers)
2386 }),
2387 (
2388 r#"foo{label1="1" or label1="2" or label1="3" or label1="4"}"#,
2389 {
2390 let matchers = Matchers::new(vec![]).with_or_matchers(vec![
2391 vec![Matcher::new(MatchOp::Equal, "label1", "1")],
2392 vec![Matcher::new(MatchOp::Equal, "label1", "2")],
2393 vec![Matcher::new(MatchOp::Equal, "label1", "3")],
2394 vec![Matcher::new(MatchOp::Equal, "label1", "4")],
2395 ]);
2396 Expr::new_vector_selector(Some(String::from("foo")), matchers)
2397 },
2398 ),
2399 (
2400 r#"foo{label1="1" or label1="2" or label1="3", label2="4"}"#,
2401 {
2402 let matchers = Matchers::new(vec![]).with_or_matchers(vec![
2403 vec![Matcher::new(MatchOp::Equal, "label1", "1")],
2404 vec![Matcher::new(MatchOp::Equal, "label1", "2")],
2405 vec![
2406 Matcher::new(MatchOp::Equal, "label1", "3"),
2407 Matcher::new(MatchOp::Equal, "label2", "4"),
2408 ],
2409 ]);
2410 Expr::new_vector_selector(Some(String::from("foo")), matchers)
2411 },
2412 ),
2413 (
2414 r#"foo{label1="1", label2="2" or label1="3" or label1="4"}"#,
2415 {
2416 let matchers = Matchers::new(vec![]).with_or_matchers(vec![
2417 vec![
2418 Matcher::new(MatchOp::Equal, "label1", "1"),
2419 Matcher::new(MatchOp::Equal, "label2", "2"),
2420 ],
2421 vec![Matcher::new(MatchOp::Equal, "label1", "3")],
2422 vec![Matcher::new(MatchOp::Equal, "label1", "4")],
2423 ]);
2424 Expr::new_vector_selector(Some(String::from("foo")), matchers)
2425 },
2426 ),
2427 ];
2428 assert_cases(Case::new_result_cases(cases));
2429
2430 let display_cases = [
2431 r#"a{label1="1"}"#,
2432 r#"a{label1="1" or label2="2"}"#,
2433 r#"a{label1="1" or label2="2" or label3="3" or label4="4"}"#,
2434 r#"a{label1="1", label2="2" or label3="3" or label4="4"}"#,
2435 r#"a{label1="1", label2="2" or label3="3", label4="4"}"#,
2436 ];
2437 display_cases
2438 .iter()
2439 .for_each(|expr| assert_eq!(parser::parse(expr).unwrap().to_string(), *expr));
2440
2441 let or_insensitive_cases = [
2442 r#"a{label1="1" or label2="2"}"#,
2443 r#"a{label1="1" OR label2="2"}"#,
2444 r#"a{label1="1" Or label2="2"}"#,
2445 r#"a{label1="1" oR label2="2"}"#,
2446 ];
2447
2448 or_insensitive_cases.iter().for_each(|expr| {
2449 assert_eq!(
2450 parser::parse(expr).unwrap().to_string(),
2451 r#"a{label1="1" or label2="2"}"#
2452 )
2453 });
2454
2455 let fail_cases = vec![
2456 (
2457 r#"foo{or}"#,
2458 r#"invalid label matcher, expected label matching operator after 'or'"#,
2459 ),
2460 (r#"foo{label1="1" or}"#, INVALID_QUERY_INFO),
2461 (r#"foo{or label1="1"}"#, INVALID_QUERY_INFO),
2462 (r#"foo{label1="1" or or label2="2"}"#, INVALID_QUERY_INFO),
2463 ];
2464 assert_cases(Case::new_fail_cases(fail_cases));
2465 }
2466
2467 #[test]
2468 fn test_prom3_string_identifier() {
2469 let case = r#"{"some.metric"}"#;
2470 assert_eq!(
2471 parser::parse(case).unwrap(),
2472 parser::parse(r#"{__name__="some.metric"}"#).unwrap()
2473 );
2474
2475 let case = r#"some_metric{"service.name"="api-server"}"#;
2476 assert_eq!(
2477 parser::parse(case).unwrap(),
2478 Expr::new_vector_selector(
2479 Some("some_metric".to_string()),
2480 Matchers::one(Matcher::new(MatchOp::Equal, "service.name", "api-server"))
2481 )
2482 .unwrap()
2483 );
2484
2485 let case = r#"sum by ("foo")(some_metric{})"#;
2486 assert_eq!(
2487 parser::parse(case).unwrap(),
2488 parser::parse(r#"sum by (foo)(some_metric{})"#).unwrap()
2489 );
2490
2491 let case = r#"test{host=~"10\\.0\\.160\\.237:808|nonexistence"}"#;
2492 parser::parse(case).unwrap();
2493 assert!(parser::parse(case).is_ok());
2494 }
2495}