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