diff --git a/data-prepper-expression/build.gradle b/data-prepper-expression/build.gradle index 79ec5590c5..76e228794f 100644 --- a/data-prepper-expression/build.gradle +++ b/data-prepper-expression/build.gradle @@ -38,7 +38,7 @@ jacocoTestCoverageVerification { violationRules { rule { //in addition to core projects rule - this one checks for 100% code coverage for this project limit { - minimum = 0.8 //keep this at 100% + minimum = 1.0 //keep this at 100% } } } @@ -48,4 +48,3 @@ jacocoTestCoverageVerification { })) } } - diff --git a/data-prepper-expression/src/main/antlr/DataPrepperExpression.g4 b/data-prepper-expression/src/main/antlr/DataPrepperExpression.g4 index a70052a599..5fc6c1a6f8 100644 --- a/data-prepper-expression/src/main/antlr/DataPrepperExpression.g4 +++ b/data-prepper-expression/src/main/antlr/DataPrepperExpression.g4 @@ -69,9 +69,8 @@ setOperator unaryOperatorExpression : primary | setInitializer - | regexPattern | parenthesesExpression - | unaryNotOperatorExpression + | unaryOperator (primary | unaryOperatorExpression) ; parenthesesExpression @@ -87,13 +86,10 @@ setInitializer : LBRACE primary (SET_DELIMITER primary)* RBRACE ; -unaryNotOperatorExpression - : unaryOperator parenthesesExpression - | unaryOperator primary - ; unaryOperator : NOT + | SUBTRACT ; primary @@ -240,6 +236,7 @@ NOT_IN_SET : SPACE 'not in' SPACE; AND : SPACE 'and' SPACE; OR : SPACE 'or' SPACE; NOT : 'not' SPACE; +SUBTRACT : '-'; LPAREN : '('; RPAREN : ')'; LBRACE : '{'; diff --git a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/NotOperator.java b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/NotOperator.java index f9b679782e..cbca1bfe81 100644 --- a/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/NotOperator.java +++ b/data-prepper-expression/src/main/java/org/opensearch/dataprepper/expression/NotOperator.java @@ -20,7 +20,7 @@ class NotOperator implements Operator { @Override public boolean shouldEvaluate(final RuleContext ctx) { - return ctx.getRuleIndex() == DataPrepperExpressionParser.RULE_unaryNotOperatorExpression; + return ctx.getRuleIndex() == DataPrepperExpressionParser.RULE_unaryOperatorExpression; } @Override diff --git a/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/GrammarLexerTest.java b/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/GrammarLexerTest.java index e7ad164bf2..734b5a74a1 100644 --- a/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/GrammarLexerTest.java +++ b/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/GrammarLexerTest.java @@ -164,6 +164,11 @@ void testTokenFORWARDSLASH() { assertToken("/", DataPrepperExpressionLexer.FORWARDSLASH); } + @Test + void testTokenSUBTRACT() { + assertToken("-", DataPrepperExpressionLexer.SUBTRACT); + } + @Test void testSpaceInsignificant() { final String statement = " "; diff --git a/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/NotOperatorTest.java b/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/NotOperatorTest.java index 5843b12f76..7ed943f24c 100644 --- a/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/NotOperatorTest.java +++ b/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/NotOperatorTest.java @@ -26,7 +26,7 @@ class NotOperatorTest { @Test void testShouldEvaluate() { - when(ctx.getRuleIndex()).thenReturn(DataPrepperExpressionParser.RULE_unaryNotOperatorExpression); + when(ctx.getRuleIndex()).thenReturn(DataPrepperExpressionParser.RULE_unaryOperatorExpression); assertThat(objectUnderTest.shouldEvaluate(ctx), is(true)); when(ctx.getRuleIndex()).thenReturn(-1); assertThat(objectUnderTest.shouldEvaluate(ctx), is(false)); diff --git a/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/ParseTreeCoercionServiceTest.java b/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/ParseTreeCoercionServiceTest.java index 6f3f935465..325938fbc7 100644 --- a/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/ParseTreeCoercionServiceTest.java +++ b/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/ParseTreeCoercionServiceTest.java @@ -85,6 +85,18 @@ void testCoerceTerminalNodeFloatType() throws ExpressionCoercionException { assertThat(result, equalTo(testFloat)); } + @Test + void testCoerceTerminalNodeBooleanType() throws ExpressionCoercionException { + when(token.getType()).thenReturn(DataPrepperExpressionParser.Boolean); + final Boolean testBoolean = new Random().nextBoolean(); + when(terminalNode.getSymbol()).thenReturn(token); + when(terminalNode.getText()).thenReturn(String.valueOf(testBoolean)); + final Event testEvent = createTestEvent(new HashMap<>()); + final Object result = objectUnderTest.coercePrimaryTerminalNode(terminalNode, testEvent); + assertThat(result, instanceOf(Boolean.class)); + assertThat(result, equalTo(testBoolean)); + } + @Test void testCoerceTerminalNodeJsonPointerType() throws ExpressionCoercionException { final String testKey1 = "key1"; diff --git a/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/ParseTreeCompositeExceptionTest.java b/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/ParseTreeCompositeExceptionTest.java index e8e72863b0..9445ed81c3 100644 --- a/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/ParseTreeCompositeExceptionTest.java +++ b/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/ParseTreeCompositeExceptionTest.java @@ -31,7 +31,7 @@ void testEmptyListThrows() { @Test void testGivenSingleExceptionThenExceptionIsCause() { final RuntimeException mock = mock(RuntimeException.class); - final ParseTreeCompositeException parseTreeCompositeException = new ParseTreeCompositeException(Arrays.asList(mock)); + final ParseTreeCompositeException parseTreeCompositeException = new ParseTreeCompositeException(Collections.singletonList(mock)); assertThat(parseTreeCompositeException.getCause(), is(mock)); } @@ -54,4 +54,19 @@ void testMultipleExceptionsPrinted() throws ParseTreeCompositeException { assertThat(message, containsString("|-- java.lang.RuntimeException: Error")); assertThat(message, containsString("|-- java.lang.NullPointerException: Throwable was null!")); } + + @Test + void testExceptionWithoutStackTrace() { + final RuntimeException error1 = new RuntimeException("Error1"); + error1.setStackTrace(new StackTraceElement[0]); + final RuntimeException error2 = new RuntimeException("Error2"); + error2.setStackTrace(new StackTraceElement[0]); + final ParseTreeCompositeException parseTreeCompositeException = new ParseTreeCompositeException(Arrays.asList(error1, error2)); + + assertThat(parseTreeCompositeException.getCause() instanceof ExceptionOverview, is(true)); + final String message = parseTreeCompositeException.getCause().getMessage(); + assertThat(message, containsString("Multiple exceptions (2)")); + assertThat(message, containsString("|-- java.lang.RuntimeException: Error2")); + assertThat(message, containsString("|-- java.lang.RuntimeException: Error1")); + } } diff --git a/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/ParseTreeExpressionTest.java b/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/ParseTreeExpressionTest.java index dea9d54d7d..75196c6d09 100644 --- a/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/ParseTreeExpressionTest.java +++ b/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/ParseTreeExpressionTest.java @@ -336,8 +336,7 @@ void testNotOperationOrder() { REGEX_OPERATOR_EXPRESSION, RELATIONAL_OPERATOR_EXPRESSION, SET_OPERATOR_EXPRESSION, - UNARY_OPERATOR_EXPRESSION, - UNARY_NOT_OPERATOR_EXPRESSION + UNARY_OPERATOR_EXPRESSION ).withChildrenMatching( isOperator(UNARY_OPERATOR), isUnaryTree() @@ -370,8 +369,7 @@ void testNotPriorityOperationOrder() { REGEX_OPERATOR_EXPRESSION, RELATIONAL_OPERATOR_EXPRESSION, SET_OPERATOR_EXPRESSION, - UNARY_OPERATOR_EXPRESSION, - UNARY_NOT_OPERATOR_EXPRESSION + UNARY_OPERATOR_EXPRESSION ).withChildrenMatching(isOperator(UNARY_OPERATOR), parenthesesExpression); assertThat(expression, isExpression(not)); diff --git a/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/ParseTreeTest.java b/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/ParseTreeTest.java index 600a488004..57940efcc8 100644 --- a/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/ParseTreeTest.java +++ b/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/ParseTreeTest.java @@ -11,6 +11,8 @@ import org.junit.jupiter.api.Test; import org.opensearch.dataprepper.expression.util.GrammarTest; +import java.util.function.Function; + import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.opensearch.dataprepper.expression.util.ContextMatcher.hasContext; @@ -199,4 +201,35 @@ void testValidJsonPointerCharacterSet() { assertThat(expression, isExpression(isJsonPointerUnaryTree())); assertThat(errorListener.isErrorFound(), is(false)); } + + @Test + void testSubtractOperator() { + final ParserRuleContext expression = parseExpression("/status_code == -200"); + + final DiagnosingMatcher lhs = isJsonPointerUnaryTree(); + final Function, DiagnosingMatcher> isNegative = + rhs -> hasContext(UNARY_OPERATOR_EXPRESSION, isOperator(UNARY_OPERATOR), rhs); + final DiagnosingMatcher doubleNegative200 = isNegative.apply(isUnaryTree()); + + final DiagnosingMatcher rhs = isParseTree( + REGEX_OPERATOR_EXPRESSION, + RELATIONAL_OPERATOR_EXPRESSION, + SET_OPERATOR_EXPRESSION + ).withChildrenMatching( + doubleNegative200 + ); + + final DiagnosingMatcher equalsExpression = isParseTree( + CONDITIONAL_EXPRESSION, + EQUALITY_OPERATOR_EXPRESSION + ).withChildrenMatching( + lhs, + isOperator(EQUALITY_OPERATOR), + rhs + ); + + + assertThat(expression, isExpression(equalsExpression)); + assertThat(errorListener.isErrorFound(), is(false)); + } } diff --git a/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/ParserTest.java b/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/ParserTest.java index 2c321a36d2..be085a0c70 100644 --- a/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/ParserTest.java +++ b/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/ParserTest.java @@ -137,6 +137,20 @@ void testValidOptionalSpaceOperators(final String expression) { assertThatIsValid(expression); } + @ParameterizedTest + @ValueSource(strings = { + "not false", + "not not false", + "not /status_code", + "not (true)", + "-5", + "-3.14", + "-(5)" + }) + void testValidUnaryOperators(final String expression) { + assertThatIsValid(expression); + } + @ParameterizedTest @ValueSource(strings = { "falkse and true", diff --git a/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/util/GrammarTest.java b/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/util/GrammarTest.java index da5b5c055a..e3790660bf 100644 --- a/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/util/GrammarTest.java +++ b/data-prepper-expression/src/test/java/org/opensearch/dataprepper/expression/util/GrammarTest.java @@ -16,16 +16,14 @@ public abstract class GrammarTest { //region ParseTree child classes - protected static final Class EXPRESSION = DataPrepperExpressionParser.ExpressionContext.class; - protected static final Class CONDITIONAL_EXPRESSION = DataPrepperExpressionParser.ConditionalExpressionContext.class; + protected static final Class CONDITIONAL_EXPRESSION = + DataPrepperExpressionParser.ConditionalExpressionContext.class; protected static final Class CONDITIONAL_OPERATOR = DataPrepperExpressionParser.ConditionalOperatorContext.class; protected static final Class EQUALITY_OPERATOR_EXPRESSION = DataPrepperExpressionParser.EqualityOperatorExpressionContext.class; protected static final Class EQUALITY_OPERATOR = DataPrepperExpressionParser.EqualityOperatorContext.class; protected static final Class REGEX_OPERATOR_EXPRESSION = DataPrepperExpressionParser.RegexOperatorExpressionContext.class; - protected static final Class REGEX_EQUALITY_OPERATOR = - DataPrepperExpressionParser.RegexEqualityOperatorContext.class; protected static final Class RELATIONAL_OPERATOR_EXPRESSION = DataPrepperExpressionParser.RelationalOperatorExpressionContext.class; protected static final Class RELATIONAL_OPERATOR = DataPrepperExpressionParser.RelationalOperatorContext.class; @@ -33,11 +31,10 @@ public abstract class GrammarTest { DataPrepperExpressionParser.SetOperatorExpressionContext.class; protected static final Class UNARY_OPERATOR_EXPRESSION = DataPrepperExpressionParser.UnaryOperatorExpressionContext.class; - protected static final Class UNARY_NOT_OPERATOR_EXPRESSION = - DataPrepperExpressionParser.UnaryNotOperatorExpressionContext.class; protected static final Class UNARY_OPERATOR = DataPrepperExpressionParser.UnaryOperatorContext.class; - protected static final Class PARENTHESES_EXPRESSION = DataPrepperExpressionParser.ParenthesesExpressionContext.class; + protected static final Class PARENTHESES_EXPRESSION = + DataPrepperExpressionParser.ParenthesesExpressionContext.class; //endregion protected ErrorListener errorListener;