This is an automated email from the ASF dual-hosted git repository.
yesamer pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-kie-drools.git
The following commit(s) were added to refs/heads/main by this push:
new 271d21192bb [incubator-kie-issues#2346] B-FEEL relational comparison
expressions return false for non-boolean operands (#6770)
271d21192bb is described below
commit 271d21192bba825c8280fbb0766c3cad7ed76f51
Author: ChinchuAjith <[email protected]>
AuthorDate: Mon Jun 29 13:47:30 2026 +0530
[incubator-kie-issues#2346] B-FEEL relational comparison expressions return
false for non-boolean operands (#6770)
* bfeel bug fix
* bfeel bug fix addind more test scenarios
* code refactoring
* changing to for loop
* fixing review comments
* fixing review comments
---
.../ast/dialectHandlers/BFEELDialectHandler.java | 134 ++++++---------------
.../ast/dialectHandlers/DefaultDialectHandler.java | 31 ++---
.../dialectHandlers/BFEELDialectHandlerTest.java | 128 ++++++++++++++++++--
3 files changed, 167 insertions(+), 126 deletions(-)
diff --git
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/dialectHandlers/BFEELDialectHandler.java
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/dialectHandlers/BFEELDialectHandler.java
index 0ec669f7370..0a4f1f191ec 100644
---
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/dialectHandlers/BFEELDialectHandler.java
+++
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/dialectHandlers/BFEELDialectHandler.java
@@ -25,7 +25,6 @@ import java.time.LocalDate;
import java.time.chrono.ChronoPeriod;
import java.util.LinkedHashMap;
import java.util.Map;
-import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
@@ -203,162 +202,97 @@ public class BFEELDialectHandler extends
DefaultDialectHandler implements Dialec
@Override
public Map<CheckedPredicate, BiFunction<Object, Object, Object>>
getGteOperations(EvaluationContext ctx) {
Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new
LinkedHashMap<>();
- // Any non-Boolean coerces to false, so (false,false) --> false
+ // BFEEL: null returns FALSE
map.put(
- new CheckedPredicate((left, right) -> {
- Boolean leftBool = (left instanceof Boolean) ? (Boolean)
left : Boolean.FALSE;
- Object rightValue = evalRight(right, ctx);
- Boolean rightBool = (rightValue instanceof Boolean) ?
(Boolean) rightValue : Boolean.FALSE;
- return Boolean.FALSE.equals(leftBool) &&
Boolean.FALSE.equals(rightBool);
- }, false),
+ new CheckedPredicate((left, right) -> left == null || right ==
null, false),
(left, right) -> Boolean.FALSE);
- // non-Boolean coercion to false
+ // BFEEL: Boolean >= logic (true >= false, true >= true, false >=
false)
map.put(
- new CheckedPredicate((left, right) -> (!(left instanceof
Boolean) || !(right instanceof Boolean)), false),
+ new CheckedPredicate((left, right) -> left instanceof Boolean
&& right instanceof Boolean, false),
(left, right) -> {
- Boolean leftBool = (left instanceof Boolean) ? (Boolean)
left : Boolean.FALSE;
- Boolean rightBool = (right instanceof Boolean) ? (Boolean)
right : Boolean.FALSE;
- return leftBool || rightBool;
+ Boolean leftBool = (Boolean) left;
+ Boolean rightBool = (Boolean) right;
+ // In BFEEL: true >= anything is true, false >= false is
true, false >= true is false
+ return leftBool || !rightBool;
});
- // numeric/comparable >= logic
+
+ // BFEEL: All other comparisons (numeric, dates, strings, etc.)
map.put(
new CheckedPredicate((left, right) -> true, false),
(left, right) -> {
Boolean greater = compare(left, right, (l, r) ->
l.compareTo(r) > 0);
- //Boolean equal = BooleanEvalHelper.isEqual(left, right,
ctx.getFEELDialect());
- Boolean equal = (EqExecutor.instance().evaluate(left,
right, ctx) instanceof Boolean)
- ? (Boolean) EqExecutor.instance().evaluate(left,
right, ctx)
- : null;
+ Object eqResult = EqExecutor.instance().evaluate(left,
right, ctx);
+ Boolean equal = (eqResult instanceof Boolean) ? (Boolean)
eqResult : null;
- if (greater == null && equal == null) {
- return Boolean.FALSE; // BFEEL default
- }
if (Boolean.TRUE.equals(greater) ||
Boolean.TRUE.equals(equal)) {
return Boolean.TRUE;
}
- return Boolean.FALSE;
+ return Boolean.FALSE; // BFEEL default for incompatible
types
});
-
- // Fall back to common >= operations for all other cases
- map.putAll(getCommonGteOperations(ctx));
return map;
}
@Override
public Map<CheckedPredicate, BiFunction<Object, Object, Object>>
getGtOperations(EvaluationContext ctx) {
Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new
LinkedHashMap<>();
-
- // Any non-Boolean coerces to false, so (false,false) --> false
+ // BFEEL: null returns FALSE
map.put(
- new CheckedPredicate((left, right) -> {
- Boolean leftBool = (left instanceof Boolean) ? (Boolean)
left : Boolean.FALSE;
- Object rightValue = evalRight(right, ctx);
- Boolean rightBool = (rightValue instanceof Boolean) ?
(Boolean) rightValue : Boolean.FALSE;
- return Boolean.FALSE.equals(leftBool) &&
Boolean.FALSE.equals(rightBool);
- }, false),
+ new CheckedPredicate((left, right) -> left == null || right ==
null, false),
(left, right) -> Boolean.FALSE);
- // non-Boolean coercion to false
- map.put(
- new CheckedPredicate((left, right) -> (!(left instanceof
Boolean) || !(right instanceof Boolean)), false),
- (left, right) -> {
- Boolean leftBool = (left instanceof Boolean) ? (Boolean)
left : Boolean.FALSE;
- Boolean rightBool = (right instanceof Boolean) ? (Boolean)
right : Boolean.FALSE;
- return leftBool || rightBool;
- });
-
- // numeric/comparable > logic
+ // BFEEL: All other comparisons (numeric, dates, strings, Booleans,
etc.)
map.put(
new CheckedPredicate((left, right) -> true, false),
- (left, right) -> {
- Boolean greater = compare(left, right,
- (l, r) -> l.compareTo(r) > 0);
- return Objects.requireNonNullElse(greater, Boolean.FALSE);
- });
-
- map.putAll(getCommonGtOperations(ctx));
+ (left, right) -> compare(left, right, (l, r) -> l.compareTo(r)
> 0));
return map;
}
@Override
public Map<CheckedPredicate, BiFunction<Object, Object, Object>>
getLteOperations(EvaluationContext ctx) {
Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new
LinkedHashMap<>();
-
- // Any non-Boolean coerces to false, so (false,false) --> false
+ // BFEEL: null returns FALSE
map.put(
- new CheckedPredicate((left, right) -> {
- Boolean leftBool = (left instanceof Boolean) ? (Boolean)
left : Boolean.FALSE;
- Object rightValue = evalRight(right, ctx);
- Boolean rightBool = (rightValue instanceof Boolean) ?
(Boolean) rightValue : Boolean.FALSE;
- return Boolean.FALSE.equals(leftBool) &&
Boolean.FALSE.equals(rightBool);
- }, false),
+ new CheckedPredicate((left, right) -> left == null || right ==
null, false),
(left, right) -> Boolean.FALSE);
- // General non-Boolean coercion to false
+ // BFEEL: Boolean <= logic (false <= anything is true, true <= true is
true, true <= false is false)
map.put(
- new CheckedPredicate((left, right) -> (!(left instanceof
Boolean) || !(right instanceof Boolean)), false),
+ new CheckedPredicate((left, right) -> left instanceof Boolean
&& right instanceof Boolean, false),
(left, right) -> {
- Boolean leftBool = (left instanceof Boolean) ? (Boolean)
left : Boolean.FALSE;
- Boolean rightBool = (right instanceof Boolean) ? (Boolean)
right : Boolean.FALSE;
- return leftBool || rightBool;
+ Boolean leftBool = (Boolean) left;
+ Boolean rightBool = (Boolean) right;
+ return !leftBool || rightBool;
});
- // Numeric/comparable ≤ logic
+ // BFEEL: All other comparisons (numeric, dates, strings, etc.)
map.put(
new CheckedPredicate((left, right) -> true, false),
(left, right) -> {
- Boolean less = compare(left, right,
- (l, r) -> l.compareTo(r) < 0);
- Boolean equal = (EqExecutor.instance().evaluate(left,
right, ctx) instanceof Boolean)
- ? (Boolean) EqExecutor.instance().evaluate(left,
right, ctx)
- : null;
-
- if (less == null && equal == null) {
- return Boolean.FALSE; // BFEEL default
- }
+ Boolean less = compare(left, right, (l, r) ->
l.compareTo(r) < 0);
+ Object eqResult = EqExecutor.instance().evaluate(left,
right, ctx);
+ Boolean equal = (eqResult instanceof Boolean) ? (Boolean)
eqResult : null;
+
if (Boolean.TRUE.equals(less) ||
Boolean.TRUE.equals(equal)) {
return Boolean.TRUE;
}
- return Boolean.FALSE;
+ return Boolean.FALSE; // BFEEL default for incompatible
types
});
-
- map.putAll(getCommonLteOperations(ctx));
return map;
}
@Override
public Map<CheckedPredicate, BiFunction<Object, Object, Object>>
getLtOperations(EvaluationContext ctx) {
Map<CheckedPredicate, BiFunction<Object, Object, Object>> map = new
LinkedHashMap<>();
-
- // Non-Boolean coerces to false, so (false,false) --> false
+ // BFEEL: null returns FALSE
map.put(
- new CheckedPredicate((left, right) -> {
- Boolean leftBool = (left instanceof Boolean) ? (Boolean)
left : Boolean.FALSE;
- Object rightValue = evalRight(right, ctx);
- Boolean rightBool = (rightValue instanceof Boolean) ?
(Boolean) rightValue : Boolean.FALSE;
- return Boolean.FALSE.equals(leftBool) &&
Boolean.FALSE.equals(rightBool);
- }, false),
+ new CheckedPredicate((left, right) -> left == null || right ==
null, false),
(left, right) -> Boolean.FALSE);
- // General non-Boolean coercion to false
- map.put(
- new CheckedPredicate((left, right) -> (!(left instanceof
Boolean) || !(right instanceof Boolean)), false),
- (left, right) -> {
- Boolean leftBool = (left instanceof Boolean) ? (Boolean)
left : Boolean.FALSE;
- Boolean rightBool = (right instanceof Boolean) ? (Boolean)
right : Boolean.FALSE;
- return leftBool || rightBool;
- });
-
- // Numeric/comparable < logic
+ // BFEEL: All other comparisons (numeric, dates, strings, Booleans,
etc.)
map.put(
new CheckedPredicate((left, right) -> true, false),
- (left, right) -> {
- Boolean less = compare(left, right,
- (l, r) -> l.compareTo(r) < 0);
- return Objects.requireNonNullElse(less, Boolean.FALSE);
- });
- map.putAll(getCommonLtOperations(ctx));
+ (left, right) -> compare(left, right, (l, r) -> l.compareTo(r)
< 0));
return map;
}
diff --git
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/dialectHandlers/DefaultDialectHandler.java
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/dialectHandlers/DefaultDialectHandler.java
index 24ab68074e4..bdc4d7f66fa 100644
---
a/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/dialectHandlers/DefaultDialectHandler.java
+++
b/kie-dmn/kie-dmn-feel/src/main/java/org/kie/dmn/feel/lang/ast/dialectHandlers/DefaultDialectHandler.java
@@ -212,10 +212,8 @@ public abstract class DefaultDialectHandler implements
DialectHandler {
(left, right) -> {
Boolean greater = compare(left, right,
(leftNum, rightNum) -> leftNum.compareTo(rightNum)
> 0);
- //Boolean equal = BooleanEvalHelper.isEqual(left, right,
dialect);
- Boolean equal = (EqExecutor.instance().evaluate(left,
right, ctx) instanceof Boolean)
- ? (Boolean) EqExecutor.instance().evaluate(left,
right, ctx)
- : null;
+ Object eqResult = EqExecutor.instance().evaluate(left,
right, ctx);
+ Boolean equal = (eqResult instanceof Boolean) ? (Boolean)
eqResult : null;
if (greater == null && equal == null)
return null;
if (Boolean.TRUE.equals(greater) ||
Boolean.TRUE.equals(equal))
@@ -275,10 +273,8 @@ public abstract class DefaultDialectHandler implements
DialectHandler {
(left, right) -> {
Boolean less = compare(left, right,
(l, r) -> l.compareTo(r) < 0);
- // Boolean equal = BooleanEvalHelper.isEqual(left, right,
dialect);
- Boolean equal = (EqExecutor.instance().evaluate(left,
right, ctx) instanceof Boolean)
- ? (Boolean) EqExecutor.instance().evaluate(left,
right, ctx)
- : null;
+ Object eqResult = EqExecutor.instance().evaluate(left,
right, ctx);
+ Boolean equal = (eqResult instanceof Boolean) ? (Boolean)
eqResult : null;
if (less == null && equal == null) {
return null;
@@ -694,18 +690,17 @@ public abstract class DefaultDialectHandler implements
DialectHandler {
Object right,
EvaluationContext ctx,
Map<CheckedPredicate, BiFunction<Object, Object, Object>>
operationMap) {
- Optional<Map.Entry<CheckedPredicate, BiFunction<Object, Object,
Object>>> match =
- operationMap.entrySet().stream()
- .filter(entry -> entry.getKey().predicate.test(left,
right))
- .findFirst();
-
- if (match.isPresent()) {
- Object result = match.get().getValue().apply(left, right);
- if (result == null && match.get().getKey().toNotify) {
- commonManageInvalidParameters(ctx);
+ for (Map.Entry<CheckedPredicate, BiFunction<Object, Object, Object>>
entry : operationMap.entrySet()) {
+ if (entry.getKey().predicate.test(left, right)) {
+ Object result = entry.getValue().apply(left, right);
+ if (result == null && entry.getKey().toNotify) {
+ commonManageInvalidParameters(ctx);
+ }
+ return result;
}
- return result;
}
+
+ // No matching predicate found
commonManageInvalidParameters(ctx);
return null;
}
diff --git
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/dialectHandlers/BFEELDialectHandlerTest.java
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/dialectHandlers/BFEELDialectHandlerTest.java
index 532a0094718..c4179bf5d39 100644
---
a/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/dialectHandlers/BFEELDialectHandlerTest.java
+++
b/kie-dmn/kie-dmn-feel/src/test/java/org/kie/dmn/feel/lang/ast/dialectHandlers/BFEELDialectHandlerTest.java
@@ -53,12 +53,14 @@ class BFEELDialectHandlerTest {
// Case 1 : STRING - If either operand is a string, convert non-string
to string
// Left: string + other
assertThat(handler.executeAdd("Hello", 123,
ctx)).isEqualTo("Hello123");
+ assertThat(handler.executeAdd("The result is: ", 1,
ctx)).isEqualTo("The result is: 1");
assertThat(handler.executeAdd("Date:", LocalDate.of(2024, 1, 1),
ctx)).isEqualTo("Date:2024-01-01");
assertThat(handler.executeAdd("Duration:", Duration.ofDays(5),
ctx)).isEqualTo("Duration:PT120H");
assertThat(handler.executeAdd("Period:", Period.ofMonths(3),
ctx)).isEqualTo("Period:P3M");
// Right: other + string
assertThat(handler.executeAdd(123, "World",
ctx)).isEqualTo("123World");
+ assertThat(handler.executeAdd(5, " minutes", ctx)).isEqualTo("5
minutes");
assertThat(handler.executeAdd(LocalDate.of(2024, 1, 1), " is the
date", ctx)).isEqualTo("2024-01-01 is the date");
assertThat(handler.executeAdd(Duration.ofDays(5), " duration",
ctx)).isEqualTo("PT120H duration");
assertThat(handler.executeAdd(Period.ofMonths(3), " period",
ctx)).isEqualTo("P3M period");
@@ -271,17 +273,21 @@ class BFEELDialectHandlerTest {
assertThat(handler.executeNotEqual(null, null,
ctx)).isEqualTo(Boolean.FALSE);
assertThat(handler.executeNotEqual(10, 20,
ctx)).isEqualTo(Boolean.TRUE);
-
- // Comparison_Relational
- assertThat(handler.executeGte(Boolean.FALSE, Boolean.FALSE,
ctx)).isEqualTo(Boolean.FALSE);
- assertThat(handler.executeGte("test", Boolean.TRUE,
ctx)).isEqualTo(Boolean.TRUE);
- assertThat(handler.executeGte(20, 10, ctx)).isEqualTo(Boolean.FALSE);
+ assertThat(handler.executeGte(Boolean.FALSE, Boolean.FALSE,
ctx)).isEqualTo(Boolean.TRUE);
+ assertThat(handler.executeGte(Boolean.TRUE, Boolean.FALSE,
ctx)).isEqualTo(Boolean.TRUE);
+ // String vs Boolean: incompatible types → false
+ assertThat(handler.executeGte("test", Boolean.TRUE,
ctx)).isEqualTo(Boolean.FALSE);
+ assertThat(handler.executeGte(20, 10, ctx)).isEqualTo(Boolean.TRUE);
// 20 >= 10 is TRUE
+ assertThat(handler.executeGte(10, 10, ctx)).isEqualTo(Boolean.TRUE);
// 10 >= 10 is TRUE
assertThat(handler.executeGte("test", 10,
ctx)).isEqualTo(Boolean.FALSE);
- assertThat(handler.executeGt(20, 10, ctx)).isEqualTo(Boolean.FALSE);
+ assertThat(handler.executeGt(20, 10, ctx)).isEqualTo(Boolean.TRUE);
// 20 > 10 is TRUE
+ assertThat(handler.executeGt(10, 20, ctx)).isEqualTo(Boolean.FALSE);
// 10 > 20 is FALSE
assertThat(handler.executeGt(new Object(), new Object(),
ctx)).isEqualTo(Boolean.FALSE);
- assertThat(handler.executeLte(5, 10, ctx)).isEqualTo(Boolean.FALSE);
- assertThat(handler.executeLt(5, 10, ctx)).isEqualTo(Boolean.FALSE);
+ assertThat(handler.executeLte(5, 10, ctx)).isEqualTo(Boolean.TRUE);
// 5 <= 10 is TRUE
+ assertThat(handler.executeLte(10, 10, ctx)).isEqualTo(Boolean.TRUE);
// 10 <= 10 is TRUE
+ assertThat(handler.executeLt(5, 10, ctx)).isEqualTo(Boolean.TRUE);
// 5 < 10 is TRUE
+ assertThat(handler.executeLt(10, 5, ctx)).isEqualTo(Boolean.FALSE);
// 10 < 5 is FALSE
// Comparison_CompareMethod
assertThat(handler.compare(null, null, (l, r) -> l.compareTo(r) >
0)).isEqualTo(Boolean.FALSE);
@@ -290,5 +296,111 @@ class BFEELDialectHandlerTest {
assertThat(handler.compare("test", 10, (l, r) -> l.compareTo(r) >
0)).isEqualTo(Boolean.FALSE);
}
+ @Test
+ void testRelationalOperatorsComprehensive() {
+ // Test GT (>) operator - comprehensive scenarios
+ assertThat(handler.executeGt(5, 2, ctx)).isEqualTo(Boolean.TRUE);
// 5 > 2
+ assertThat(handler.executeGt(2, 5, ctx)).isEqualTo(Boolean.FALSE);
// 2 > 5
+ assertThat(handler.executeGt(5, 5, ctx)).isEqualTo(Boolean.FALSE);
// 5 > 5 (equal)
+ assertThat(handler.executeGt(new BigDecimal("10.5"), new
BigDecimal("10.4"), ctx)).isEqualTo(Boolean.TRUE);
+ assertThat(handler.executeGt(null, 5, ctx)).isEqualTo(Boolean.FALSE);
// null > 5
+ assertThat(handler.executeGt(5, null, ctx)).isEqualTo(Boolean.FALSE);
// 5 > null
+
+ // Test GTE (>=) operator - comprehensive scenarios
+ assertThat(handler.executeGte(5, 2, ctx)).isEqualTo(Boolean.TRUE);
// 5 >= 2
+ assertThat(handler.executeGte(5, 5, ctx)).isEqualTo(Boolean.TRUE);
// 5 >= 5 (equal)
+ assertThat(handler.executeGte(2, 5, ctx)).isEqualTo(Boolean.FALSE);
// 2 >= 5
+ assertThat(handler.executeGte(new BigDecimal("10.5"), new
BigDecimal("10.5"), ctx)).isEqualTo(Boolean.TRUE);
+ assertThat(handler.executeGte(null, 5, ctx)).isEqualTo(Boolean.FALSE);
// null >= 5
+
+ // Test LT (<) operator - comprehensive scenarios
+ assertThat(handler.executeLt(2, 5, ctx)).isEqualTo(Boolean.TRUE);
// 2 < 5
+ assertThat(handler.executeLt(5, 2, ctx)).isEqualTo(Boolean.FALSE);
// 5 < 2
+ assertThat(handler.executeLt(5, 5, ctx)).isEqualTo(Boolean.FALSE);
// 5 < 5 (equal)
+ assertThat(handler.executeLt(new BigDecimal("10.4"), new
BigDecimal("10.5"), ctx)).isEqualTo(Boolean.TRUE);
+ assertThat(handler.executeLt(null, 5, ctx)).isEqualTo(Boolean.FALSE);
// null < 5
+ assertThat(handler.executeLt(5, null, ctx)).isEqualTo(Boolean.FALSE);
// 5 < null
+
+ // Test LTE (<=) operator - comprehensive scenarios
+ assertThat(handler.executeLte(2, 5, ctx)).isEqualTo(Boolean.TRUE);
// 2 <= 5
+ assertThat(handler.executeLte(5, 5, ctx)).isEqualTo(Boolean.TRUE);
// 5 <= 5 (equal)
+ assertThat(handler.executeLte(5, 2, ctx)).isEqualTo(Boolean.FALSE);
// 5 <= 2
+ assertThat(handler.executeLte(new BigDecimal("10.5"), new
BigDecimal("10.5"), ctx)).isEqualTo(Boolean.TRUE);
+ assertThat(handler.executeLte(null, 5, ctx)).isEqualTo(Boolean.FALSE);
// null <= 5
+
+ // Test with BigDecimal edge cases
+ assertThat(handler.executeGt(new BigDecimal("0.1"), new
BigDecimal("0.09"), ctx)).isEqualTo(Boolean.TRUE);
+ assertThat(handler.executeLt(new BigDecimal("-5"), new
BigDecimal("5"), ctx)).isEqualTo(Boolean.TRUE);
+ assertThat(handler.executeGte(new BigDecimal("0"), new
BigDecimal("0"), ctx)).isEqualTo(Boolean.TRUE);
+
+ // Test with negative numbers
+ assertThat(handler.executeGt(-2, -5, ctx)).isEqualTo(Boolean.TRUE);
// -2 > -5
+ assertThat(handler.executeLt(-5, -2, ctx)).isEqualTo(Boolean.TRUE);
// -5 < -2
+ assertThat(handler.executeGte(-5, -5, ctx)).isEqualTo(Boolean.TRUE);
// -5 >= -5
+ assertThat(handler.executeLte(-2, -2, ctx)).isEqualTo(Boolean.TRUE);
// -2 <= -2
+ }
+
+ @Test
+ void testRelationalOperatorsWithDatesAndDurations() {
+ // Test with LocalDate
+ LocalDate date1 = LocalDate.of(2024, 1, 1);
+ LocalDate date2 = LocalDate.of(2024, 1, 10);
+ LocalDate date3 = LocalDate.of(2024, 1, 1);
+
+ assertThat(handler.executeGt(date2, date1,
ctx)).isEqualTo(Boolean.TRUE); // later > earlier
+ assertThat(handler.executeLt(date1, date2,
ctx)).isEqualTo(Boolean.TRUE); // earlier < later
+ assertThat(handler.executeGte(date1, date3,
ctx)).isEqualTo(Boolean.TRUE); // same >= same
+ assertThat(handler.executeLte(date1, date3,
ctx)).isEqualTo(Boolean.TRUE); // same <= same
+ assertThat(handler.executeGt(date1, date2,
ctx)).isEqualTo(Boolean.FALSE); // earlier > later
+
+ // Test with Duration
+ Duration dur1 = Duration.ofHours(1);
+ Duration dur2 = Duration.ofHours(2);
+ Duration dur3 = Duration.ofHours(1);
+
+ assertThat(handler.executeGt(dur2, dur1,
ctx)).isEqualTo(Boolean.TRUE); // 2h > 1h
+ assertThat(handler.executeLt(dur1, dur2,
ctx)).isEqualTo(Boolean.TRUE); // 1h < 2h
+ assertThat(handler.executeGte(dur1, dur3,
ctx)).isEqualTo(Boolean.TRUE); // 1h >= 1h
+ assertThat(handler.executeLte(dur1, dur3,
ctx)).isEqualTo(Boolean.TRUE); // 1h <= 1h
+ assertThat(handler.executeGt(dur1, dur2,
ctx)).isEqualTo(Boolean.FALSE); // 1h > 2h
+
+ // Test with Period
+ Period period1 = Period.ofMonths(6);
+ Period period2 = Period.ofYears(1); // 12 months
+ Period period3 = Period.ofMonths(6);
+
+ assertThat(handler.executeGt(period2, period1,
ctx)).isEqualTo(Boolean.TRUE); // 12m > 6m
+ assertThat(handler.executeLt(period1, period2,
ctx)).isEqualTo(Boolean.TRUE); // 6m < 12m
+ assertThat(handler.executeGte(period1, period3,
ctx)).isEqualTo(Boolean.TRUE); // 6m >= 6m
+ assertThat(handler.executeLte(period1, period3,
ctx)).isEqualTo(Boolean.TRUE); // 6m <= 6m
+ }
+
+ @Test
+ void testRelationalOperatorsWithIncompatibleTypes() {
+ // String vs Number - should return false
+ assertThat(handler.executeGt("test", 10,
ctx)).isEqualTo(Boolean.FALSE);
+ assertThat(handler.executeLt("test", 10,
ctx)).isEqualTo(Boolean.FALSE);
+ assertThat(handler.executeGte("test", 10,
ctx)).isEqualTo(Boolean.FALSE);
+ assertThat(handler.executeLte("test", 10,
ctx)).isEqualTo(Boolean.FALSE);
+
+ // Number vs String - should return false
+ assertThat(handler.executeGt(10, "test",
ctx)).isEqualTo(Boolean.FALSE);
+ assertThat(handler.executeLt(10, "test",
ctx)).isEqualTo(Boolean.FALSE);
+
+ // Date vs Number - should return false
+ assertThat(handler.executeGt(LocalDate.of(2024, 1, 1), 10,
ctx)).isEqualTo(Boolean.FALSE);
+ assertThat(handler.executeLt(LocalDate.of(2024, 1, 1), 10,
ctx)).isEqualTo(Boolean.FALSE);
+
+ // Duration vs String - should return false
+ assertThat(handler.executeGt(Duration.ofDays(5), "test",
ctx)).isEqualTo(Boolean.FALSE);
+ assertThat(handler.executeLt(Duration.ofDays(5), "test",
ctx)).isEqualTo(Boolean.FALSE);
+
+ // Object vs Object (non-comparable) - should return false
+ Object obj1 = new Object();
+ Object obj2 = new Object();
+ assertThat(handler.executeGt(obj1, obj2,
ctx)).isEqualTo(Boolean.FALSE);
+ assertThat(handler.executeLt(obj1, obj2,
ctx)).isEqualTo(Boolean.FALSE);
+ }
+
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]