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