Skip to content

Commit

Permalink
feat: emit error event when expression engine return parsing errors (#…
Browse files Browse the repository at this point in the history
…2311)

* make expression parser return a InvalidSyntaxError

* emit event in case of syntax error
  • Loading branch information
mathnogueira authored Apr 4, 2023
1 parent b9b6103 commit 125db30
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 11 deletions.
10 changes: 10 additions & 0 deletions server/executor/assertion_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,16 @@ func (e *defaultAssertionRunner) emitFailedAssertions(ctx context.Context, req A
))
}

if errors.Is(spanAssertionResult.CompareErr, expression.ErrInvalidSyntax) {
e.eventEmitter.Emit(ctx, events.TestSpecsAssertionError(
req.Run.TestID,
req.Run.ID,
spanAssertionResult.CompareErr,
spanAssertionResult.SpanID.String(),
string(assertionResult.Assertion),
))
}

}
}
}
Expand Down
26 changes: 26 additions & 0 deletions server/expression/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
)

var ErrExpressionResolution error = errors.New("resolution error")
var ErrInvalidSyntax error = errors.New("invalid syntax")

type ResolutionError struct {
innerErr error
Expand All @@ -31,3 +32,28 @@ func (e *ResolutionError) Unwrap() error {
func resolutionError(innerErr error) error {
return &ResolutionError{innerErr: innerErr}
}

type InvalidSyntaxError struct {
innerErr error
}

func (e *InvalidSyntaxError) Error() string {
return e.innerErr.Error()
}

func (e *InvalidSyntaxError) Is(target error) bool {
if errors.Is(target, ErrInvalidSyntax) {
return true
}

return errors.Is(e.innerErr, target)
}

func (e *InvalidSyntaxError) Unwrap() error {
return errors.Unwrap(e.innerErr)
}

func invalidSyntaxError(err error, expression string) error {
innerErr := fmt.Errorf(`invalid syntax "%s": %w`, expression, err)
return &InvalidSyntaxError{innerErr: innerErr}
}
6 changes: 3 additions & 3 deletions server/expression/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func NewExecutor(dataStores ...DataStore) Executor {
func (e Executor) Statement(statement string) (string, string, error) {
parsedStatement, err := ParseStatement(statement)
if err != nil {
return "", "", fmt.Errorf("could not parse statement: %w", err)
return "", "", err
}

leftValue, err := e.ResolveExpression(parsedStatement.Left)
Expand Down Expand Up @@ -77,7 +77,7 @@ func (e Executor) GetParsedStatement(statement string) (Statement, error) {
expression, err := Parse(statement)
if err != nil {
// it's really invalid
return Statement{}, fmt.Errorf("could not parse statement: %w", err)
return Statement{}, invalidSyntaxError(err, statement)
}

parsedStatement.Left = &expression
Expand Down Expand Up @@ -122,7 +122,7 @@ func (e Executor) Expression(expression string) (value.Value, error) {
var expr Expr
err = parser.ParseString("", expression, &expr)
if err != nil {
return value.Nil, fmt.Errorf(`could not parse expression "%s": %w`, expression, err)
return value.Nil, invalidSyntaxError(err, expression)
}

return e.ResolveExpression(&expr)
Expand Down
4 changes: 2 additions & 2 deletions server/expression/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func ParseStatement(statement string) (Statement, error) {

err = parser.ParseString("", statement, &parsedStatement)
if err != nil {
return Statement{}, fmt.Errorf(`could not parse statement "%s": %w`, statement, err)
return Statement{}, invalidSyntaxError(err, statement)
}

return parsedStatement, nil
Expand Down Expand Up @@ -63,7 +63,7 @@ func Parse(expression string) (Expr, error) {

err = parser.ParseString("", expression, &parsedExpression)
if err != nil {
return Expr{}, fmt.Errorf(`could not parse statement "%s": %w`, expression, err)
return Expr{}, invalidSyntaxError(err, expression)
}

return parsedExpression, nil
Expand Down
32 changes: 32 additions & 0 deletions server/expression/parser_errors_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package expression_test

import (
"errors"
"strings"
"testing"

"github.com/kubeshop/tracetest/server/expression"
"github.com/stretchr/testify/assert"
)

func TestStatementParsingErrors(t *testing.T) {
executor := expression.NewExecutor()
_, _, err := executor.Statement(`1 1 + = 2`)

assert.Error(t, err)
assert.True(t, strings.HasPrefix(err.Error(), `invalid syntax "1 1 + = 2": `))

unwrappedErr := errors.Unwrap(err)
assert.False(t, strings.HasPrefix(unwrappedErr.Error(), `invalid syntax "1 1 + = 2": `))
}

func TestExpressionParsingErrors(t *testing.T) {
executor := expression.NewExecutor()
_, err := executor.Expression(`attr:attribute env:number`)

assert.Error(t, err)
assert.True(t, strings.HasPrefix(err.Error(), `invalid syntax "attr:attribute env:number": `))

unwrappedErr := errors.Unwrap(err)
assert.False(t, strings.HasPrefix(unwrappedErr.Error(), `invalid syntax "attr:attribute env:number": `))
}
8 changes: 2 additions & 6 deletions server/expression/tokens.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
package expression

import (
"fmt"
)

type Token struct {
Identifier string
Type TermType
Expand All @@ -12,7 +8,7 @@ type Token struct {
func GetTokens(statement string) ([]Token, error) {
parsedStatement, err := ParseStatement(statement)
if err != nil {
return []Token{}, fmt.Errorf("could not parse statement: %w", err)
return []Token{}, invalidSyntaxError(err, statement)
}

leftTokens := extractTokensFromExpression(parsedStatement.Left)
Expand All @@ -31,7 +27,7 @@ func GetTokens(statement string) ([]Token, error) {
func GetTokensFromExpression(expression string) ([]Token, error) {
parsedExpression, err := Parse(expression)
if err != nil {
return []Token{}, fmt.Errorf("could not parse statement: %w", err)
return []Token{}, invalidSyntaxError(err, expression)
}

return extractTokensFromExpression(&parsedExpression), nil
Expand Down

0 comments on commit 125db30

Please sign in to comment.