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