Skip to content
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
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ repositories {
mavenCentral()
}

version = "1.3.1-SNAPSHOT"
version = "1.4.0-SNAPSHOT"
group = "org.hisp.dhis.lib.expression"

if (project.hasProperty("removeSnapshotSuffix")) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,16 +201,19 @@ enum class BinaryOperator(val symbol: String, private val returnType: ValueType,
if (left == null || right == null) {
return left == null && right == null
}
if (left is Boolean || right is Boolean) {
return Typed.toBooleanTypeCoercion(left) == Typed.toBooleanTypeCoercion(right)
if (left is Number || right is Number) {
val leftNum = tryToNumber(left) ?: return false
val rightNum = tryToNumber(right) ?: return false
return leftNum == rightNum
}
return if (left is Number || right is Number) {
Typed.toNumberTypeCoercion(left) == Typed.toNumberTypeCoercion(
right
)
return if (left is Boolean || right is Boolean) {
Typed.toBooleanTypeCoercion(left) == Typed.toBooleanTypeCoercion(right)
} else left == right
}

private fun tryToNumber(value: Any?): Double? {
return try { Typed.toNumberTypeCoercion(value) } catch (_: Exception) { null }
}

fun notEqual(left: Any?, right: Any?): Boolean {
return !equal(left, right)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,19 +87,35 @@ internal class CompareExpressionTest {
assertEquals(true, evaluate("'hi' == \"hi\""))
assertEquals(true, evaluate("'true' == true"))
assertEquals(true, evaluate("true == 'true'"))

// Any value that cannot be coerced to a number is not equal to any number
assertEquals(false, evaluate("2 == ''"))
assertEquals(false, evaluate("2 == 'any string that is not a number'"))

// Booleans are coerced to numbers (true→1, false→0) when compared with a number
assertEquals(true, evaluate("1 == true"))
assertEquals(true, evaluate("0 == false"))
assertEquals(false, evaluate("0 == true"))
assertEquals(false, evaluate("1 == false"))
assertEquals(true, evaluate("1.0 == true"))
assertEquals(true, evaluate("0.0 == false"))
assertEquals(false, evaluate("2.5 == true"))
assertEquals(false, evaluate("2.5 == false"))
assertEquals(false, evaluate("2 == true"))
assertEquals(false, evaluate("2 == false"))

// Any string other than 'true' is coerced to false
assertEquals(true, evaluate("false == ''"))
assertEquals(true, evaluate("false == 'any string that is not a boolean'"))
assertEquals(false, evaluate("true == ''"))
assertEquals(false, evaluate("true == 'any string that is not a boolean'"))
}

@Test
fun testDivideByZero() {
assertEquals(false, evaluate("2 == 2 / 0"))
}

@Test
fun testIncompatibleTypes() {
val ex = assertFailsWith(IllegalArgumentException::class) { evaluate("2.1 == false") }
assertEquals("Could not coerce Double '2.1' to Boolean", ex.message)
}

companion object {
private fun evaluate(expression: String): Any? {
return Expression(expression).evaluate()
Expand Down
Loading