bk_promql_parser/parser/
parse.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::parser::{lex, Expr, INVALID_QUERY_INFO};
16
17/// Parse the given query literal to an AST (which is [`Expr`] in this crate).
18pub fn parse(input: &str) -> Result<Expr, String> {
19    match lex::lexer(input) {
20        Err(e) => Err(e),
21        Ok(lexer) => {
22            // NOTE: the errs is ignored so far.
23            let (res, _errs) = crate::promql_y::parse(&lexer);
24            res.ok_or_else(|| String::from(INVALID_QUERY_INFO))?
25        }
26    }
27}
28
29/// cases in original prometheus is a huge slices which are constructed more than 3000 lines,
30/// and it is hard to split them based on the original order. So here is the Note:
31///
32/// - all cases SHOULD be covered, and the same literal float and literal
33///   string SHOULD be the same with the original prometheus.
34/// - all cases will be split into different blocks based on the type of parsed Expr.
35#[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            // for abnormal input
109            ("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                // this case is the same with the previous upper one
200                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            // (r#""\x.""#, ""),
231        ];
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                // Test and/or precedence and reassigning of operands.
429                "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                // Test and/or/unless precedence.
453                "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                // Test precedence and reassigning of operands.
479                "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            // cases from https://prometheus.io/docs/prometheus/latest/querying/operators
672            (
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            // NOTE: group modifier CAN NOT be used without on/ignoring modifier
739            ("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            // the following multiple __name__ matcher test cases are not from prometheus
949            (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            // (
1011            //     r#"some_metric{a="\xff"}"#,
1012            //     "1:15: parse error: invalid UTF-8 rune",
1013            // ),
1014            (
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 label matcher, expected label matching operator after 'lol'",
1038                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            // cases from https://prometheus.io/docs/prometheus/latest/querying/functions
1344            (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            // special cases
1572            (
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            // (r#"label_replace(a, `b`, `c\xff`, `d`, `.*`)"#, ""),
1722        ];
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            // Check that start and end functions do not mask metrics.
2074            ("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            // Fuzzing regression tests.
2150            ("-=", 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}