Files
hetty/pkg/search/parser_test.go

250 lines
6.4 KiB
Go
Raw Permalink Normal View History

2020-11-16 22:14:58 +01:00
package search
import (
"errors"
"reflect"
2022-01-21 11:45:54 +01:00
"regexp"
2020-11-16 22:14:58 +01:00
"testing"
)
func TestParseQuery(t *testing.T) {
2021-04-25 16:23:53 +02:00
t.Parallel()
2020-11-16 22:14:58 +01:00
tests := []struct {
name string
input string
expectedExpression Expression
expectedError error
}{
{
name: "empty query",
input: "",
expectedExpression: nil,
expectedError: errors.New("search: unexpected EOF"),
2020-11-16 22:14:58 +01:00
},
{
name: "string literal expression",
input: "foobar",
2022-01-21 11:45:54 +01:00
expectedExpression: StringLiteral{Value: "foobar"},
2020-11-16 22:14:58 +01:00
expectedError: nil,
},
{
name: "boolean expression with equal operator",
input: "foo = bar",
2022-01-21 11:45:54 +01:00
expectedExpression: InfixExpression{
2020-11-16 22:14:58 +01:00
Operator: TokOpEq,
2022-01-21 11:45:54 +01:00
Left: StringLiteral{Value: "foo"},
Right: StringLiteral{Value: "bar"},
2020-11-16 22:14:58 +01:00
},
expectedError: nil,
},
{
name: "boolean expression with not equal operator",
input: "foo != bar",
2022-01-21 11:45:54 +01:00
expectedExpression: InfixExpression{
2020-11-16 22:14:58 +01:00
Operator: TokOpNotEq,
2022-01-21 11:45:54 +01:00
Left: StringLiteral{Value: "foo"},
Right: StringLiteral{Value: "bar"},
2020-11-16 22:14:58 +01:00
},
expectedError: nil,
},
{
name: "boolean expression with greater than operator",
input: "foo > bar",
2022-01-21 11:45:54 +01:00
expectedExpression: InfixExpression{
2020-11-16 22:14:58 +01:00
Operator: TokOpGt,
2022-01-21 11:45:54 +01:00
Left: StringLiteral{Value: "foo"},
Right: StringLiteral{Value: "bar"},
2020-11-16 22:14:58 +01:00
},
expectedError: nil,
},
{
name: "boolean expression with less than operator",
input: "foo < bar",
2022-01-21 11:45:54 +01:00
expectedExpression: InfixExpression{
2020-11-16 22:14:58 +01:00
Operator: TokOpLt,
2022-01-21 11:45:54 +01:00
Left: StringLiteral{Value: "foo"},
Right: StringLiteral{Value: "bar"},
2020-11-16 22:14:58 +01:00
},
expectedError: nil,
},
{
name: "boolean expression with greater than or equal operator",
input: "foo >= bar",
2022-01-21 11:45:54 +01:00
expectedExpression: InfixExpression{
2020-11-16 22:14:58 +01:00
Operator: TokOpGtEq,
2022-01-21 11:45:54 +01:00
Left: StringLiteral{Value: "foo"},
Right: StringLiteral{Value: "bar"},
2020-11-16 22:14:58 +01:00
},
expectedError: nil,
},
{
name: "boolean expression with less than or equal operator",
input: "foo <= bar",
2022-01-21 11:45:54 +01:00
expectedExpression: InfixExpression{
2020-11-16 22:14:58 +01:00
Operator: TokOpLtEq,
2022-01-21 11:45:54 +01:00
Left: StringLiteral{Value: "foo"},
Right: StringLiteral{Value: "bar"},
2020-11-16 22:14:58 +01:00
},
expectedError: nil,
},
{
name: "boolean expression with regular expression operator",
input: "foo =~ bar",
2022-01-21 11:45:54 +01:00
expectedExpression: InfixExpression{
2020-11-16 22:14:58 +01:00
Operator: TokOpRe,
2022-01-21 11:45:54 +01:00
Left: StringLiteral{Value: "foo"},
2022-03-15 19:32:29 +01:00
Right: RegexpLiteral{regexp.MustCompile("bar")},
2020-11-16 22:14:58 +01:00
},
expectedError: nil,
},
{
name: "boolean expression with not regular expression operator",
input: "foo !~ bar",
2022-01-21 11:45:54 +01:00
expectedExpression: InfixExpression{
2020-11-16 22:14:58 +01:00
Operator: TokOpNotRe,
2022-01-21 11:45:54 +01:00
Left: StringLiteral{Value: "foo"},
2022-03-15 19:32:29 +01:00
Right: RegexpLiteral{regexp.MustCompile("bar")},
2020-11-16 22:14:58 +01:00
},
expectedError: nil,
},
{
name: "boolean expression with AND, OR and NOT operators",
input: "foo AND bar OR NOT baz",
2022-01-21 11:45:54 +01:00
expectedExpression: InfixExpression{
2020-11-16 22:14:58 +01:00
Operator: TokOpAnd,
2022-01-21 11:45:54 +01:00
Left: StringLiteral{Value: "foo"},
Right: InfixExpression{
2020-11-16 22:14:58 +01:00
Operator: TokOpOr,
2022-01-21 11:45:54 +01:00
Left: StringLiteral{Value: "bar"},
Right: PrefixExpression{
2020-11-16 22:14:58 +01:00
Operator: TokOpNot,
2022-01-21 11:45:54 +01:00
Right: StringLiteral{Value: "baz"},
2020-11-16 22:14:58 +01:00
},
},
},
expectedError: nil,
},
{
name: "boolean expression with nested group",
input: "(foo AND bar) OR NOT baz",
2022-01-21 11:45:54 +01:00
expectedExpression: InfixExpression{
2020-11-16 22:14:58 +01:00
Operator: TokOpOr,
2022-01-21 11:45:54 +01:00
Left: InfixExpression{
2020-11-16 22:14:58 +01:00
Operator: TokOpAnd,
2022-01-21 11:45:54 +01:00
Left: StringLiteral{Value: "foo"},
Right: StringLiteral{Value: "bar"},
2020-11-16 22:14:58 +01:00
},
2022-01-21 11:45:54 +01:00
Right: PrefixExpression{
2020-11-16 22:14:58 +01:00
Operator: TokOpNot,
2022-01-21 11:45:54 +01:00
Right: StringLiteral{Value: "baz"},
2020-11-16 22:14:58 +01:00
},
},
expectedError: nil,
},
{
name: "implicit boolean expression with string literal operands",
input: "foo bar baz",
2022-01-21 11:45:54 +01:00
expectedExpression: InfixExpression{
2020-11-16 22:14:58 +01:00
Operator: TokOpAnd,
2022-01-21 11:45:54 +01:00
Left: InfixExpression{
2020-11-16 22:14:58 +01:00
Operator: TokOpAnd,
2022-01-21 11:45:54 +01:00
Left: StringLiteral{Value: "foo"},
Right: StringLiteral{Value: "bar"},
2020-11-16 22:14:58 +01:00
},
2022-01-21 11:45:54 +01:00
Right: StringLiteral{Value: "baz"},
2020-11-16 22:14:58 +01:00
},
expectedError: nil,
},
{
name: "implicit boolean expression nested in group",
input: "(foo bar)",
2022-01-21 11:45:54 +01:00
expectedExpression: InfixExpression{
Operator: TokOpAnd,
2022-01-21 11:45:54 +01:00
Left: StringLiteral{Value: "foo"},
Right: StringLiteral{Value: "bar"},
},
expectedError: nil,
},
2020-11-16 22:14:58 +01:00
{
name: "implicit and explicit boolean expression with string literal operands",
input: "foo bar OR baz yolo",
2022-01-21 11:45:54 +01:00
expectedExpression: InfixExpression{
2020-11-16 22:14:58 +01:00
Operator: TokOpAnd,
2022-01-21 11:45:54 +01:00
Left: InfixExpression{
2020-11-16 22:14:58 +01:00
Operator: TokOpAnd,
2022-01-21 11:45:54 +01:00
Left: StringLiteral{Value: "foo"},
Right: InfixExpression{
2020-11-16 22:14:58 +01:00
Operator: TokOpOr,
2022-01-21 11:45:54 +01:00
Left: StringLiteral{Value: "bar"},
Right: StringLiteral{Value: "baz"},
2020-11-16 22:14:58 +01:00
},
},
2022-01-21 11:45:54 +01:00
Right: StringLiteral{Value: "yolo"},
2020-11-16 22:14:58 +01:00
},
expectedError: nil,
},
{
name: "implicit boolean expression with comparison operands",
input: "foo=bar baz=~yolo",
2022-01-21 11:45:54 +01:00
expectedExpression: InfixExpression{
2020-11-16 22:14:58 +01:00
Operator: TokOpAnd,
2022-01-21 11:45:54 +01:00
Left: InfixExpression{
2020-11-16 22:14:58 +01:00
Operator: TokOpEq,
2022-01-21 11:45:54 +01:00
Left: StringLiteral{Value: "foo"},
Right: StringLiteral{Value: "bar"},
2020-11-16 22:14:58 +01:00
},
2022-01-21 11:45:54 +01:00
Right: InfixExpression{
2020-11-16 22:14:58 +01:00
Operator: TokOpRe,
2022-01-21 11:45:54 +01:00
Left: StringLiteral{Value: "baz"},
2022-03-15 19:32:29 +01:00
Right: RegexpLiteral{regexp.MustCompile("yolo")},
2020-11-16 22:14:58 +01:00
},
},
expectedError: nil,
},
{
name: "eq operator takes precedence over boolean ops",
input: "foo=bar OR baz=yolo",
2022-01-21 11:45:54 +01:00
expectedExpression: InfixExpression{
Operator: TokOpOr,
2022-01-21 11:45:54 +01:00
Left: InfixExpression{
Operator: TokOpEq,
2022-01-21 11:45:54 +01:00
Left: StringLiteral{Value: "foo"},
Right: StringLiteral{Value: "bar"},
},
2022-01-21 11:45:54 +01:00
Right: InfixExpression{
Operator: TokOpEq,
2022-01-21 11:45:54 +01:00
Left: StringLiteral{Value: "baz"},
Right: StringLiteral{Value: "yolo"},
},
},
expectedError: nil,
},
2020-11-16 22:14:58 +01:00
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
got, err := ParseQuery(tt.input)
assertError(t, tt.expectedError, err)
if !reflect.DeepEqual(tt.expectedExpression, got) {
t.Errorf("expected: %v, got: %v", tt.expectedExpression, got)
}
})
}
}
func assertError(t *testing.T, exp, got error) {
2021-04-25 16:23:53 +02:00
t.Helper()
2020-11-16 22:14:58 +01:00
switch {
case exp == nil && got != nil:
t.Fatalf("expected: nil, got: %v", got)
case exp != nil && got == nil:
t.Fatalf("expected: %v, got: nil", exp.Error())
case exp != nil && got != nil && exp.Error() != got.Error():
t.Fatalf("expected: %v, got: %v", exp.Error(), got.Error())
}
}