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