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