promql_parser/parser/
parse.rs

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