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]

Reply via email to