Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle non-existing variable in comparison #676

Merged
merged 4 commits into from
Jul 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,8 @@ class FeelInterpreter {
x match {
case ValNull => f(c(ValNull, y.toOption.getOrElse(ValNull)))
case x if (y == ValNull) => f(c(x.toOption.getOrElse(ValNull), ValNull))
case _ : ValError => f(c(ValNull, y.toOption.getOrElse(ValNull)))
case _ if (y.isInstanceOf[ValError]) => f(c(ValNull, x.toOption.getOrElse(ValNull)))
case ValNumber(x) => withNumber(y, y => f(c(x, y)))
case ValBoolean(x) => withBoolean(y, y => f(c(x, y)))
case ValString(x) => withString(y, y => f(c(x, y)))
Expand Down Expand Up @@ -657,10 +659,8 @@ class FeelInterpreter {
c: (Val, Val) => Boolean,
f: Boolean => Val)(implicit context: EvalContext): Val =
x match {
case ValNull => withVal(y, y => ValBoolean(false))
case _ if (y == ValNull) => withVal(x, x => ValBoolean(false))
case _ if (!x.isComparable) => ValError(s"$x is not comparable")
case _ if (!y.isComparable) => ValError(s"$y is not comparable")
case _ if (!x.isComparable) => ValNull
case _ if (!y.isComparable) => ValNull
case _ if (x.getClass != y.getClass) =>
ValError(s"$x can not be compared to $y")
case _ => f(c(x, y))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ class BuiltinValueMapperInputTest extends AnyFlatSpec with Matchers {
engine
.evalExpression("bar.foo = \"baz\"",
context = Context.StaticContext(variables, null))
.getOrElse() shouldBe ()
.getOrElse() shouldBe false
}

it should "read scala string from object getter with attribute notation" in {
Expand Down Expand Up @@ -292,7 +292,7 @@ class BuiltinValueMapperInputTest extends AnyFlatSpec with Matchers {
engine
.evalExpression("bar.baz = \"foo\"",
context = Context.StaticContext(variables, null))
.getOrElse() shouldBe ()
.getOrElse() shouldBe false
}

it should "read java.util.Map" in {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,22 +264,22 @@ class InterpreterExpressionTest

"A variable name" should "not be a key-word" in {

eval("some = true") shouldBe a[ValError]
eval("every = true") shouldBe a[ValError]
eval("if = true") shouldBe a[ValError]
eval("then = true") shouldBe a[ValError]
eval("else = true") shouldBe a[ValError]
eval("function = true") shouldBe a[ValError]
eval("for = true") shouldBe a[ValError]
eval("between = true") shouldBe a[ValError]
eval("instance = true") shouldBe a[ValError]
eval("of = true") shouldBe a[ValError]
eval("not = true") shouldBe a[ValError]
eval("in = true") shouldBe a[ValError]
eval("satisfies = true") shouldBe a[ValError]
eval("and = true") shouldBe a[ValError]
eval("or = true") shouldBe a[ValError]
eval("return = true") shouldBe a[ValError]
eval("some = true", Map("some" -> 1)) shouldBe a[ValError]
eval("every = true", Map("every" -> 1)) shouldBe a[ValError]
eval("if = true", Map("if" -> 1)) shouldBe a[ValError]
eval("then = true", Map("then" -> 1)) shouldBe a[ValError]
eval("else = true", Map("else" -> 1)) shouldBe a[ValError]
eval("function = true", Map("function" -> 1)) shouldBe a[ValError]
eval("for = true", Map("for" -> 1)) shouldBe a[ValError]
eval("between = true", Map("between" -> 1)) shouldBe a[ValError]
eval("instance = true", Map("instance" -> 1)) shouldBe a[ValError]
eval("of = true", Map("of" -> 1)) shouldBe a[ValError]
eval("not = true", Map("not" -> 1)) shouldBe a[ValError]
eval("in = true", Map("in" -> 1)) shouldBe a[ValError]
eval("satisfies = true", Map("satisfies" -> 1)) shouldBe a[ValError]
eval("and = true", Map("and" -> 1)) shouldBe a[ValError]
eval("or = true", Map("or" -> 1)) shouldBe a[ValError]
eval("return = true", Map("return" -> 1)) shouldBe a[ValError]
remcowesterhoud marked this conversation as resolved.
Show resolved Hide resolved
}

List(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package org.camunda.feel.impl.interpreter;

import org.camunda.feel.impl.FeelIntegrationTest
import org.camunda.feel.syntaxtree._
import org.scalatest.matchers.should.Matchers
import org.scalatest.flatspec.AnyFlatSpec

class InterpreterNonExistingVariableExpressionTest
remcowesterhoud marked this conversation as resolved.
Show resolved Hide resolved
extends AnyFlatSpec
with Matchers
with FeelIntegrationTest {

"a non existing variable" should "compare with '='" in {
eval("x = 1") should be(ValBoolean(false))
eval("1 = x") should be(ValBoolean(false))
eval("x = true") should be(ValBoolean(false))
eval("true = x") should be(ValBoolean(false))
eval(""" x = "string" """) should be(ValBoolean(false))
eval(""" "string" = x """) should be(ValBoolean(false))
eval("x = null") should be(ValBoolean(true))
eval("null = x") should be(ValBoolean(true))
eval("x = y") should be(ValBoolean(true))
}

it should "compare with `<`" in {
eval("x < 1") should be(ValNull)
eval("1 < x") should be(ValNull)
eval("x < true") should be(ValNull)
eval("true < x") should be(ValNull)
eval(""" x < "string" """) should be(ValNull)
eval(""" "string" < x """) should be(ValNull)
eval("x < null") should be(ValNull)
eval("null < x") should be(ValNull)
eval("x < y") should be(ValNull)
}

it should "compare with `>`" in {
eval("x > 1") should be(ValNull)
eval("1 > x") should be(ValNull)
eval("x > true") should be(ValNull)
eval("true > x") should be(ValNull)
eval(""" x > "string" """) should be(ValNull)
eval(""" "string" > x """) should be(ValNull)
eval("x > null") should be(ValNull)
eval("null > x") should be(ValNull)
eval("x > y") should be(ValNull)
}

it should "compare with `<=`" in {
eval("x <= 1") should be(ValNull)
eval("1 <= x") should be(ValNull)
eval("x <= true") should be(ValNull)
eval("true <= x") should be(ValNull)
eval(""" x <= "string" """) should be(ValNull)
eval(""" "string" <= x """) should be(ValNull)
eval("x <= null") should be(ValNull)
eval("null <= x") should be(ValNull)
eval("x <= y") should be(ValNull)
}

it should "compare with `>=`" in {
eval("x >= 1") should be(ValNull)
eval("1 >= x") should be(ValNull)
eval("x >= true") should be(ValNull)
eval("true >= x") should be(ValNull)
eval(""" x >= "string" """) should be(ValNull)
eval(""" "string" >= x """) should be(ValNull)
eval("x >= null") should be(ValNull)
eval("null >= x") should be(ValNull)
eval("x >= y") should be(ValNull)
}

it should "compare with `between _ and _`" in {
eval("x between 1 and 3") should be(ValNull)
eval("1 between x and 3") should be(ValNull)
eval("3 between 1 and x") should be(ValNull)
eval("x between y and 3") should be(ValNull)
eval("x between 1 and y") should be(ValNull)
eval("x between y and z") should be(ValNull)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -180,11 +180,13 @@ class InterpreterNumberExpressionTest
eval("null = 2") should be(ValBoolean(false))
eval("null != 2") should be(ValBoolean(true))

eval("2 > null") should be(ValBoolean(false))
eval("null < 2") should be(ValBoolean(false))
eval("2 > null") should be(ValNull)
eval("null < 2") should be(ValNull)
}

eval("null in < 2") should be(ValBoolean(false))
eval("null in (2..4)") should be(ValBoolean(false))
ignore should "compare with 'null in'" in {
eval("null in < 2") should be(ValNull)
eval("null in (2..4)") should be(ValNull)
remcowesterhoud marked this conversation as resolved.
Show resolved Hide resolved
}

it should "compare with 'between _ and _'" in {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,11 +130,13 @@ class InterpreterUnaryTest
}

it should "compare to null" in {

evalUnaryTests(null, "3") should be(ValBoolean(false))
evalUnaryTests(null, "< 3") should be(ValBoolean(false))
evalUnaryTests(null, "> 3") should be(ValBoolean(false))
evalUnaryTests(null, "(0..10)") should be(ValBoolean(false))
}

ignore should "compare to null with < or >" in {
evalUnaryTests(null, "< 3") should be(ValNull)
evalUnaryTests(null, "> 3") should be(ValNull)
evalUnaryTests(null, "(0..10)") should be(ValNull)
}

"A string" should "be equal to another string" in {
Expand Down