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