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