2015-03-30 09:12:51 -07:00
// Copyright 2015 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
2020-02-03 08:23:44 -08:00
package parser
2015-03-30 09:12:51 -07:00
import (
2022-06-08 01:47:52 -07:00
"errors"
2015-03-30 09:12:51 -07:00
"math"
"testing"
2015-08-20 08:18:46 -07:00
"github.com/prometheus/common/model"
2020-10-29 02:43:23 -07:00
"github.com/stretchr/testify/require"
2019-03-25 16:01:12 -07:00
2023-08-25 14:35:42 -07:00
"github.com/prometheus/prometheus/model/histogram"
2021-11-08 06:23:17 -08:00
"github.com/prometheus/prometheus/model/labels"
2023-09-14 09:57:31 -07:00
"github.com/prometheus/prometheus/promql/parser/posrange"
2015-03-30 09:12:51 -07:00
)
var testExpr = [ ] struct {
2015-04-29 07:35:18 -07:00
input string // The input to be parsed.
expected Expr // The expected expression AST.
fail bool // Whether parsing is supposed to fail.
errMsg string // If not empty the parsing error has to contain this string.
2015-03-30 09:12:51 -07:00
} {
2016-12-28 00:16:48 -08:00
// Scalars and scalar-to-scalar operations.
2023-12-08 10:53:39 -08:00
// {
// input: "1",
// expected: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 0, End: 1},
// },
// },
// {
// input: "+Inf",
// expected: &NumberLiteral{
// Val: math.Inf(1),
// PosRange: posrange.PositionRange{Start: 0, End: 4},
// },
// },
// {
// input: "-Inf",
// expected: &NumberLiteral{
// Val: math.Inf(-1),
// PosRange: posrange.PositionRange{Start: 0, End: 4},
// },
// },
// {
// input: ".5",
// expected: &NumberLiteral{
// Val: 0.5,
// PosRange: posrange.PositionRange{Start: 0, End: 2},
// },
// },
// {
// input: "5.",
// expected: &NumberLiteral{
// Val: 5,
// PosRange: posrange.PositionRange{Start: 0, End: 2},
// },
// },
// {
// input: "123.4567",
// expected: &NumberLiteral{
// Val: 123.4567,
// PosRange: posrange.PositionRange{Start: 0, End: 8},
// },
// },
// {
// input: "5e-3",
// expected: &NumberLiteral{
// Val: 0.005,
// PosRange: posrange.PositionRange{Start: 0, End: 4},
// },
// },
// {
// input: "5e3",
// expected: &NumberLiteral{
// Val: 5000,
// PosRange: posrange.PositionRange{Start: 0, End: 3},
// },
// },
// {
// input: "0xc",
// expected: &NumberLiteral{
// Val: 12,
// PosRange: posrange.PositionRange{Start: 0, End: 3},
// },
// },
// {
// input: "0755",
// expected: &NumberLiteral{
// Val: 493,
// PosRange: posrange.PositionRange{Start: 0, End: 4},
// },
// },
// {
// input: "+5.5e-3",
// expected: &NumberLiteral{
// Val: 0.0055,
// PosRange: posrange.PositionRange{Start: 0, End: 7},
// },
// },
// {
// input: "-0755",
// expected: &NumberLiteral{
// Val: -493,
// PosRange: posrange.PositionRange{Start: 0, End: 5},
// },
// },
// {
// input: "1 + 1",
// expected: &BinaryExpr{
// Op: ADD,
// LHS: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 0, End: 1},
// },
// RHS: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 4, End: 5},
// },
// },
// },
// {
// input: "1 - 1",
// expected: &BinaryExpr{
// Op: SUB,
// LHS: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 0, End: 1},
// },
// RHS: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 4, End: 5},
// },
// },
// },
// {
// input: "1 * 1",
// expected: &BinaryExpr{
// Op: MUL,
// LHS: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 0, End: 1},
// },
// RHS: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 4, End: 5},
// },
// },
// },
// {
// input: "1 % 1",
// expected: &BinaryExpr{
// Op: MOD,
// LHS: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 0, End: 1},
// },
// RHS: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 4, End: 5},
// },
// },
// },
// {
// input: "1 / 1",
// expected: &BinaryExpr{
// Op: DIV,
// LHS: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 0, End: 1},
// },
// RHS: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 4, End: 5},
// },
// },
// },
// {
// input: "1 == bool 1",
// expected: &BinaryExpr{
// Op: EQLC,
// LHS: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 0, End: 1},
// },
// RHS: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 10, End: 11},
// },
// ReturnBool: true,
// },
// },
// {
// input: "1 != bool 1",
// expected: &BinaryExpr{
// Op: NEQ,
// LHS: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 0, End: 1},
// },
// RHS: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 10, End: 11},
// },
// ReturnBool: true,
// },
// },
// {
// input: "1 > bool 1",
// expected: &BinaryExpr{
// Op: GTR,
// LHS: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 0, End: 1},
// },
// RHS: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 9, End: 10},
// },
// ReturnBool: true,
// },
// },
// {
// input: "1 >= bool 1",
// expected: &BinaryExpr{
// Op: GTE,
// LHS: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 0, End: 1},
// },
// RHS: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 10, End: 11},
// },
// ReturnBool: true,
// },
// },
// {
// input: "1 < bool 1",
// expected: &BinaryExpr{
// Op: LSS,
// LHS: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 0, End: 1},
// },
// RHS: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 9, End: 10},
// },
// ReturnBool: true,
// },
// },
// {
// input: "1 <= bool 1",
// expected: &BinaryExpr{
// Op: LTE,
// LHS: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 0, End: 1},
// },
// RHS: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 10, End: 11},
// },
// ReturnBool: true,
// },
// },
// {
// input: "-1^2",
// expected: &UnaryExpr{
// Op: SUB,
// Expr: &BinaryExpr{
// Op: POW,
// LHS: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 1, End: 2},
// },
// RHS: &NumberLiteral{
// Val: 2,
// PosRange: posrange.PositionRange{Start: 3, End: 4},
// },
// },
// },
// },
// {
// input: "-1*2",
// expected: &BinaryExpr{
// Op: MUL,
// LHS: &NumberLiteral{
// Val: -1,
// PosRange: posrange.PositionRange{Start: 0, End: 2},
// },
// RHS: &NumberLiteral{
// Val: 2,
// PosRange: posrange.PositionRange{Start: 3, End: 4},
// },
// },
// },
// {
// input: "-1+2",
// expected: &BinaryExpr{
// Op: ADD,
// LHS: &NumberLiteral{
// Val: -1,
// PosRange: posrange.PositionRange{Start: 0, End: 2},
// },
// RHS: &NumberLiteral{
// Val: 2,
// PosRange: posrange.PositionRange{Start: 3, End: 4},
// },
// },
// },
// {
// input: "-1^-2",
// expected: &UnaryExpr{
// Op: SUB,
// Expr: &BinaryExpr{
// Op: POW,
// LHS: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 1, End: 2},
// },
// RHS: &NumberLiteral{
// Val: -2,
// PosRange: posrange.PositionRange{Start: 3, End: 5},
// },
// },
// },
// },
// {
// input: "+1 + -2 * 1",
// expected: &BinaryExpr{
// Op: ADD,
// LHS: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 0, End: 2},
// },
// RHS: &BinaryExpr{
// Op: MUL,
// LHS: &NumberLiteral{
// Val: -2,
// PosRange: posrange.PositionRange{Start: 5, End: 7},
// },
// RHS: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 10, End: 11},
// },
// },
// },
// },
// {
// input: "1 + 2/(3*1)",
// expected: &BinaryExpr{
// Op: ADD,
// LHS: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 0, End: 1},
// },
// RHS: &BinaryExpr{
// Op: DIV,
// LHS: &NumberLiteral{
// Val: 2,
// PosRange: posrange.PositionRange{Start: 4, End: 5},
// },
// RHS: &ParenExpr{
// Expr: &BinaryExpr{
// Op: MUL,
// LHS: &NumberLiteral{
// Val: 3,
// PosRange: posrange.PositionRange{Start: 7, End: 8},
// },
// RHS: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 9, End: 10},
// },
// },
// PosRange: posrange.PositionRange{Start: 6, End: 11},
// },
// },
// },
// },
// {
// input: "1 < bool 2 - 1 * 2",
// expected: &BinaryExpr{
// Op: LSS,
// ReturnBool: true,
// LHS: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 0, End: 1},
// },
// RHS: &BinaryExpr{
// Op: SUB,
// LHS: &NumberLiteral{
// Val: 2,
// PosRange: posrange.PositionRange{Start: 9, End: 10},
// },
// RHS: &BinaryExpr{
// Op: MUL,
// LHS: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 13, End: 14},
// },
// RHS: &NumberLiteral{
// Val: 2,
// PosRange: posrange.PositionRange{Start: 17, End: 18},
// },
// },
// },
// },
// },
// {
// input: "-some_metric",
// expected: &UnaryExpr{
// Op: SUB,
// Expr: &VectorSelector{
// Name: "some_metric",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "some_metric"),
// },
// PosRange: posrange.PositionRange{
// Start: 1,
// End: 12,
// },
// },
// },
// },
// {
// input: "+some_metric",
// expected: &UnaryExpr{
// Op: ADD,
// Expr: &VectorSelector{
// Name: "some_metric",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "some_metric"),
// },
// PosRange: posrange.PositionRange{
// Start: 1,
// End: 12,
// },
// },
// },
// },
// {
// input: " +some_metric",
// expected: &UnaryExpr{
// Op: ADD,
// Expr: &VectorSelector{
// Name: "some_metric",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "some_metric"),
// },
// PosRange: posrange.PositionRange{
// Start: 2,
// End: 13,
// },
// },
// StartPos: 1,
// },
// },
// {
// input: ` +{"some_metric"}`,
// expected: &UnaryExpr{
// Op: ADD,
// Expr: &VectorSelector{
// Name: "some_metric",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "some_metric"),
// },
// PosRange: posrange.PositionRange{
// Start: 2,
// End: 17,
// },
// },
// StartPos: 1,
// },
// },
// {
// input: "",
// fail: true,
// errMsg: "no expression found in input",
// },
// {
// input: "# just a comment\n\n",
// fail: true,
// errMsg: "no expression found in input",
// },
// {
// input: "1+",
// fail: true,
// errMsg: "unexpected end of input",
// },
// {
// input: ".",
// fail: true,
// errMsg: "unexpected character: '.'",
// },
// {
// input: "2.5.",
// fail: true,
// errMsg: "unexpected character: '.'",
// },
// {
// input: "100..4",
// fail: true,
// errMsg: `unexpected number ".4"`,
// },
// {
// input: "0deadbeef",
// fail: true,
// errMsg: "bad number or duration syntax: \"0de\"",
// },
// {
// input: "1 /",
// fail: true,
// errMsg: "unexpected end of input",
// },
// {
// input: "*1",
// fail: true,
// errMsg: "unexpected <op:*>",
// },
// {
// input: "(1))",
// fail: true,
// errMsg: "unexpected right parenthesis ')'",
// },
// {
// input: "((1)",
// fail: true,
// errMsg: "unclosed left parenthesis",
// },
// {
// input: "999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999",
// fail: true,
// errMsg: "out of range",
// },
// {
// input: "(",
// fail: true,
// errMsg: "unclosed left parenthesis",
// },
// {
// input: "1 and 1",
// fail: true,
// errMsg: "set operator \"and\" not allowed in binary scalar expression",
// },
// {
// input: "1 == 1",
// fail: true,
// errMsg: "1:3: parse error: comparisons between scalars must use BOOL modifier",
// },
// {
// input: "1 or 1",
// fail: true,
// errMsg: "set operator \"or\" not allowed in binary scalar expression",
// },
// {
// input: "1 unless 1",
// fail: true,
// errMsg: "set operator \"unless\" not allowed in binary scalar expression",
// },
// {
// input: "1 !~ 1",
// fail: true,
// errMsg: `unexpected character after '!': '~'`,
// },
// {
// input: "1 =~ 1",
// fail: true,
// errMsg: `unexpected character after '=': '~'`,
// },
// {
// input: `-"string"`,
// fail: true,
// errMsg: `unary expression only allowed on expressions of type scalar or instant vector, got "string"`,
// },
// {
// input: `-test[5m]`,
// fail: true,
// errMsg: `unary expression only allowed on expressions of type scalar or instant vector, got "range vector"`,
// },
// {
// input: `*test`,
// fail: true,
// errMsg: "unexpected <op:*>",
// },
// {
// input: "1 offset 1d",
// fail: true,
// errMsg: "1:1: parse error: offset modifier must be preceded by an instant vector selector or range vector selector or a subquery",
// },
// {
// input: "foo offset 1s offset 2s",
// fail: true,
// errMsg: "offset may not be set multiple times",
// },
// {
// input: "a - on(b) ignoring(c) d",
// fail: true,
// errMsg: "1:11: parse error: unexpected <ignoring>",
// },
// // Vector binary operations.
// {
// input: "foo * bar",
// expected: &BinaryExpr{
// Op: MUL,
// LHS: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 3,
// },
// },
// RHS: &VectorSelector{
// Name: "bar",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "bar"),
// },
// PosRange: posrange.PositionRange{
// Start: 6,
// End: 9,
// },
// },
// VectorMatching: &VectorMatching{Card: CardOneToOne},
// },
// },
// {
// input: "foo * sum",
// expected: &BinaryExpr{
// Op: MUL,
// LHS: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 3,
// },
// },
// RHS: &VectorSelector{
// Name: "sum",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "sum"),
// },
// PosRange: posrange.PositionRange{
// Start: 6,
// End: 9,
// },
// },
// VectorMatching: &VectorMatching{Card: CardOneToOne},
// },
// },
// {
// input: "foo == 1",
// expected: &BinaryExpr{
// Op: EQLC,
// LHS: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 3,
// },
// },
// RHS: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 7, End: 8},
// },
// },
// },
// {
// input: "foo == bool 1",
// expected: &BinaryExpr{
// Op: EQLC,
// LHS: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 3,
// },
// },
// RHS: &NumberLiteral{
// Val: 1,
// PosRange: posrange.PositionRange{Start: 12, End: 13},
// },
// ReturnBool: true,
// },
// },
// {
// input: "2.5 / bar",
// expected: &BinaryExpr{
// Op: DIV,
// LHS: &NumberLiteral{
// Val: 2.5,
// PosRange: posrange.PositionRange{Start: 0, End: 3},
// },
// RHS: &VectorSelector{
// Name: "bar",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "bar"),
// },
// PosRange: posrange.PositionRange{
// Start: 6,
// End: 9,
// },
// },
// },
// },
// {
// input: "foo and bar",
// expected: &BinaryExpr{
// Op: LAND,
// LHS: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 3,
// },
// },
// RHS: &VectorSelector{
// Name: "bar",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "bar"),
// },
// PosRange: posrange.PositionRange{
// Start: 8,
// End: 11,
// },
// },
// VectorMatching: &VectorMatching{Card: CardManyToMany},
// },
// },
// {
// input: "foo or bar",
// expected: &BinaryExpr{
// Op: LOR,
// LHS: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 3,
// },
// },
// RHS: &VectorSelector{
// Name: "bar",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "bar"),
// },
// PosRange: posrange.PositionRange{
// Start: 7,
// End: 10,
// },
// },
// VectorMatching: &VectorMatching{Card: CardManyToMany},
// },
// },
// {
// input: "foo unless bar",
// expected: &BinaryExpr{
// Op: LUNLESS,
// LHS: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 3,
// },
// },
// RHS: &VectorSelector{
// Name: "bar",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "bar"),
// },
// PosRange: posrange.PositionRange{
// Start: 11,
// End: 14,
// },
// },
// VectorMatching: &VectorMatching{Card: CardManyToMany},
// },
// },
// {
// // Test and/or precedence and reassigning of operands.
// input: "foo + bar or bla and blub",
// expected: &BinaryExpr{
// Op: LOR,
// LHS: &BinaryExpr{
// Op: ADD,
// LHS: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 3,
// },
// },
// RHS: &VectorSelector{
// Name: "bar",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "bar"),
// },
// PosRange: posrange.PositionRange{
// Start: 6,
// End: 9,
// },
// },
// VectorMatching: &VectorMatching{Card: CardOneToOne},
// },
// RHS: &BinaryExpr{
// Op: LAND,
// LHS: &VectorSelector{
// Name: "bla",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "bla"),
// },
// PosRange: posrange.PositionRange{
// Start: 13,
// End: 16,
// },
// },
// RHS: &VectorSelector{
// Name: "blub",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "blub"),
// },
// PosRange: posrange.PositionRange{
// Start: 21,
// End: 25,
// },
// },
// VectorMatching: &VectorMatching{Card: CardManyToMany},
// },
// VectorMatching: &VectorMatching{Card: CardManyToMany},
// },
// },
// {
// // Test and/or/unless precedence.
// input: "foo and bar unless baz or qux",
// expected: &BinaryExpr{
// Op: LOR,
// LHS: &BinaryExpr{
// Op: LUNLESS,
// LHS: &BinaryExpr{
// Op: LAND,
// LHS: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 3,
// },
// },
// RHS: &VectorSelector{
// Name: "bar",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "bar"),
// },
// PosRange: posrange.PositionRange{
// Start: 8,
// End: 11,
// },
// },
// VectorMatching: &VectorMatching{Card: CardManyToMany},
// },
// RHS: &VectorSelector{
// Name: "baz",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "baz"),
// },
// PosRange: posrange.PositionRange{
// Start: 19,
// End: 22,
// },
// },
// VectorMatching: &VectorMatching{Card: CardManyToMany},
// },
// RHS: &VectorSelector{
// Name: "qux",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "qux"),
// },
// PosRange: posrange.PositionRange{
// Start: 26,
// End: 29,
// },
// },
// VectorMatching: &VectorMatching{Card: CardManyToMany},
// },
// },
// {
// // Test precedence and reassigning of operands.
// input: "bar + on(foo) bla / on(baz, buz) group_right(test) blub",
// expected: &BinaryExpr{
// Op: ADD,
// LHS: &VectorSelector{
// Name: "bar",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "bar"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 3,
// },
// },
// RHS: &BinaryExpr{
// Op: DIV,
// LHS: &VectorSelector{
// Name: "bla",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "bla"),
// },
// PosRange: posrange.PositionRange{
// Start: 14,
// End: 17,
// },
// },
// RHS: &VectorSelector{
// Name: "blub",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "blub"),
// },
// PosRange: posrange.PositionRange{
// Start: 51,
// End: 55,
// },
// },
// VectorMatching: &VectorMatching{
// Card: CardOneToMany,
// MatchingLabels: []string{"baz", "buz"},
// On: true,
// Include: []string{"test"},
// },
// },
// VectorMatching: &VectorMatching{
// Card: CardOneToOne,
// MatchingLabels: []string{"foo"},
// On: true,
// },
// },
// },
// {
// input: "foo * on(test,blub) bar",
// expected: &BinaryExpr{
// Op: MUL,
// LHS: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 3,
// },
// },
// RHS: &VectorSelector{
// Name: "bar",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "bar"),
// },
// PosRange: posrange.PositionRange{
// Start: 20,
// End: 23,
// },
// },
// VectorMatching: &VectorMatching{
// Card: CardOneToOne,
// MatchingLabels: []string{"test", "blub"},
// On: true,
// },
// },
// },
// {
// input: "foo * on(test,blub) group_left bar",
// expected: &BinaryExpr{
// Op: MUL,
// LHS: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 3,
// },
// },
// RHS: &VectorSelector{
// Name: "bar",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "bar"),
// },
// PosRange: posrange.PositionRange{
// Start: 31,
// End: 34,
// },
// },
// VectorMatching: &VectorMatching{
// Card: CardManyToOne,
// MatchingLabels: []string{"test", "blub"},
// On: true,
// },
// },
// },
// {
// input: "foo and on(test,blub) bar",
// expected: &BinaryExpr{
// Op: LAND,
// LHS: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 3,
// },
// },
// RHS: &VectorSelector{
// Name: "bar",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "bar"),
// },
// PosRange: posrange.PositionRange{
// Start: 22,
// End: 25,
// },
// },
// VectorMatching: &VectorMatching{
// Card: CardManyToMany,
// MatchingLabels: []string{"test", "blub"},
// On: true,
// },
// },
// },
// {
// input: "foo and on() bar",
// expected: &BinaryExpr{
// Op: LAND,
// LHS: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 3,
// },
// },
// RHS: &VectorSelector{
// Name: "bar",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "bar"),
// },
// PosRange: posrange.PositionRange{
// Start: 13,
// End: 16,
// },
// },
// VectorMatching: &VectorMatching{
// Card: CardManyToMany,
// MatchingLabels: []string{},
// On: true,
// },
// },
// },
// {
// input: "foo and ignoring(test,blub) bar",
// expected: &BinaryExpr{
// Op: LAND,
// LHS: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 3,
// },
// },
// RHS: &VectorSelector{
// Name: "bar",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "bar"),
// },
// PosRange: posrange.PositionRange{
// Start: 28,
// End: 31,
// },
// },
// VectorMatching: &VectorMatching{
// Card: CardManyToMany,
// MatchingLabels: []string{"test", "blub"},
// },
// },
// },
// {
// input: "foo and ignoring() bar",
// expected: &BinaryExpr{
// Op: LAND,
// LHS: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 3,
// },
// },
// RHS: &VectorSelector{
// Name: "bar",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "bar"),
// },
// PosRange: posrange.PositionRange{
// Start: 19,
// End: 22,
// },
// },
// VectorMatching: &VectorMatching{
// Card: CardManyToMany,
// MatchingLabels: []string{},
// },
// },
// },
// {
// input: "foo unless on(bar) baz",
// expected: &BinaryExpr{
// Op: LUNLESS,
// LHS: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 3,
// },
// },
// RHS: &VectorSelector{
// Name: "baz",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "baz"),
// },
// PosRange: posrange.PositionRange{
// Start: 19,
// End: 22,
// },
// },
// VectorMatching: &VectorMatching{
// Card: CardManyToMany,
// MatchingLabels: []string{"bar"},
// On: true,
// },
// },
// },
// {
// input: "foo / on(test,blub) group_left(bar) bar",
// expected: &BinaryExpr{
// Op: DIV,
// LHS: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 3,
// },
// },
// RHS: &VectorSelector{
// Name: "bar",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "bar"),
// },
// PosRange: posrange.PositionRange{
// Start: 36,
// End: 39,
// },
// },
// VectorMatching: &VectorMatching{
// Card: CardManyToOne,
// MatchingLabels: []string{"test", "blub"},
// On: true,
// Include: []string{"bar"},
// },
// },
// },
// {
// input: "foo / ignoring(test,blub) group_left(blub) bar",
// expected: &BinaryExpr{
// Op: DIV,
// LHS: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 3,
// },
// },
// RHS: &VectorSelector{
// Name: "bar",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "bar"),
// },
// PosRange: posrange.PositionRange{
// Start: 43,
// End: 46,
// },
// },
// VectorMatching: &VectorMatching{
// Card: CardManyToOne,
// MatchingLabels: []string{"test", "blub"},
// Include: []string{"blub"},
// },
// },
// },
// {
// input: "foo / ignoring(test,blub) group_left(bar) bar",
// expected: &BinaryExpr{
// Op: DIV,
// LHS: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 3,
// },
// },
// RHS: &VectorSelector{
// Name: "bar",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "bar"),
// },
// PosRange: posrange.PositionRange{
// Start: 42,
// End: 45,
// },
// },
// VectorMatching: &VectorMatching{
// Card: CardManyToOne,
// MatchingLabels: []string{"test", "blub"},
// Include: []string{"bar"},
// },
// },
// },
// {
// input: "foo - on(test,blub) group_right(bar,foo) bar",
// expected: &BinaryExpr{
// Op: SUB,
// LHS: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 3,
// },
// },
// RHS: &VectorSelector{
// Name: "bar",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "bar"),
// },
// PosRange: posrange.PositionRange{
// Start: 41,
// End: 44,
// },
// },
// VectorMatching: &VectorMatching{
// Card: CardOneToMany,
// MatchingLabels: []string{"test", "blub"},
// Include: []string{"bar", "foo"},
// On: true,
// },
// },
// },
// {
// input: "foo - ignoring(test,blub) group_right(bar,foo) bar",
// expected: &BinaryExpr{
// Op: SUB,
// LHS: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 3,
// },
// },
// RHS: &VectorSelector{
// Name: "bar",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "bar"),
// },
// PosRange: posrange.PositionRange{
// Start: 47,
// End: 50,
// },
// },
// VectorMatching: &VectorMatching{
// Card: CardOneToMany,
// MatchingLabels: []string{"test", "blub"},
// Include: []string{"bar", "foo"},
// },
// },
// },
// {
// input: "foo and 1",
// fail: true,
// errMsg: "set operator \"and\" not allowed in binary scalar expression",
// },
// {
// input: "1 and foo",
// fail: true,
// errMsg: "set operator \"and\" not allowed in binary scalar expression",
// },
// {
// input: "foo or 1",
// fail: true,
// errMsg: "set operator \"or\" not allowed in binary scalar expression",
// },
// {
// input: "1 or foo",
// fail: true,
// errMsg: "set operator \"or\" not allowed in binary scalar expression",
// },
// {
// input: "foo unless 1",
// fail: true,
// errMsg: "set operator \"unless\" not allowed in binary scalar expression",
// },
// {
// input: "1 unless foo",
// fail: true,
// errMsg: "set operator \"unless\" not allowed in binary scalar expression",
// },
// {
// input: "1 or on(bar) foo",
// fail: true,
// errMsg: "vector matching only allowed between instant vectors",
// },
// {
// input: "foo == on(bar) 10",
// fail: true,
// errMsg: "vector matching only allowed between instant vectors",
// },
// {
// input: "foo + group_left(baz) bar",
// fail: true,
// errMsg: "unexpected <group_left>",
// },
// {
// input: "foo and on(bar) group_left(baz) bar",
// fail: true,
// errMsg: "no grouping allowed for \"and\" operation",
// },
// {
// input: "foo and on(bar) group_right(baz) bar",
// fail: true,
// errMsg: "no grouping allowed for \"and\" operation",
// },
// {
// input: "foo or on(bar) group_left(baz) bar",
// fail: true,
// errMsg: "no grouping allowed for \"or\" operation",
// },
// {
// input: "foo or on(bar) group_right(baz) bar",
// fail: true,
// errMsg: "no grouping allowed for \"or\" operation",
// },
// {
// input: "foo unless on(bar) group_left(baz) bar",
// fail: true,
// errMsg: "no grouping allowed for \"unless\" operation",
// },
// {
// input: "foo unless on(bar) group_right(baz) bar",
// fail: true,
// errMsg: "no grouping allowed for \"unless\" operation",
// },
// {
// input: `http_requests{group="production"} + on(instance) group_left(job,instance) cpu_count{type="smp"}`,
// fail: true,
// errMsg: "label \"instance\" must not occur in ON and GROUP clause at once",
// },
// {
// input: "foo + bool bar",
// fail: true,
// errMsg: "bool modifier can only be used on comparison operators",
// },
// {
// input: "foo + bool 10",
// fail: true,
// errMsg: "bool modifier can only be used on comparison operators",
// },
// {
// input: "foo and bool 10",
// fail: true,
// errMsg: "bool modifier can only be used on comparison operators",
// },
// // Test Vector selector.
// {
// input: "foo",
// expected: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 3,
// },
// },
// },
// {
// input: "min",
// expected: &VectorSelector{
// Name: "min",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "min"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 3,
// },
// },
// },
// {
// input: "foo offset 5m",
// expected: &VectorSelector{
// Name: "foo",
// OriginalOffset: 5 * time.Minute,
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 13,
// },
// },
// },
// {
// input: "foo offset -7m",
// expected: &VectorSelector{
// Name: "foo",
// OriginalOffset: -7 * time.Minute,
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 14,
// },
// },
// },
// {
// input: `foo OFFSET 1h30m`,
// expected: &VectorSelector{
// Name: "foo",
// OriginalOffset: 90 * time.Minute,
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 16,
// },
// },
// },
// {
// input: `foo OFFSET 1m30ms`,
// expected: &VectorSelector{
// Name: "foo",
// OriginalOffset: time.Minute + 30*time.Millisecond,
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 17,
// },
// },
// },
// {
// input: `foo @ 1603774568`,
// expected: &VectorSelector{
// Name: "foo",
// Timestamp: makeInt64Pointer(1603774568000),
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 16,
// },
// },
// },
// {
// input: `foo @ -100`,
// expected: &VectorSelector{
// Name: "foo",
// Timestamp: makeInt64Pointer(-100000),
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 10,
// },
// },
// },
// {
// input: `foo @ .3`,
// expected: &VectorSelector{
// Name: "foo",
// Timestamp: makeInt64Pointer(300),
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 8,
// },
// },
// },
// {
// input: `foo @ 3.`,
// expected: &VectorSelector{
// Name: "foo",
// Timestamp: makeInt64Pointer(3000),
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 8,
// },
// },
// },
// {
// input: `foo @ 3.33`,
// expected: &VectorSelector{
// Name: "foo",
// Timestamp: makeInt64Pointer(3330),
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 10,
// },
// },
// },
// { // Rounding off.
// input: `foo @ 3.3333`,
// expected: &VectorSelector{
// Name: "foo",
// Timestamp: makeInt64Pointer(3333),
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 12,
// },
// },
// },
// { // Rounding off.
// input: `foo @ 3.3335`,
// expected: &VectorSelector{
// Name: "foo",
// Timestamp: makeInt64Pointer(3334),
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 12,
// },
// },
// },
// {
// input: `foo @ 3e2`,
// expected: &VectorSelector{
// Name: "foo",
// Timestamp: makeInt64Pointer(300000),
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 9,
// },
// },
// },
// {
// input: `foo @ 3e-1`,
// expected: &VectorSelector{
// Name: "foo",
// Timestamp: makeInt64Pointer(300),
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 10,
// },
// },
// },
// {
// input: `foo @ 0xA`,
// expected: &VectorSelector{
// Name: "foo",
// Timestamp: makeInt64Pointer(10000),
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 9,
// },
// },
// },
// {
// input: `foo @ -3.3e1`,
// expected: &VectorSelector{
// Name: "foo",
// Timestamp: makeInt64Pointer(-33000),
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 12,
// },
// },
// },
// {
// input: `foo @ +Inf`,
// fail: true,
// errMsg: "1:1: parse error: timestamp out of bounds for @ modifier: +Inf",
// },
// {
// input: `foo @ -Inf`,
// fail: true,
// errMsg: "1:1: parse error: timestamp out of bounds for @ modifier: -Inf",
// },
// {
// input: `foo @ NaN`,
// fail: true,
// errMsg: "1:1: parse error: timestamp out of bounds for @ modifier: NaN",
// },
// {
// input: fmt.Sprintf(`foo @ %f`, float64(math.MaxInt64)+1),
// fail: true,
// errMsg: fmt.Sprintf("1:1: parse error: timestamp out of bounds for @ modifier: %f", float64(math.MaxInt64)+1),
// },
// {
// input: fmt.Sprintf(`foo @ %f`, float64(math.MinInt64)-1),
// fail: true,
// errMsg: fmt.Sprintf("1:1: parse error: timestamp out of bounds for @ modifier: %f", float64(math.MinInt64)-1),
// },
// {
// input: `foo:bar{a="bc"}`,
// expected: &VectorSelector{
// Name: "foo:bar",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, "a", "bc"),
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo:bar"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 15,
// },
// },
// },
{
input : ` { "foo"} ` ,
2021-02-09 08:03:16 -08:00
expected : & VectorSelector {
2023-12-08 10:53:39 -08:00
Name : "foo" ,
2021-02-09 08:03:16 -08:00
LabelMatchers : [ ] * labels . Matcher {
MustLabelMatcher ( labels . MatchEqual , model . MetricNameLabel , "foo" ) ,
2023-12-08 10:53:39 -08:00
MustLabelMatcher ( labels . MatchEqual , "a" , "bc" ) ,
2021-02-09 08:03:16 -08:00
} ,
2023-09-14 09:57:31 -07:00
PosRange : posrange . PositionRange {
2021-02-09 08:03:16 -08:00
Start : 0 ,
2023-12-08 10:53:39 -08:00
End : 6 ,
2021-08-12 09:38:06 -07:00
} ,
} ,
2021-02-09 08:03:16 -08:00
} ,
2023-12-08 10:53:39 -08:00
// {
// input: `{"foo", a="bc"}`,
// expected: &VectorSelector{
// Name: "foo:bar",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// MustLabelMatcher(labels.MatchEqual, "a", "bc"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 15,
// },
// },
// },
// {
// input: `foo{NaN='bc'}`,
// expected: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, "NaN", "bc"),
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 13,
// },
// },
// },
// {
// input: `foo{bar='}'}`,
// expected: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, "bar", "}"),
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 12,
// },
// },
// },
// {
// input: `foo{a="b", foo!="bar", test=~"test", bar!~"baz"}`,
// expected: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, "a", "b"),
// MustLabelMatcher(labels.MatchNotEqual, "foo", "bar"),
// MustLabelMatcher(labels.MatchRegexp, "test", "test"),
// MustLabelMatcher(labels.MatchNotRegexp, "bar", "baz"),
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 48,
// },
// },
// },
// {
// input: `foo{a="b", foo!="bar", test=~"test", bar!~"baz",}`,
// expected: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, "a", "b"),
// MustLabelMatcher(labels.MatchNotEqual, "foo", "bar"),
// MustLabelMatcher(labels.MatchRegexp, "test", "test"),
// MustLabelMatcher(labels.MatchNotRegexp, "bar", "baz"),
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 49,
// },
// },
// },
// {
// input: `{`,
// fail: true,
// errMsg: "unexpected end of input inside braces",
// },
// {
// input: `}`,
// fail: true,
// errMsg: "unexpected character: '}'",
// },
// {
// input: `some{`,
// fail: true,
// errMsg: "unexpected end of input inside braces",
// },
// {
// input: `some}`,
// fail: true,
// errMsg: "unexpected character: '}'",
// },
// {
// input: `some_metric{a=b}`,
// fail: true,
// errMsg: "unexpected identifier \"b\" in label matching, expected string",
// },
// {
// input: `some_metric{a:b="b"}`,
// fail: true,
// errMsg: "unexpected character inside braces: ':'",
// },
// {
// input: `foo{a*"b"}`,
// fail: true,
// errMsg: "unexpected character inside braces: '*'",
// },
// {
// input: `foo{a>="b"}`,
// fail: true,
// // TODO(fabxc): willingly lexing wrong tokens allows for more precise error
// // messages from the parser - consider if this is an option.
// errMsg: "unexpected character inside braces: '>'",
// },
// {
// input: "some_metric{a=\"\xff\"}",
// fail: true,
// errMsg: "1:15: parse error: invalid UTF-8 rune",
// },
// {
// input: `foo{gibberish}`,
// fail: true,
// errMsg: `unexpected "}" in label matching, expected label matching operator`,
// },
// {
// input: `foo{1}`,
// fail: true,
// errMsg: "unexpected character inside braces: '1'",
// },
// {
// input: `{}`,
// fail: true,
// errMsg: "vector selector must contain at least one non-empty matcher",
// },
// {
// input: `{x=""}`,
// fail: true,
// errMsg: "vector selector must contain at least one non-empty matcher",
// },
// {
// input: `{x=~".*"}`,
// fail: true,
// errMsg: "vector selector must contain at least one non-empty matcher",
// },
// {
// input: `{x!~".+"}`,
// fail: true,
// errMsg: "vector selector must contain at least one non-empty matcher",
// },
// {
// input: `{x!="a"}`,
// fail: true,
// errMsg: "vector selector must contain at least one non-empty matcher",
// },
// {
// input: `foo{__name__="bar"}`,
// fail: true,
// errMsg: `metric name must not be set twice: "foo" or "bar"`,
// },
// {
// input: `foo{__name__= =}`,
// fail: true,
// errMsg: `1:15: parse error: unexpected "=" in label matching, expected string`,
// },
// {
// input: `foo{,}`,
// fail: true,
// errMsg: `unexpected "," in label matching, expected identifier or "}"`,
// },
// {
// input: `foo{__name__ == "bar"}`,
// fail: true,
// errMsg: `1:15: parse error: unexpected "=" in label matching, expected string`,
// },
// {
// input: `foo{__name__="bar" lol}`,
// fail: true,
// errMsg: `unexpected identifier "lol" in label matching, expected "," or "}"`,
// },
// // Test matrix selector.
// {
// input: "test[5s]",
// expected: &MatrixSelector{
// VectorSelector: &VectorSelector{
// Name: "test",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "test"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 4,
// },
// },
// Range: 5 * time.Second,
// EndPos: 8,
// },
// },
// {
// input: "test[5m]",
// expected: &MatrixSelector{
// VectorSelector: &VectorSelector{
// Name: "test",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "test"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 4,
// },
// },
// Range: 5 * time.Minute,
// EndPos: 8,
// },
// },
// {
// input: `foo[5m30s]`,
// expected: &MatrixSelector{
// VectorSelector: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 3,
// },
// },
// Range: 5*time.Minute + 30*time.Second,
// EndPos: 10,
// },
// },
// {
// input: "test[5h] OFFSET 5m",
// expected: &MatrixSelector{
// VectorSelector: &VectorSelector{
// Name: "test",
// OriginalOffset: 5 * time.Minute,
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "test"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 4,
// },
// },
// Range: 5 * time.Hour,
// EndPos: 18,
// },
// },
// {
// input: "test[5d] OFFSET 10s",
// expected: &MatrixSelector{
// VectorSelector: &VectorSelector{
// Name: "test",
// OriginalOffset: 10 * time.Second,
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "test"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 4,
// },
// },
// Range: 5 * 24 * time.Hour,
// EndPos: 19,
// },
// },
// {
// input: "test[5w] offset 2w",
// expected: &MatrixSelector{
// VectorSelector: &VectorSelector{
// Name: "test",
// OriginalOffset: 14 * 24 * time.Hour,
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "test"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 4,
// },
// },
// Range: 5 * 7 * 24 * time.Hour,
// EndPos: 18,
// },
// },
// {
// input: `test{a="b"}[5y] OFFSET 3d`,
// expected: &MatrixSelector{
// VectorSelector: &VectorSelector{
// Name: "test",
// OriginalOffset: 3 * 24 * time.Hour,
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, "a", "b"),
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "test"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 11,
// },
// },
// Range: 5 * 365 * 24 * time.Hour,
// EndPos: 25,
// },
// },
// {
// input: `test{a="b"}[5y] @ 1603774699`,
// expected: &MatrixSelector{
// VectorSelector: &VectorSelector{
// Name: "test",
// Timestamp: makeInt64Pointer(1603774699000),
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, "a", "b"),
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "test"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 11,
// },
// },
// Range: 5 * 365 * 24 * time.Hour,
// EndPos: 28,
// },
// },
// {
// input: `foo[5mm]`,
// fail: true,
// errMsg: "bad duration syntax: \"5mm\"",
// },
// {
// input: `foo[5m1]`,
// fail: true,
// errMsg: "bad duration syntax: \"5m1\"",
// },
// {
// input: `foo[5m:1m1]`,
// fail: true,
// errMsg: "bad number or duration syntax: \"1m1\"",
// },
// {
// input: `foo[5y1hs]`,
// fail: true,
// errMsg: "unknown unit \"hs\" in duration \"5y1hs\"",
// },
// {
// input: `foo[5m1h]`,
// fail: true,
// errMsg: "not a valid duration string: \"5m1h\"",
// },
// {
// input: `foo[5m1m]`,
// fail: true,
// errMsg: "not a valid duration string: \"5m1m\"",
// },
// {
// input: `foo[0m]`,
// fail: true,
// errMsg: "duration must be greater than 0",
// },
// {
// input: `foo["5m"]`,
// fail: true,
// },
// {
// input: `foo[]`,
// fail: true,
// errMsg: "missing unit character in duration",
// },
// {
// input: `foo[1]`,
// fail: true,
// errMsg: "missing unit character in duration",
// },
// {
// input: `some_metric[5m] OFFSET 1`,
// fail: true,
// errMsg: "unexpected number \"1\" in offset, expected duration",
// },
// {
// input: `some_metric[5m] OFFSET 1mm`,
// fail: true,
// errMsg: "bad number or duration syntax: \"1mm\"",
// },
// {
// input: `some_metric[5m] OFFSET`,
// fail: true,
// errMsg: "unexpected end of input in offset, expected duration",
// },
// {
// input: `some_metric OFFSET 1m[5m]`,
// fail: true,
// errMsg: "1:22: parse error: no offset modifiers allowed before range",
// },
// {
// input: `some_metric[5m] @ 1m`,
// fail: true,
// errMsg: "1:19: parse error: unexpected duration \"1m\" in @, expected timestamp",
// },
// {
// input: `some_metric[5m] @`,
// fail: true,
// errMsg: "1:18: parse error: unexpected end of input in @, expected timestamp",
// },
// {
// input: `some_metric @ 1234 [5m]`,
// fail: true,
// errMsg: "1:20: parse error: no @ modifiers allowed before range",
// },
// {
// input: `(foo + bar)[5m]`,
// fail: true,
// errMsg: "1:12: parse error: ranges only allowed for vector selectors",
// },
// // Test aggregation.
// {
// input: "sum by (foo)(some_metric)",
// expected: &AggregateExpr{
// Op: SUM,
// Expr: &VectorSelector{
// Name: "some_metric",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "some_metric"),
// },
// PosRange: posrange.PositionRange{
// Start: 13,
// End: 24,
// },
// },
// Grouping: []string{"foo"},
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 25,
// },
// },
// },
// {
// input: "avg by (foo)(some_metric)",
// expected: &AggregateExpr{
// Op: AVG,
// Expr: &VectorSelector{
// Name: "some_metric",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "some_metric"),
// },
// PosRange: posrange.PositionRange{
// Start: 13,
// End: 24,
// },
// },
// Grouping: []string{"foo"},
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 25,
// },
// },
// },
// {
// input: "max by (foo)(some_metric)",
// expected: &AggregateExpr{
// Op: MAX,
// Expr: &VectorSelector{
// Name: "some_metric",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "some_metric"),
// },
// PosRange: posrange.PositionRange{
// Start: 13,
// End: 24,
// },
// },
// Grouping: []string{"foo"},
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 25,
// },
// },
// },
// {
// input: "sum without (foo) (some_metric)",
// expected: &AggregateExpr{
// Op: SUM,
// Without: true,
// Expr: &VectorSelector{
// Name: "some_metric",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "some_metric"),
// },
// PosRange: posrange.PositionRange{
// Start: 19,
// End: 30,
// },
// },
// Grouping: []string{"foo"},
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 31,
// },
// },
// },
// {
// input: "sum (some_metric) without (foo)",
// expected: &AggregateExpr{
// Op: SUM,
// Without: true,
// Expr: &VectorSelector{
// Name: "some_metric",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "some_metric"),
// },
// PosRange: posrange.PositionRange{
// Start: 5,
// End: 16,
// },
// },
// Grouping: []string{"foo"},
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 31,
// },
// },
// },
// {
// input: "stddev(some_metric)",
// expected: &AggregateExpr{
// Op: STDDEV,
// Expr: &VectorSelector{
// Name: "some_metric",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "some_metric"),
// },
// PosRange: posrange.PositionRange{
// Start: 7,
// End: 18,
// },
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 19,
// },
// },
// },
// {
// input: "stdvar by (foo)(some_metric)",
// expected: &AggregateExpr{
// Op: STDVAR,
// Expr: &VectorSelector{
// Name: "some_metric",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "some_metric"),
// },
// PosRange: posrange.PositionRange{
// Start: 16,
// End: 27,
// },
// },
// Grouping: []string{"foo"},
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 28,
// },
// },
// },
// {
// input: "sum by ()(some_metric)",
// expected: &AggregateExpr{
// Op: SUM,
// Expr: &VectorSelector{
// Name: "some_metric",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "some_metric"),
// },
// PosRange: posrange.PositionRange{
// Start: 10,
// End: 21,
// },
// },
// Grouping: []string{},
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 22,
// },
// },
// },
// {
// input: "sum by (foo,bar,)(some_metric)",
// expected: &AggregateExpr{
// Op: SUM,
// Expr: &VectorSelector{
// Name: "some_metric",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "some_metric"),
// },
// PosRange: posrange.PositionRange{
// Start: 18,
// End: 29,
// },
// },
// Grouping: []string{"foo", "bar"},
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 30,
// },
// },
// },
// {
// input: "sum by (foo,)(some_metric)",
// expected: &AggregateExpr{
// Op: SUM,
// Expr: &VectorSelector{
// Name: "some_metric",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "some_metric"),
// },
// PosRange: posrange.PositionRange{
// Start: 14,
// End: 25,
// },
// },
// Grouping: []string{"foo"},
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 26,
// },
// },
// },
// {
// input: "topk(5, some_metric)",
// expected: &AggregateExpr{
// Op: TOPK,
// Expr: &VectorSelector{
// Name: "some_metric",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "some_metric"),
// },
// PosRange: posrange.PositionRange{
// Start: 8,
// End: 19,
// },
// },
// Param: &NumberLiteral{
// Val: 5,
// PosRange: posrange.PositionRange{
// Start: 5,
// End: 6,
// },
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 20,
// },
// },
// },
// {
// input: `count_values("value", some_metric)`,
// expected: &AggregateExpr{
// Op: COUNT_VALUES,
// Expr: &VectorSelector{
// Name: "some_metric",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "some_metric"),
// },
// PosRange: posrange.PositionRange{
// Start: 22,
// End: 33,
// },
// },
// Param: &StringLiteral{
// Val: "value",
// PosRange: posrange.PositionRange{
// Start: 13,
// End: 20,
// },
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 34,
// },
// },
// },
// {
// // Test usage of keywords as label names.
// input: "sum without(and, by, avg, count, alert, annotations)(some_metric)",
// expected: &AggregateExpr{
// Op: SUM,
// Without: true,
// Expr: &VectorSelector{
// Name: "some_metric",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "some_metric"),
// },
// PosRange: posrange.PositionRange{
// Start: 53,
// End: 64,
// },
// },
// Grouping: []string{"and", "by", "avg", "count", "alert", "annotations"},
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 65,
// },
// },
// },
// {
// input: "sum without(==)(some_metric)",
// fail: true,
// errMsg: "unexpected <op:==> in grouping opts, expected label",
// },
// {
// input: "sum without(,)(some_metric)",
// fail: true,
// errMsg: `unexpected "," in grouping opts, expected label`,
// },
// {
// input: "sum without(foo,,)(some_metric)",
// fail: true,
// errMsg: `unexpected "," in grouping opts, expected label`,
// },
// {
// input: `sum some_metric by (test)`,
// fail: true,
// errMsg: "unexpected identifier \"some_metric\"",
// },
// {
// input: `sum (some_metric) by test`,
// fail: true,
// errMsg: "unexpected identifier \"test\" in grouping opts",
// },
// {
// input: `sum (some_metric) by test`,
// fail: true,
// errMsg: "unexpected identifier \"test\" in grouping opts",
// },
// {
// input: `sum () by (test)`,
// fail: true,
// errMsg: "no arguments for aggregate expression provided",
// },
// {
// input: "MIN keep_common (some_metric)",
// fail: true,
// errMsg: "1:5: parse error: unexpected identifier \"keep_common\"",
// },
// {
// input: "MIN (some_metric) keep_common",
// fail: true,
// errMsg: `unexpected identifier "keep_common"`,
// },
// {
// input: `sum (some_metric) without (test) by (test)`,
// fail: true,
// errMsg: "unexpected <by>",
// },
// {
// input: `sum without (test) (some_metric) by (test)`,
// fail: true,
// errMsg: "unexpected <by>",
// },
// {
// input: `topk(some_metric)`,
// fail: true,
// errMsg: "wrong number of arguments for aggregate expression provided, expected 2, got 1",
// },
// {
// input: `topk(some_metric,)`,
// fail: true,
// errMsg: "trailing commas not allowed in function call args",
// },
// {
// input: `topk(some_metric, other_metric)`,
// fail: true,
// errMsg: "1:6: parse error: expected type scalar in aggregation parameter, got instant vector",
// },
// {
// input: `count_values(5, other_metric)`,
// fail: true,
// errMsg: "1:14: parse error: expected type string in aggregation parameter, got scalar",
// },
// {
// input: `rate(some_metric[5m]) @ 1234`,
// fail: true,
// errMsg: "1:1: parse error: @ modifier must be preceded by an instant vector selector or range vector selector or a subquery",
// },
// // Test function calls.
// {
// input: "time()",
// expected: &Call{
// Func: MustGetFunction("time"),
// Args: Expressions{},
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 6,
// },
// },
// },
// {
// input: `floor(some_metric{foo!="bar"})`,
// expected: &Call{
// Func: MustGetFunction("floor"),
// Args: Expressions{
// &VectorSelector{
// Name: "some_metric",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchNotEqual, "foo", "bar"),
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "some_metric"),
// },
// PosRange: posrange.PositionRange{
// Start: 6,
// End: 29,
// },
// },
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 30,
// },
// },
// },
// {
// input: "rate(some_metric[5m])",
// expected: &Call{
// Func: MustGetFunction("rate"),
// Args: Expressions{
// &MatrixSelector{
// VectorSelector: &VectorSelector{
// Name: "some_metric",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "some_metric"),
// },
// PosRange: posrange.PositionRange{
// Start: 5,
// End: 16,
// },
// },
// Range: 5 * time.Minute,
// EndPos: 20,
// },
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 21,
// },
// },
// },
// {
// input: "round(some_metric)",
// expected: &Call{
// Func: MustGetFunction("round"),
// Args: Expressions{
// &VectorSelector{
// Name: "some_metric",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "some_metric"),
// },
// PosRange: posrange.PositionRange{
// Start: 6,
// End: 17,
// },
// },
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 18,
// },
// },
// },
// {
// input: "round(some_metric, 5)",
// expected: &Call{
// Func: MustGetFunction("round"),
// Args: Expressions{
// &VectorSelector{
// Name: "some_metric",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "some_metric"),
// },
// PosRange: posrange.PositionRange{
// Start: 6,
// End: 17,
// },
// },
// &NumberLiteral{
// Val: 5,
// PosRange: posrange.PositionRange{
// Start: 19,
// End: 20,
// },
// },
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 21,
// },
// },
// },
// {
// input: "floor()",
// fail: true,
// errMsg: "expected 1 argument(s) in call to \"floor\", got 0",
// },
// {
// input: "floor(some_metric, other_metric)",
// fail: true,
// errMsg: "expected 1 argument(s) in call to \"floor\", got 2",
// },
// {
// input: "floor(some_metric, 1)",
// fail: true,
// errMsg: "expected 1 argument(s) in call to \"floor\", got 2",
// },
// {
// input: "floor(1)",
// fail: true,
// errMsg: "expected type instant vector in call to function \"floor\", got scalar",
// },
// {
// input: "hour(some_metric, some_metric, some_metric)",
// fail: true,
// errMsg: "expected at most 1 argument(s) in call to \"hour\", got 3",
// },
// {
// input: "time(some_metric)",
// fail: true,
// errMsg: "expected 0 argument(s) in call to \"time\", got 1",
// },
// {
// input: "non_existent_function_far_bar()",
// fail: true,
// errMsg: "unknown function with name \"non_existent_function_far_bar\"",
// },
// {
// input: "rate(some_metric)",
// fail: true,
// errMsg: "expected type range vector in call to function \"rate\", got instant vector",
// },
// {
// input: "label_replace(a, `b`, `c\xff`, `d`, `.*`)",
// fail: true,
// errMsg: "1:23: parse error: invalid UTF-8 rune",
// },
// // Fuzzing regression tests.
// {
// input: "-=",
// fail: true,
// errMsg: `unexpected "="`,
// },
// {
// input: "++-++-+-+-<",
// fail: true,
// errMsg: `unexpected <op:<>`,
// },
// {
// input: "e-+=/(0)",
// fail: true,
// errMsg: `unexpected "="`,
// },
// {
// input: "a>b()",
// fail: true,
// errMsg: `unknown function`,
// },
// {
// input: "rate(avg)",
// fail: true,
// errMsg: `expected type range vector`,
// },
// {
// // This is testing that we are not re-rendering the expression string for each error, which would timeout.
// input: "(" + strings.Repeat("-{}-1", 10000) + ")" + strings.Repeat("[1m:]", 1000),
// fail: true,
// errMsg: `1:3: parse error: vector selector must contain at least one non-empty matcher`,
// },
// {
// input: "sum(sum)",
// expected: &AggregateExpr{
// Op: SUM,
// Expr: &VectorSelector{
// Name: "sum",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "sum"),
// },
// PosRange: posrange.PositionRange{
// Start: 4,
// End: 7,
// },
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 8,
// },
// },
// },
// {
// input: "a + sum",
// expected: &BinaryExpr{
// Op: ADD,
// LHS: &VectorSelector{
// Name: "a",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "a"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 1,
// },
// },
// RHS: &VectorSelector{
// Name: "sum",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "sum"),
// },
// PosRange: posrange.PositionRange{
// Start: 4,
// End: 7,
// },
// },
// VectorMatching: &VectorMatching{},
// },
// },
// // String quoting and escape sequence interpretation tests.
// {
// input: `"double-quoted string \" with escaped quote"`,
// expected: &StringLiteral{
// Val: "double-quoted string \" with escaped quote",
// PosRange: posrange.PositionRange{Start: 0, End: 44},
// },
// },
// {
// input: `'single-quoted string \' with escaped quote'`,
// expected: &StringLiteral{
// Val: "single-quoted string ' with escaped quote",
// PosRange: posrange.PositionRange{Start: 0, End: 44},
// },
// },
// {
// input: "`backtick-quoted string`",
// expected: &StringLiteral{
// Val: "backtick-quoted string",
// PosRange: posrange.PositionRange{Start: 0, End: 24},
// },
// },
// {
// input: `"\a\b\f\n\r\t\v\\\" - \xFF\377\u1234\U00010111\U0001011111☺"`,
// expected: &StringLiteral{
// Val: "\a\b\f\n\r\t\v\\\" - \xFF\377\u1234\U00010111\U0001011111☺",
// PosRange: posrange.PositionRange{Start: 0, End: 62},
// },
// },
// {
// input: `'\a\b\f\n\r\t\v\\\' - \xFF\377\u1234\U00010111\U0001011111☺'`,
// expected: &StringLiteral{
// Val: "\a\b\f\n\r\t\v\\' - \xFF\377\u1234\U00010111\U0001011111☺",
// PosRange: posrange.PositionRange{Start: 0, End: 62},
// },
// },
// {
// input: "`" + `\a\b\f\n\r\t\v\\\"\' - \xFF\377\u1234\U00010111\U0001011111☺` + "`",
// expected: &StringLiteral{
// Val: `\a\b\f\n\r\t\v\\\"\' - \xFF\377\u1234\U00010111\U0001011111☺`,
// PosRange: posrange.PositionRange{Start: 0, End: 64},
// },
// },
// {
// input: "`\\``",
// fail: true,
// errMsg: "unterminated raw string",
// },
// {
// input: `"\`,
// fail: true,
// errMsg: "escape sequence not terminated",
// },
// {
// input: `"\c"`,
// fail: true,
// errMsg: "unknown escape sequence U+0063 'c'",
// },
// {
// input: `"\x."`,
// fail: true,
// errMsg: "illegal character U+002E '.' in escape sequence",
// },
// // Subquery.
// {
// input: `foo{bar="baz"}[10m:6s]`,
// expected: &SubqueryExpr{
// Expr: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, "bar", "baz"),
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 14,
// },
// },
// Range: 10 * time.Minute,
// Step: 6 * time.Second,
// EndPos: 22,
// },
// },
// {
// input: `foo{bar="baz"}[10m5s:1h6ms]`,
// expected: &SubqueryExpr{
// Expr: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, "bar", "baz"),
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 14,
// },
// },
// Range: 10*time.Minute + 5*time.Second,
// Step: time.Hour + 6*time.Millisecond,
// EndPos: 27,
// },
// },
// {
// input: `foo[10m:]`,
// expected: &SubqueryExpr{
// Expr: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 3,
// },
// },
// Range: 10 * time.Minute,
// EndPos: 9,
// },
// },
// {
// input: `min_over_time(rate(foo{bar="baz"}[2s])[5m:5s])`,
// expected: &Call{
// Func: MustGetFunction("min_over_time"),
// Args: Expressions{
// &SubqueryExpr{
// Expr: &Call{
// Func: MustGetFunction("rate"),
// Args: Expressions{
// &MatrixSelector{
// VectorSelector: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, "bar", "baz"),
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 19,
// End: 33,
// },
// },
// Range: 2 * time.Second,
// EndPos: 37,
// },
// },
// PosRange: posrange.PositionRange{
// Start: 14,
// End: 38,
// },
// },
// Range: 5 * time.Minute,
// Step: 5 * time.Second,
// EndPos: 45,
// },
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 46,
// },
// },
// },
// {
// input: `min_over_time(rate(foo{bar="baz"}[2s])[5m:])[4m:3s]`,
// expected: &SubqueryExpr{
// Expr: &Call{
// Func: MustGetFunction("min_over_time"),
// Args: Expressions{
// &SubqueryExpr{
// Expr: &Call{
// Func: MustGetFunction("rate"),
// Args: Expressions{
// &MatrixSelector{
// VectorSelector: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, "bar", "baz"),
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 19,
// End: 33,
// },
// },
// Range: 2 * time.Second,
// EndPos: 37,
// },
// },
// PosRange: posrange.PositionRange{
// Start: 14,
// End: 38,
// },
// },
// Range: 5 * time.Minute,
// EndPos: 43,
// },
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 44,
// },
// },
// Range: 4 * time.Minute,
// Step: 3 * time.Second,
// EndPos: 51,
// },
// },
// {
// input: `min_over_time(rate(foo{bar="baz"}[2s])[5m:] offset 4m)[4m:3s]`,
// expected: &SubqueryExpr{
// Expr: &Call{
// Func: MustGetFunction("min_over_time"),
// Args: Expressions{
// &SubqueryExpr{
// Expr: &Call{
// Func: MustGetFunction("rate"),
// Args: Expressions{
// &MatrixSelector{
// VectorSelector: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, "bar", "baz"),
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 19,
// End: 33,
// },
// },
// Range: 2 * time.Second,
// EndPos: 37,
// },
// },
// PosRange: posrange.PositionRange{
// Start: 14,
// End: 38,
// },
// },
// Range: 5 * time.Minute,
// OriginalOffset: 4 * time.Minute,
// EndPos: 53,
// },
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 54,
// },
// },
// Range: 4 * time.Minute,
// Step: 3 * time.Second,
// EndPos: 61,
// },
// },
// {
// input: `min_over_time(rate(foo{bar="baz"}[2s])[5m:] @ 1603775091)[4m:3s]`,
// expected: &SubqueryExpr{
// Expr: &Call{
// Func: MustGetFunction("min_over_time"),
// Args: Expressions{
// &SubqueryExpr{
// Expr: &Call{
// Func: MustGetFunction("rate"),
// Args: Expressions{
// &MatrixSelector{
// VectorSelector: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, "bar", "baz"),
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 19,
// End: 33,
// },
// },
// Range: 2 * time.Second,
// EndPos: 37,
// },
// },
// PosRange: posrange.PositionRange{
// Start: 14,
// End: 38,
// },
// },
// Range: 5 * time.Minute,
// Timestamp: makeInt64Pointer(1603775091000),
// EndPos: 56,
// },
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 57,
// },
// },
// Range: 4 * time.Minute,
// Step: 3 * time.Second,
// EndPos: 64,
// },
// },
// {
// input: `min_over_time(rate(foo{bar="baz"}[2s])[5m:] @ -160377509)[4m:3s]`,
// expected: &SubqueryExpr{
// Expr: &Call{
// Func: MustGetFunction("min_over_time"),
// Args: Expressions{
// &SubqueryExpr{
// Expr: &Call{
// Func: MustGetFunction("rate"),
// Args: Expressions{
// &MatrixSelector{
// VectorSelector: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, "bar", "baz"),
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 19,
// End: 33,
// },
// },
// Range: 2 * time.Second,
// EndPos: 37,
// },
// },
// PosRange: posrange.PositionRange{
// Start: 14,
// End: 38,
// },
// },
// Range: 5 * time.Minute,
// Timestamp: makeInt64Pointer(-160377509000),
// EndPos: 56,
// },
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 57,
// },
// },
// Range: 4 * time.Minute,
// Step: 3 * time.Second,
// EndPos: 64,
// },
// },
// {
// input: "sum without(and, by, avg, count, alert, annotations)(some_metric) [30m:10s]",
// expected: &SubqueryExpr{
// Expr: &AggregateExpr{
// Op: SUM,
// Without: true,
// Expr: &VectorSelector{
// Name: "some_metric",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "some_metric"),
// },
// PosRange: posrange.PositionRange{
// Start: 53,
// End: 64,
// },
// },
// Grouping: []string{"and", "by", "avg", "count", "alert", "annotations"},
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 65,
// },
// },
// Range: 30 * time.Minute,
// Step: 10 * time.Second,
// EndPos: 75,
// },
// },
// {
// input: `some_metric OFFSET 1m [10m:5s]`,
// expected: &SubqueryExpr{
// Expr: &VectorSelector{
// Name: "some_metric",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "some_metric"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 21,
// },
// OriginalOffset: 1 * time.Minute,
// },
// Range: 10 * time.Minute,
// Step: 5 * time.Second,
// EndPos: 30,
// },
// },
// {
// input: `some_metric @ 123 [10m:5s]`,
// expected: &SubqueryExpr{
// Expr: &VectorSelector{
// Name: "some_metric",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "some_metric"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 17,
// },
// Timestamp: makeInt64Pointer(123000),
// },
// Range: 10 * time.Minute,
// Step: 5 * time.Second,
// EndPos: 26,
// },
// },
// {
// input: `some_metric @ 123 offset 1m [10m:5s]`,
// expected: &SubqueryExpr{
// Expr: &VectorSelector{
// Name: "some_metric",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "some_metric"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 27,
// },
// Timestamp: makeInt64Pointer(123000),
// OriginalOffset: 1 * time.Minute,
// },
// Range: 10 * time.Minute,
// Step: 5 * time.Second,
// EndPos: 36,
// },
// },
// {
// input: `some_metric offset 1m @ 123 [10m:5s]`,
// expected: &SubqueryExpr{
// Expr: &VectorSelector{
// Name: "some_metric",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "some_metric"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 27,
// },
// Timestamp: makeInt64Pointer(123000),
// OriginalOffset: 1 * time.Minute,
// },
// Range: 10 * time.Minute,
// Step: 5 * time.Second,
// EndPos: 36,
// },
// },
// {
// input: `some_metric[10m:5s] offset 1m @ 123`,
// expected: &SubqueryExpr{
// Expr: &VectorSelector{
// Name: "some_metric",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "some_metric"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 11,
// },
// },
// Timestamp: makeInt64Pointer(123000),
// OriginalOffset: 1 * time.Minute,
// Range: 10 * time.Minute,
// Step: 5 * time.Second,
// EndPos: 35,
// },
// },
// {
// input: `(foo + bar{nm="val"})[5m:]`,
// expected: &SubqueryExpr{
// Expr: &ParenExpr{
// Expr: &BinaryExpr{
// Op: ADD,
// VectorMatching: &VectorMatching{
// Card: CardOneToOne,
// },
// LHS: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 1,
// End: 4,
// },
// },
// RHS: &VectorSelector{
// Name: "bar",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, "nm", "val"),
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "bar"),
// },
// PosRange: posrange.PositionRange{
// Start: 7,
// End: 20,
// },
// },
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 21,
// },
// },
// Range: 5 * time.Minute,
// EndPos: 26,
// },
// },
// {
// input: `(foo + bar{nm="val"})[5m:] offset 10m`,
// expected: &SubqueryExpr{
// Expr: &ParenExpr{
// Expr: &BinaryExpr{
// Op: ADD,
// VectorMatching: &VectorMatching{
// Card: CardOneToOne,
// },
// LHS: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 1,
// End: 4,
// },
// },
// RHS: &VectorSelector{
// Name: "bar",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, "nm", "val"),
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "bar"),
// },
// PosRange: posrange.PositionRange{
// Start: 7,
// End: 20,
// },
// },
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 21,
// },
// },
// Range: 5 * time.Minute,
// OriginalOffset: 10 * time.Minute,
// EndPos: 37,
// },
// },
// {
// input: `(foo + bar{nm="val"} @ 1234)[5m:] @ 1603775019`,
// expected: &SubqueryExpr{
// Expr: &ParenExpr{
// Expr: &BinaryExpr{
// Op: ADD,
// VectorMatching: &VectorMatching{
// Card: CardOneToOne,
// },
// LHS: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 1,
// End: 4,
// },
// },
// RHS: &VectorSelector{
// Name: "bar",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, "nm", "val"),
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "bar"),
// },
// Timestamp: makeInt64Pointer(1234000),
// PosRange: posrange.PositionRange{
// Start: 7,
// End: 27,
// },
// },
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 28,
// },
// },
// Range: 5 * time.Minute,
// Timestamp: makeInt64Pointer(1603775019000),
// EndPos: 46,
// },
// },
// {
// input: "test[5d] OFFSET 10s [10m:5s]",
// fail: true,
// errMsg: "1:1: parse error: subquery is only allowed on instant vector, got matrix",
// },
// {
// input: `(foo + bar{nm="val"})[5m:][10m:5s]`,
// fail: true,
// errMsg: `1:1: parse error: subquery is only allowed on instant vector, got matrix`,
// },
// {
// input: "rate(food[1m])[1h] offset 1h",
// fail: true,
// errMsg: `1:15: parse error: ranges only allowed for vector selectors`,
// },
// {
// input: "rate(food[1m])[1h] @ 100",
// fail: true,
// errMsg: `1:15: parse error: ranges only allowed for vector selectors`,
// },
// // Preprocessors.
// {
// input: `foo @ start()`,
// expected: &VectorSelector{
// Name: "foo",
// StartOrEnd: START,
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 13,
// },
// },
// },
// {
// input: `foo @ end()`,
// expected: &VectorSelector{
// Name: "foo",
// StartOrEnd: END,
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 11,
// },
// },
// },
// {
// input: `test[5y] @ start()`,
// expected: &MatrixSelector{
// VectorSelector: &VectorSelector{
// Name: "test",
// StartOrEnd: START,
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "test"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 4,
// },
// },
// Range: 5 * 365 * 24 * time.Hour,
// EndPos: 18,
// },
// },
// {
// input: `test[5y] @ end()`,
// expected: &MatrixSelector{
// VectorSelector: &VectorSelector{
// Name: "test",
// StartOrEnd: END,
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "test"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 4,
// },
// },
// Range: 5 * 365 * 24 * time.Hour,
// EndPos: 16,
// },
// },
// {
// input: `foo[10m:6s] @ start()`,
// expected: &SubqueryExpr{
// Expr: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 3,
// },
// },
// Range: 10 * time.Minute,
// Step: 6 * time.Second,
// StartOrEnd: START,
// EndPos: 21,
// },
// },
// {
// input: `foo[10m:6s] @ end()`,
// expected: &SubqueryExpr{
// Expr: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 3,
// },
// },
// Range: 10 * time.Minute,
// Step: 6 * time.Second,
// StartOrEnd: END,
// EndPos: 19,
// },
// },
// {
// input: `start()`,
// fail: true,
// errMsg: `1:6: parse error: unexpected "("`,
// },
// {
// input: `end()`,
// fail: true,
// errMsg: `1:4: parse error: unexpected "("`,
// },
// // Check that start and end functions do not mask metrics.
// {
// input: `start`,
// expected: &VectorSelector{
// Name: "start",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "start"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 5,
// },
// },
// },
// {
// input: `end`,
// expected: &VectorSelector{
// Name: "end",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "end"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 3,
// },
// },
// },
// {
// input: `start{end="foo"}`,
// expected: &VectorSelector{
// Name: "start",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, "end", "foo"),
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "start"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 16,
// },
// },
// },
// {
// input: `end{start="foo"}`,
// expected: &VectorSelector{
// Name: "end",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, "start", "foo"),
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "end"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 16,
// },
// },
// },
// {
// input: `foo unless on(start) bar`,
// expected: &BinaryExpr{
// Op: LUNLESS,
// LHS: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 3,
// },
// },
// RHS: &VectorSelector{
// Name: "bar",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "bar"),
// },
// PosRange: posrange.PositionRange{
// Start: 21,
// End: 24,
// },
// },
// VectorMatching: &VectorMatching{
// Card: CardManyToMany,
// MatchingLabels: []string{"start"},
// On: true,
// },
// },
// },
// {
// input: `foo unless on(end) bar`,
// expected: &BinaryExpr{
// Op: LUNLESS,
// LHS: &VectorSelector{
// Name: "foo",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "foo"),
// },
// PosRange: posrange.PositionRange{
// Start: 0,
// End: 3,
// },
// },
// RHS: &VectorSelector{
// Name: "bar",
// LabelMatchers: []*labels.Matcher{
// MustLabelMatcher(labels.MatchEqual, model.MetricNameLabel, "bar"),
// },
// PosRange: posrange.PositionRange{
// Start: 19,
// End: 22,
// },
// },
// VectorMatching: &VectorMatching{
// Card: CardManyToMany,
// MatchingLabels: []string{"end"},
// On: true,
// },
// },
// },
2015-03-30 09:12:51 -07:00
}
2021-01-20 02:57:39 -08:00
func makeInt64Pointer ( val int64 ) * int64 {
valp := new ( int64 )
* valp = val
return valp
}
2023-12-08 10:53:39 -08:00
//{"foo", a="bc"}
2015-03-30 09:12:51 -07:00
func TestParseExpressions ( t * testing . T ) {
for _ , test := range testExpr {
2020-08-04 12:12:41 -07:00
t . Run ( test . input , func ( t * testing . T ) {
expr , err := ParseExpr ( test . input )
2015-08-03 03:53:31 -07:00
2020-08-04 12:12:41 -07:00
// Unexpected errors are always caused by a bug.
2020-10-29 02:43:23 -07:00
require . NotEqual ( t , err , errUnexpected , "unexpected error occurred" )
2015-03-30 09:12:51 -07:00
2020-08-04 12:12:41 -07:00
if ! test . fail {
2020-10-29 02:43:23 -07:00
require . NoError ( t , err )
require . Equal ( t , test . expected , expr , "error on input '%s'" , test . input )
2020-08-04 12:12:41 -07:00
} else {
2020-10-29 02:43:23 -07:00
require . Error ( t , err )
require . Contains ( t , err . Error ( ) , test . errMsg , "unexpected error on input '%s', expected '%s', got '%s'" , test . input , test . errMsg , err . Error ( ) )
2020-03-16 07:47:47 -07:00
2022-06-08 01:47:52 -07:00
var errorList ParseErrors
ok := errors . As ( err , & errorList )
2020-03-16 07:47:47 -07:00
2020-10-29 02:43:23 -07:00
require . True ( t , ok , "unexpected error type" )
2020-03-16 07:47:47 -07:00
2020-08-04 12:12:41 -07:00
for _ , e := range errorList {
2023-12-07 03:35:01 -08:00
require . LessOrEqual ( t , 0 , e . PositionRange . Start , "parse error has negative position\nExpression '%s'\nError: %v" , test . input , e )
require . LessOrEqual ( t , e . PositionRange . Start , e . PositionRange . End , "parse error has negative length\nExpression '%s'\nError: %v" , test . input , e )
require . LessOrEqual ( t , e . PositionRange . End , posrange . Pos ( len ( test . input ) ) , "parse error is not contained in input\nExpression '%s'\nError: %v" , test . input , e )
2020-08-04 12:12:41 -07:00
}
2020-03-16 07:47:47 -07:00
}
2020-08-04 12:12:41 -07:00
} )
2015-03-30 09:12:51 -07:00
}
}
// NaN has no equality. Thus, we need a separate test for it.
func TestNaNExpression ( t * testing . T ) {
2018-03-20 07:30:52 -07:00
expr , err := ParseExpr ( "NaN" )
2020-10-29 02:43:23 -07:00
require . NoError ( t , err )
2015-03-30 09:12:51 -07:00
nl , ok := expr . ( * NumberLiteral )
2020-10-29 02:43:23 -07:00
require . True ( t , ok , "expected number literal but got %T" , expr )
2023-04-09 00:08:40 -07:00
require . True ( t , math . IsNaN ( nl . Val ) , "expected 'NaN' in number literal but got %v" , nl . Val )
2015-03-30 09:12:51 -07:00
}
2015-05-11 05:04:53 -07:00
var testSeries = [ ] struct {
input string
2016-12-28 00:16:48 -08:00
expectedMetric labels . Labels
2020-02-03 08:45:41 -08:00
expectedValues [ ] SequenceValue
2015-05-11 05:04:53 -07:00
fail bool
} {
{
input : ` { } 1 2 3 ` ,
2022-07-21 09:23:30 -07:00
expectedMetric : labels . EmptyLabels ( ) ,
2015-05-11 05:04:53 -07:00
expectedValues : newSeq ( 1 , 2 , 3 ) ,
} , {
2016-12-28 00:16:48 -08:00
input : ` { a="b"} -1 2 3 ` ,
expectedMetric : labels . FromStrings ( "a" , "b" ) ,
2015-05-11 05:04:53 -07:00
expectedValues : newSeq ( - 1 , 2 , 3 ) ,
} , {
2016-12-28 00:16:48 -08:00
input : ` my_metric 1 2 3 ` ,
expectedMetric : labels . FromStrings ( labels . MetricName , "my_metric" ) ,
2015-05-11 05:04:53 -07:00
expectedValues : newSeq ( 1 , 2 , 3 ) ,
} , {
2016-12-28 00:16:48 -08:00
input : ` my_metric { } 1 2 3 ` ,
expectedMetric : labels . FromStrings ( labels . MetricName , "my_metric" ) ,
2015-05-11 05:04:53 -07:00
expectedValues : newSeq ( 1 , 2 , 3 ) ,
} , {
2016-12-28 00:16:48 -08:00
input : ` my_metric { a="b"} 1 2 3 ` ,
expectedMetric : labels . FromStrings ( labels . MetricName , "my_metric" , "a" , "b" ) ,
2015-05-11 05:04:53 -07:00
expectedValues : newSeq ( 1 , 2 , 3 ) ,
} , {
2016-12-28 00:16:48 -08:00
input : ` my_metric { a="b"} 1 2 3-10x4 ` ,
expectedMetric : labels . FromStrings ( labels . MetricName , "my_metric" , "a" , "b" ) ,
2015-05-11 05:04:53 -07:00
expectedValues : newSeq ( 1 , 2 , 3 , - 7 , - 17 , - 27 , - 37 ) ,
2015-06-04 09:21:24 -07:00
} , {
2016-12-28 00:16:48 -08:00
input : ` my_metric { a="b"} 1 2 3-0x4 ` ,
expectedMetric : labels . FromStrings ( labels . MetricName , "my_metric" , "a" , "b" ) ,
2015-06-04 09:21:24 -07:00
expectedValues : newSeq ( 1 , 2 , 3 , 3 , 3 , 3 , 3 ) ,
2023-08-25 14:35:42 -07:00
} , {
input : ` { } 1+1 ` ,
fail : true ,
} , {
input : ` { } 1x0 ` ,
expectedMetric : labels . EmptyLabels ( ) ,
expectedValues : newSeq ( 1 ) ,
} , {
input : ` { } 1+1x0 ` ,
expectedMetric : labels . EmptyLabels ( ) ,
expectedValues : newSeq ( 1 ) ,
2015-05-11 05:04:53 -07:00
} , {
2016-12-28 00:16:48 -08:00
input : ` my_metric { a="b"} 1 3 _ 5 _x4 ` ,
expectedMetric : labels . FromStrings ( labels . MetricName , "my_metric" , "a" , "b" ) ,
2015-05-11 05:04:53 -07:00
expectedValues : newSeq ( 1 , 3 , none , 5 , none , none , none , none ) ,
} , {
input : ` my_metric { a="b"} 1 3 _ 5 _a4 ` ,
fail : true ,
2018-09-13 01:08:01 -07:00
} , {
input : ` my_metric { a="b"} 1 -1 ` ,
expectedMetric : labels . FromStrings ( labels . MetricName , "my_metric" , "a" , "b" ) ,
expectedValues : newSeq ( 1 , - 1 ) ,
} , {
input : ` my_metric { a="b"} 1 +1 ` ,
expectedMetric : labels . FromStrings ( labels . MetricName , "my_metric" , "a" , "b" ) ,
expectedValues : newSeq ( 1 , 1 ) ,
} , {
input : ` my_metric { a="b"} 1 -1 -3-10x4 7 9 +5 ` ,
expectedMetric : labels . FromStrings ( labels . MetricName , "my_metric" , "a" , "b" ) ,
expectedValues : newSeq ( 1 , - 1 , - 3 , - 13 , - 23 , - 33 , - 43 , 7 , 9 , 5 ) ,
} , {
input : ` my_metric { a="b"} 1 +1 +4 -6 -2 8 ` ,
expectedMetric : labels . FromStrings ( labels . MetricName , "my_metric" , "a" , "b" ) ,
expectedValues : newSeq ( 1 , 1 , 4 , - 6 , - 2 , 8 ) ,
} , {
// Trailing spaces should be correctly handles.
input : ` my_metric { a="b"} 1 2 3 ` ,
expectedMetric : labels . FromStrings ( labels . MetricName , "my_metric" , "a" , "b" ) ,
expectedValues : newSeq ( 1 , 2 , 3 ) ,
2021-02-18 22:38:05 -08:00
} , {
// Handle escaped unicode characters as whole label values.
input : ` my_metric { a="\u70ac"} 1 2 3 ` ,
expectedMetric : labels . FromStrings ( labels . MetricName , "my_metric" , "a" , ` 炬 ` ) ,
expectedValues : newSeq ( 1 , 2 , 3 ) ,
} , {
// Handle escaped unicode characters as partial label values.
input : ` my_metric { a="\u70ac = torch"} 1 2 3 ` ,
expectedMetric : labels . FromStrings ( labels . MetricName , "my_metric" , "a" , ` 炬 = torch ` ) ,
expectedValues : newSeq ( 1 , 2 , 3 ) ,
2018-09-13 01:08:01 -07:00
} , {
input : ` my_metric { a="b"} -3-3 -3 ` ,
fail : true ,
} , {
input : ` my_metric { a="b"} -3 -3-3 ` ,
fail : true ,
} , {
input : ` my_metric { a="b"} -3 _-2 ` ,
fail : true ,
} , {
input : ` my_metric { a="b"} -3 3+3x4-4 ` ,
fail : true ,
2015-05-11 05:04:53 -07:00
} ,
}
2015-05-11 06:56:35 -07:00
// For these tests only, we use the smallest float64 to signal an omitted value.
2015-05-11 05:04:53 -07:00
const none = math . SmallestNonzeroFloat64
2020-02-03 08:45:41 -08:00
func newSeq ( vals ... float64 ) ( res [ ] SequenceValue ) {
2015-05-11 05:04:53 -07:00
for _ , v := range vals {
if v == none {
2020-02-03 10:23:07 -08:00
res = append ( res , SequenceValue { Omitted : true } )
2015-05-11 05:04:53 -07:00
} else {
2020-02-03 10:23:07 -08:00
res = append ( res , SequenceValue { Value : v } )
2015-05-11 05:04:53 -07:00
}
}
return res
}
2023-08-25 14:35:42 -07:00
func TestParseHistogramSeries ( t * testing . T ) {
for _ , test := range [ ] struct {
name string
input string
expected [ ] histogram . FloatHistogram
expectedError string
} {
{
name : "empty histogram" ,
input : "{} {{}}" ,
expected : [ ] histogram . FloatHistogram { { } } ,
} ,
{
name : "empty histogram with space" ,
input : "{} {{ }}" ,
expected : [ ] histogram . FloatHistogram { { } } ,
} ,
{
name : "all properties used" ,
input : ` { } {{ schema : 1 sum : -0.3 count : 3 .1 z_bucket : 7 .1 z_bucket_w : 0 .05 buckets : [ 5 .1 10 7 ] offset : -3 n_buckets : [ 4 .1 5 ] n_offset : -5 }} ` ,
expected : [ ] histogram . FloatHistogram { {
Schema : 1 ,
Sum : - 0.3 ,
Count : 3.1 ,
ZeroCount : 7.1 ,
ZeroThreshold : 0.05 ,
PositiveBuckets : [ ] float64 { 5.1 , 10 , 7 } ,
PositiveSpans : [ ] histogram . Span { { Offset : - 3 , Length : 3 } } ,
NegativeBuckets : [ ] float64 { 4.1 , 5 } ,
NegativeSpans : [ ] histogram . Span { { Offset : - 5 , Length : 2 } } ,
} } ,
} ,
{
name : "all properties used - with spaces" ,
input : ` { } {{ schema : 1 sum : 0 .3 count : 3 z_bucket : 7 z_bucket_w : 5 buckets : [ 5 10 7 ] offset : -3 n_buckets : [ 4 5 ] n_offset : 5 }} ` ,
expected : [ ] histogram . FloatHistogram { {
Schema : 1 ,
Sum : 0.3 ,
Count : 3 ,
ZeroCount : 7 ,
ZeroThreshold : 5 ,
PositiveBuckets : [ ] float64 { 5 , 10 , 7 } ,
PositiveSpans : [ ] histogram . Span { { Offset : - 3 , Length : 3 } } ,
NegativeBuckets : [ ] float64 { 4 , 5 } ,
NegativeSpans : [ ] histogram . Span { { Offset : 5 , Length : 2 } } ,
} } ,
} ,
{
name : "static series" ,
input : ` { } {{ buckets : [ 5 10 7 ] schema : 1 }} x2 ` ,
expected : [ ] histogram . FloatHistogram {
{
Schema : 1 ,
PositiveBuckets : [ ] float64 { 5 , 10 , 7 } ,
PositiveSpans : [ ] histogram . Span { {
Offset : 0 ,
Length : 3 ,
} } ,
} ,
{
Schema : 1 ,
PositiveBuckets : [ ] float64 { 5 , 10 , 7 } ,
PositiveSpans : [ ] histogram . Span { {
Offset : 0 ,
Length : 3 ,
} } ,
} ,
{
Schema : 1 ,
PositiveBuckets : [ ] float64 { 5 , 10 , 7 } ,
PositiveSpans : [ ] histogram . Span { {
Offset : 0 ,
Length : 3 ,
} } ,
} ,
} ,
} ,
{
name : "static series - x0" ,
input : ` { } {{ buckets : [ 5 10 7 ] schema : 1 }} x0 ` ,
expected : [ ] histogram . FloatHistogram {
{
Schema : 1 ,
PositiveBuckets : [ ] float64 { 5 , 10 , 7 } ,
PositiveSpans : [ ] histogram . Span { {
Offset : 0 ,
Length : 3 ,
} } ,
} ,
} ,
} ,
{
name : "2 histograms stated explicitly" ,
input : ` { } {{ buckets : [ 5 10 7 ] schema : 1 }} {{ buckets : [ 1 2 3 ] schema : 1 }} ` ,
expected : [ ] histogram . FloatHistogram {
{
Schema : 1 ,
PositiveBuckets : [ ] float64 { 5 , 10 , 7 } ,
PositiveSpans : [ ] histogram . Span { {
Offset : 0 ,
Length : 3 ,
} } ,
} ,
{
Schema : 1 ,
PositiveBuckets : [ ] float64 { 1 , 2 , 3 } ,
PositiveSpans : [ ] histogram . Span { {
Offset : 0 ,
Length : 3 ,
} } ,
} ,
} ,
} ,
{
name : "series with increment - with different schemas" ,
input : ` { } {{ buckets : [ 5 ] schema : 0 }} + {{ buckets : [ 1 2 ] schema : 1 }} x2 ` ,
expected : [ ] histogram . FloatHistogram {
{
PositiveBuckets : [ ] float64 { 5 } ,
PositiveSpans : [ ] histogram . Span { {
Offset : 0 ,
Length : 1 ,
} } ,
} ,
{
PositiveBuckets : [ ] float64 { 6 , 2 } ,
PositiveSpans : [ ] histogram . Span { {
Offset : 0 ,
Length : 2 ,
} } ,
} ,
{
PositiveBuckets : [ ] float64 { 7 , 4 } ,
PositiveSpans : [ ] histogram . Span { {
Offset : 0 ,
Length : 2 ,
} } ,
} ,
} ,
} ,
{
name : "series with decrement" ,
input : ` { } {{ buckets : [ 5 10 7 ] schema : 1 }} - {{ buckets : [ 1 2 3 ] schema : 1 }} x2 ` ,
expected : [ ] histogram . FloatHistogram {
{
Schema : 1 ,
PositiveBuckets : [ ] float64 { 5 , 10 , 7 } ,
PositiveSpans : [ ] histogram . Span { {
Offset : 0 ,
Length : 3 ,
} } ,
} ,
{
Schema : 1 ,
PositiveBuckets : [ ] float64 { 4 , 8 , 4 } ,
PositiveSpans : [ ] histogram . Span { {
Offset : 0 ,
Length : 3 ,
} } ,
} ,
{
Schema : 1 ,
PositiveBuckets : [ ] float64 { 3 , 6 , 1 } ,
PositiveSpans : [ ] histogram . Span { {
Offset : 0 ,
Length : 3 ,
} } ,
} ,
} ,
} ,
{
name : "series with increment - 0x" ,
input : ` { } {{ buckets : [ 5 10 7 ] schema : 1 }} + {{ buckets : [ 1 2 3 ] schema : 1 }} x0 ` ,
expected : [ ] histogram . FloatHistogram {
{
Schema : 1 ,
PositiveBuckets : [ ] float64 { 5 , 10 , 7 } ,
PositiveSpans : [ ] histogram . Span { {
Offset : 0 ,
Length : 3 ,
} } ,
} ,
} ,
} ,
{
name : "series with different schemas - second one is smaller" ,
input : ` { } {{ buckets : [ 5 10 7 ] schema : 1 }} + {{ buckets : [ 1 2 3 ] schema : 0 }} x2 ` ,
expectedError : ` 1:63: parse error: error combining histograms: cannot merge from schema 0 to 1 ` ,
} ,
{
name : "different order" ,
input : ` { } {{ buckets : [ 5 10 7 ] schema : 1 }} ` ,
expected : [ ] histogram . FloatHistogram { {
Schema : 1 ,
PositiveBuckets : [ ] float64 { 5 , 10 , 7 } ,
PositiveSpans : [ ] histogram . Span { {
Offset : 0 ,
Length : 3 ,
} } ,
} } ,
} ,
{
name : "double property" ,
input : ` { } {{ schema : 1 schema : 1 }} ` ,
expectedError : ` 1:1: parse error: duplicate key "schema" in histogram ` ,
} ,
{
name : "unknown property" ,
input : ` { } {{ foo : 1 }} ` ,
expectedError : ` 1:6: parse error: bad histogram descriptor found: "foo" ` ,
} ,
{
name : "space before :" ,
input : ` { } {{ schema : 1 }} ` ,
expectedError : "1:6: parse error: missing `:` for histogram descriptor" ,
} ,
{
name : "space after :" ,
input : ` { } {{ schema : 1 }} ` ,
expectedError : ` 1:13: parse error: unexpected " " in series values ` ,
} ,
{
name : "space after [" ,
input : ` { } {{ buckets : [ 1 ] }} ` ,
expectedError : ` 1:15: parse error: unexpected " " in series values ` ,
} ,
{
name : "space after {{" ,
input : ` { } {{ schema : 1 }} ` ,
expectedError : ` 1:7: parse error: unexpected "<Item 57372>" "schema" in series values ` ,
} ,
} {
t . Run ( test . name , func ( t * testing . T ) {
_ , vals , err := ParseSeriesDesc ( test . input )
if test . expectedError != "" {
require . EqualError ( t , err , test . expectedError )
return
}
require . NoError ( t , err )
var got [ ] histogram . FloatHistogram
for _ , v := range vals {
got = append ( got , * v . Histogram )
}
require . Equal ( t , test . expected , got )
} )
}
}
func TestHistogramTestExpression ( t * testing . T ) {
for _ , test := range [ ] struct {
name string
input histogram . FloatHistogram
expected string
} {
{
name : "single positive and negative span" ,
input : histogram . FloatHistogram {
Schema : 1 ,
Sum : - 0.3 ,
Count : 3.1 ,
ZeroCount : 7.1 ,
ZeroThreshold : 0.05 ,
PositiveBuckets : [ ] float64 { 5.1 , 10 , 7 } ,
PositiveSpans : [ ] histogram . Span { { Offset : - 3 , Length : 3 } } ,
NegativeBuckets : [ ] float64 { 4.1 , 5 } ,
NegativeSpans : [ ] histogram . Span { { Offset : - 5 , Length : 2 } } ,
} ,
expected : ` {{ schema : 1 count : 3 .1 sum : -0.3 z_bucket : 7 .1 z_bucket_w : 0 .05 offset : -3 buckets : [ 5 .1 10 7 ] n_offset : -5 n_buckets : [ 4 .1 5 ] }} ` ,
} ,
{
name : "multiple positive and negative spans" ,
input : histogram . FloatHistogram {
PositiveBuckets : [ ] float64 { 5.1 , 10 , 7 } ,
PositiveSpans : [ ] histogram . Span {
{ Offset : - 3 , Length : 1 } ,
{ Offset : 4 , Length : 2 } ,
} ,
NegativeBuckets : [ ] float64 { 4.1 , 5 , 7 , 8 , 9 } ,
NegativeSpans : [ ] histogram . Span {
{ Offset : - 1 , Length : 2 } ,
{ Offset : 2 , Length : 3 } ,
} ,
} ,
expected : ` {{ offset : -3 buckets : [ 5 .1 0 0 0 0 10 7 ] n_offset : -1 n_buckets : [ 4 .1 5 0 0 7 8 9 ] }} ` ,
} ,
} {
t . Run ( test . name , func ( t * testing . T ) {
expression := test . input . TestExpression ( )
require . Equal ( t , test . expected , expression )
_ , vals , err := ParseSeriesDesc ( "{} " + expression )
require . NoError ( t , err )
require . Len ( t , vals , 1 )
canonical := vals [ 0 ] . Histogram
require . NotNil ( t , canonical )
require . Equal ( t , test . expected , canonical . TestExpression ( ) )
} )
}
}
2015-05-11 05:04:53 -07:00
func TestParseSeries ( t * testing . T ) {
for _ , test := range testSeries {
2020-02-03 09:48:27 -08:00
metric , vals , err := ParseSeriesDesc ( test . input )
2015-08-03 03:53:31 -07:00
// Unexpected errors are always caused by a bug.
2020-10-29 02:43:23 -07:00
require . NotEqual ( t , err , errUnexpected , "unexpected error occurred" )
2015-08-03 03:53:31 -07:00
2019-10-09 17:06:53 -07:00
if ! test . fail {
2020-10-29 02:43:23 -07:00
require . NoError ( t , err )
require . Equal ( t , test . expectedMetric , metric , "error on input '%s'" , test . input )
require . Equal ( t , test . expectedValues , vals , "error in input '%s'" , test . input )
2018-03-20 07:30:52 -07:00
} else {
2020-10-29 02:43:23 -07:00
require . Error ( t , err )
2015-05-11 05:04:53 -07:00
}
}
}
2015-08-02 04:37:42 -07:00
2015-08-19 06:28:53 -07:00
func TestRecoverParserRuntime ( t * testing . T ) {
2023-03-22 02:02:10 -07:00
p := NewParser ( "foo bar" )
2015-08-02 04:37:42 -07:00
var err error
2018-11-12 10:47:13 -08:00
defer func ( ) {
2020-10-29 02:43:23 -07:00
require . Equal ( t , errUnexpected , err )
2018-11-12 10:47:13 -08:00
} ( )
defer p . recover ( & err )
2015-08-02 04:37:42 -07:00
// Cause a runtime panic.
var a [ ] int
a [ 123 ] = 1
}
2015-08-19 06:28:53 -07:00
func TestRecoverParserError ( t * testing . T ) {
2023-03-22 02:02:10 -07:00
p := NewParser ( "foo bar" )
2015-08-02 04:37:42 -07:00
var err error
2019-03-25 16:01:12 -07:00
e := errors . New ( "custom error" )
2015-08-02 04:37:42 -07:00
2015-08-25 17:04:01 -07:00
defer func ( ) {
2020-10-29 02:43:23 -07:00
require . Equal ( t , e . Error ( ) , err . Error ( ) )
2015-08-25 17:04:01 -07:00
} ( )
defer p . recover ( & err )
panic ( e )
2015-08-02 04:37:42 -07:00
}
2021-03-16 02:47:45 -07:00
func TestExtractSelectors ( t * testing . T ) {
for _ , tc := range [ ... ] struct {
input string
expected [ ] string
} {
{
"foo" ,
[ ] string { ` { __name__="foo"} ` } ,
} , {
` foo { bar="baz"} ` ,
[ ] string { ` { bar="baz", __name__="foo"} ` } ,
} , {
` foo { bar="baz"} / flip { flop="flap"} ` ,
[ ] string { ` { bar="baz", __name__="foo"} ` , ` { flop="flap", __name__="flip"} ` } ,
} , {
` rate(foo[5m]) ` ,
[ ] string { ` { __name__="foo"} ` } ,
} , {
` vector(1) ` ,
[ ] string { } ,
} ,
} {
expr , err := ParseExpr ( tc . input )
require . NoError ( t , err )
var expected [ ] [ ] * labels . Matcher
for _ , s := range tc . expected {
selector , err := ParseMetricSelector ( s )
require . NoError ( t , err )
expected = append ( expected , selector )
}
require . Equal ( t , expected , ExtractSelectors ( expr ) )
}
}
2023-03-22 02:02:10 -07:00
func TestParseCustomFunctions ( t * testing . T ) {
funcs := Functions
funcs [ "custom_func" ] = & Function {
Name : "custom_func" ,
ArgTypes : [ ] ValueType { ValueTypeMatrix } ,
ReturnType : ValueTypeVector ,
}
input := "custom_func(metric[1m])"
p := NewParser ( input , WithFunctions ( funcs ) )
expr , err := p . ParseExpr ( )
require . NoError ( t , err )
call , ok := expr . ( * Call )
require . True ( t , ok )
require . Equal ( t , "custom_func" , call . Func . Name )
}