From 6f5076471fcb7416170b8c059ca16b3554cde03b Mon Sep 17 00:00:00 2001 From: Philipp Ossler Date: Thu, 16 Jan 2025 13:31:44 +0100 Subject: [PATCH 1/3] test: Verify unary-test expressions Add test cases for unary-test expressions to verify that an expression returns false. (cherry picked from commit 113f7bc671a788fe00f50b2917fa13bdc43b284e) --- .../interpreter/InterpreterUnaryTest.scala | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/test/scala/org/camunda/feel/impl/interpreter/InterpreterUnaryTest.scala b/src/test/scala/org/camunda/feel/impl/interpreter/InterpreterUnaryTest.scala index fbdb8fa3d..07ed39913 100644 --- a/src/test/scala/org/camunda/feel/impl/interpreter/InterpreterUnaryTest.scala +++ b/src/test/scala/org/camunda/feel/impl/interpreter/InterpreterUnaryTest.scala @@ -655,4 +655,24 @@ class InterpreterUnaryTest evaluateUnaryTests("5 < ? or ? < 10", inputValue = null) should returnNull() } + it should "return true if it evaluates to true" in { + + evaluateUnaryTests("x", inputValue = 3, variables = Map("x" -> true)) should returnResult(true) + evaluateUnaryTests("4 < 10", 3) should returnResult(true) + evaluateUnaryTests("even(4)", 3) should returnResult(true) + evaluateUnaryTests("list contains([1,2,3], 3)", 3) should returnResult(true) + } + + it should "return false if it evaluates to false" in { + + evaluateUnaryTests( + expression = "x", + inputValue = 3, + variables = Map("x" -> false) + ) should returnResult(false) + evaluateUnaryTests(expression = "4 > 10", 3) should returnResult(false) + evaluateUnaryTests(expression = "odd(4)", 3) should returnResult(false) + evaluateUnaryTests(expression = "list contains([1,2], 3)", 3) should returnResult(false) + } + } From f1fb818104f56e4837d3897bc8a5a876f8853b4e Mon Sep 17 00:00:00 2001 From: Philipp Ossler Date: Thu, 16 Jan 2025 13:37:08 +0100 Subject: [PATCH 2/3] fix: Unary-test expression if value is false Fix a regression for unary-test expressions. If the expression evaluates to false and the input value is of a different type, the unary-test should return false instead of null. (cherry picked from commit 0a2ec197a76032049e9a28540bfede11e883566f) --- .../org/camunda/feel/impl/interpreter/FeelInterpreter.scala | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/scala/org/camunda/feel/impl/interpreter/FeelInterpreter.scala b/src/main/scala/org/camunda/feel/impl/interpreter/FeelInterpreter.scala index f721a22fc..1d078f369 100644 --- a/src/main/scala/org/camunda/feel/impl/interpreter/FeelInterpreter.scala +++ b/src/main/scala/org/camunda/feel/impl/interpreter/FeelInterpreter.scala @@ -672,6 +672,9 @@ class FeelInterpreter(private val valueMapper: ValueMapper) { case ValBoolean(true) => // the expression is the input value ValBoolean(true) + case _ if x == ValBoolean(false) => + // the expression is false + ValBoolean(false) case _ if x.isInstanceOf[ValList] => // the expression is a list but doesn't contain the input value ValBoolean(false) From 56f95cab138c34e415d3da6786b9fc5b8815ad97 Mon Sep 17 00:00:00 2001 From: Philipp Ossler Date: Thu, 16 Jan 2025 13:58:58 +0100 Subject: [PATCH 3/3] test: Verify unary-test negation Add test cases for the unary-test negation using not(). (cherry picked from commit b2edd820104ae743f53491ffec9c6d0cab489e63) --- .../interpreter/InterpreterUnaryTest.scala | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/src/test/scala/org/camunda/feel/impl/interpreter/InterpreterUnaryTest.scala b/src/test/scala/org/camunda/feel/impl/interpreter/InterpreterUnaryTest.scala index 07ed39913..103d0802a 100644 --- a/src/test/scala/org/camunda/feel/impl/interpreter/InterpreterUnaryTest.scala +++ b/src/test/scala/org/camunda/feel/impl/interpreter/InterpreterUnaryTest.scala @@ -675,4 +675,99 @@ class InterpreterUnaryTest evaluateUnaryTests(expression = "list contains([1,2], 3)", 3) should returnResult(false) } + "A negation" should "return true if it evaluates to a value that is not equal to the implicit value" in { + + evaluateUnaryTests("not(1)", 3) should returnResult(true) + evaluateUnaryTests(""" not("a") """, "b") should returnResult(true) + } + + it should "return false if it evaluates to a value that is equal to the implicit value" in { + + evaluateUnaryTests("not(3)", 3) should returnResult(false) + evaluateUnaryTests(""" not("b") """, "b") should returnResult(false) + } + + it should "return null if it evaluates to a value that has a different type than the implicit value" in { + + evaluateUnaryTests("not(1)", "b") should returnNull() + evaluateUnaryTests(""" not("a") """, 2) should returnNull() + } + + it should "return true if it evaluates to false when the implicit value is applied to it" in { + + evaluateUnaryTests("not(< 3)", 5) should returnResult(true) + evaluateUnaryTests("not([1..3])", 5) should returnResult(true) + evaluateUnaryTests("not(> x)", inputValue = 5, variables = Map("x" -> 10)) should returnResult( + true + ) + } + + it should "return false if it evaluates to true when the implicit value is applied to it" in { + + evaluateUnaryTests("not(< 10)", 5) should returnResult(false) + evaluateUnaryTests("not([1..10])", 5) should returnResult(false) + evaluateUnaryTests("not(> x)", inputValue = 5, variables = Map("x" -> 3)) should returnResult( + false + ) + } + + it should "return null if it evaluates to null when the implicit value is applied to it" in { + + evaluateUnaryTests("not(< 3)", "a") should returnNull() + evaluateUnaryTests("not(< 3)", inputValue = null) should returnNull() + } + + it should "return true if it evaluates to false" in { + + evaluateUnaryTests("not(x)", inputValue = 3, variables = Map("x" -> false)) should returnResult( + true + ) + evaluateUnaryTests("not(4 > 10)", 3) should returnResult(true) + evaluateUnaryTests("not(odd(4))", 3) should returnResult(true) + evaluateUnaryTests("not(list contains([1,2], 3))", 3) should returnResult(true) + } + + it should "return false if it evaluates to true" in { + + evaluateUnaryTests("not(x)", inputValue = 3, variables = Map("x" -> true)) should returnResult( + false + ) + evaluateUnaryTests("not(4 < 10)", 3) should returnResult(false) + evaluateUnaryTests("not(even(4))", 3) should returnResult(false) + evaluateUnaryTests("not(list contains([1,2,3], 3))", 3) should returnResult(false) + } + + it should "return true if it evaluates to null and the implicit value is not null" in { + + evaluateUnaryTests("not(null)", 5) should returnResult(true) + evaluateUnaryTests("not(not_existing)", 5) should returnResult(true) + } + + it should "return false if it evaluates to null and the implicit value is null" in { + + evaluateUnaryTests("not(null)", inputValue = null) should returnResult(false) + evaluateUnaryTests("not(not_existing)", inputValue = null) should returnResult(false) + } + + it should "return true if a disjunction evaluates to false" in { + + evaluateUnaryTests("not(2,3)", 5) should returnResult(true) + evaluateUnaryTests("not(< 3, > 10)", 5) should returnResult(true) + evaluateUnaryTests("not([0..3], [10..20])", 5) should returnResult(true) + } + + it should "return false if a disjunction evaluates to true" in { + + evaluateUnaryTests("not(2,3)", 3) should returnResult(false) + evaluateUnaryTests("not(< 3, > 10)", 1) should returnResult(false) + evaluateUnaryTests("not([0..3], [10..20])", 1) should returnResult(false) + } + + it should "return null if a disjunction evaluates to null" in { + + evaluateUnaryTests("not(2,3)", "a") should returnNull() + evaluateUnaryTests("not(< 3, > 10)", "a") should returnNull() + evaluateUnaryTests("not([0..3], [10..20])", "a") should returnNull() + } + }