You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2025/07/04 21:20:29 UTC

(commons-lang) 03/08: Fix NullPointerExceptions in org.apache.commons.lang3.compare.ComparableUtils.ComparableCheckBuilder

This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-lang.git

commit 8cc6363673bbcbff0777dc20343d207a443eed4a
Author: Gary D. Gregory <ga...@gmail.com>
AuthorDate: Fri Jul 4 14:23:55 2025 -0400

    Fix NullPointerExceptions in
    org.apache.commons.lang3.compare.ComparableUtils.ComparableCheckBuilder
    
    - Fix NullPointerException in
    org.apache.commons.lang3.compare.ComparableUtils.ComparableCheckBuilder.equalTo(A)
    - Fix NullPointerException in
    org.apache.commons.lang3.compare.ComparableUtils.ComparableCheckBuilder.greaterThan(A).</action>
    - Fix NullPointerException in
    org.apache.commons.lang3.compare.ComparableUtils.ComparableCheckBuilder.greaterThanOrEqualTo(A).</action>
    - Fix NullPointerException in
    org.apache.commons.lang3.compare.ComparableUtils.ComparableCheckBuilder.lessThan(A).</action>
    - Fix NullPointerException in
    org.apache.commons.lang3.compare.ComparableUtils.ComparableCheckBuilder.lessThanOrEqualTo(A)
---
 src/changes/changes.xml                            |   5 +
 .../commons/lang3/compare/ComparableUtils.java     |  14 +--
 .../commons/lang3/compare/ComparableUtilsTest.java | 123 +++++++++++++++------
 3 files changed, 101 insertions(+), 41 deletions(-)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 20e7e2ea1..7e8bc2440 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -103,6 +103,11 @@ The <action> type attribute can be add,update,fix,remove.
     <action                   type="fix" dev="ggregory" due-to="Gary Gregory">org.apache.commons.lang3.EnumUtils.getFirstEnumIgnoreCase(Class, String, Function, E) now returns the given default enum on null enumClass input.</action>
     <action                   type="fix" dev="ggregory" due-to="Gary Gregory">org.apache.commons.lang3.EnumUtils.getEnumIgnoreCase(Class, String, E) now returns the given default enum on null enumClass input.</action>
     <action                   type="fix" dev="ggregory" due-to="Gary Gregory">org.apache.commons.lang3.EnumUtils.getEnumIgnoreCase(Class, String) now returns the given default enum on null enumClass input.</action>
+    <action                   type="fix" dev="ggregory" due-to="Gary Gregory">Fix NullPointerException in org.apache.commons.lang3.compare.ComparableUtils.ComparableCheckBuilder.equalTo(A).</action>
+    <action                   type="fix" dev="ggregory" due-to="Gary Gregory">Fix NullPointerException in org.apache.commons.lang3.compare.ComparableUtils.ComparableCheckBuilder.greaterThan(A).</action>
+    <action                   type="fix" dev="ggregory" due-to="Gary Gregory">Fix NullPointerException in org.apache.commons.lang3.compare.ComparableUtils.ComparableCheckBuilder.greaterThanOrEqualTo(A).</action>
+    <action                   type="fix" dev="ggregory" due-to="Gary Gregory">Fix NullPointerException in org.apache.commons.lang3.compare.ComparableUtils.ComparableCheckBuilder.lessThan(A).</action>
+    <action                   type="fix" dev="ggregory" due-to="Gary Gregory">Fix NullPointerException in org.apache.commons.lang3.compare.ComparableUtils.ComparableCheckBuilder.lessThanOrEqualTo(A).</action>
     <!-- ADD -->
     <action                   type="add" dev="ggregory" due-to="Gary Gregory">Add Strings and refactor StringUtils.</action>
     <action issue="LANG-1747" type="add" dev="ggregory" due-to="Oliver B. Fischer, Gary Gregory">Add StopWatch.run([Failable]Runnable) and get([Failable]Supplier).</action>
diff --git a/src/main/java/org/apache/commons/lang3/compare/ComparableUtils.java b/src/main/java/org/apache/commons/lang3/compare/ComparableUtils.java
index 1f8f6c836..be75a6390 100644
--- a/src/main/java/org/apache/commons/lang3/compare/ComparableUtils.java
+++ b/src/main/java/org/apache/commons/lang3/compare/ComparableUtils.java
@@ -21,9 +21,9 @@
 import org.apache.commons.lang3.ObjectUtils;
 
 /**
- * Utility library to provide helper methods for translating {@link Comparable#compareTo} result into a boolean.
+ * Helper translating {@link Comparable#compareTo} results to booleans.
  *
- * <p>Example: {@code boolean x = is(myComparable).lessThanOrEqualTo(otherComparable)}</p>
+ * <p>Example: {@code boolean x = ComparableUtils.is(myComparable).lessThanOrEqualTo(otherComparable)}</p>
  *
  * <p>#ThreadSafe#</p>
  *
@@ -81,7 +81,7 @@ private boolean betweenOrderedExclusive(final A b, final A c) {
          * @return true if the value returned by {@link Comparable#compareTo} is equal to {@code 0}
          */
         public boolean equalTo(final A b) {
-            return a.compareTo(b) == 0;
+            return a != null && a.compareTo(b) == 0;
         }
 
         /**
@@ -91,7 +91,7 @@ public boolean equalTo(final A b) {
          * @return true if the value returned by {@link Comparable#compareTo} is greater than {@code 0}
          */
         public boolean greaterThan(final A b) {
-            return a.compareTo(b) > 0;
+            return a != null && a.compareTo(b) > 0;
         }
 
         /**
@@ -101,7 +101,7 @@ public boolean greaterThan(final A b) {
          * @return true if the value returned by {@link Comparable#compareTo} is greater than or equal to {@code 0}
          */
         public boolean greaterThanOrEqualTo(final A b) {
-            return a.compareTo(b) >= 0;
+            return a != null && a.compareTo(b) >= 0;
         }
 
         /**
@@ -111,7 +111,7 @@ public boolean greaterThanOrEqualTo(final A b) {
          * @return true if the value returned by {@link Comparable#compareTo} is less than {@code 0}
          */
         public boolean lessThan(final A b) {
-            return a.compareTo(b) < 0;
+            return a != null && a.compareTo(b) < 0;
         }
 
         /**
@@ -121,7 +121,7 @@ public boolean lessThan(final A b) {
          * @return true if the value returned by {@link Comparable#compareTo} is less than or equal to {@code 0}
          */
         public boolean lessThanOrEqualTo(final A b) {
-            return a.compareTo(b) <= 0;
+            return a != null && a.compareTo(b) <= 0;
         }
     }
 
diff --git a/src/test/java/org/apache/commons/lang3/compare/ComparableUtilsTest.java b/src/test/java/org/apache/commons/lang3/compare/ComparableUtilsTest.java
index 3ec14dd59..e0daca343 100644
--- a/src/test/java/org/apache/commons/lang3/compare/ComparableUtilsTest.java
+++ b/src/test/java/org/apache/commons/lang3/compare/ComparableUtilsTest.java
@@ -16,7 +16,7 @@
  */
 package org.apache.commons.lang3.compare;
 
-import static org.apache.commons.lang3.compare.ComparableUtils.is;
+import static org.apache.commons.lang3.LangAssertions.assertNullPointerException;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -46,12 +46,12 @@ final class C_is_0 {
 
                 @Test
                 void between_returns_false() {
-                    assertFalse(is(a).between(b, c));
+                    assertFalse(ComparableUtils.is(a).between(b, c));
                 }
 
                 @Test
                 void betweenExclusive_returns_false() {
-                    assertFalse(is(a).betweenExclusive(b, c));
+                    assertFalse(ComparableUtils.is(a).betweenExclusive(b, c));
                 }
 
                 @Test
@@ -74,12 +74,12 @@ final class C_is_1 {
 
                 @Test
                 void between_returns_true() {
-                    assertTrue(is(a).between(b, c));
+                    assertTrue(ComparableUtils.is(a).between(b, c));
                 }
 
                 @Test
                 void betweenExclusive_returns_false() {
-                    assertFalse(is(a).betweenExclusive(b, c));
+                    assertFalse(ComparableUtils.is(a).betweenExclusive(b, c));
                 }
 
                 @Test
@@ -101,12 +101,12 @@ final class C_is_10 {
 
                 @Test
                 void between_returns_true() {
-                    assertTrue(is(a).between(b, c));
+                    assertTrue(ComparableUtils.is(a).between(b, c));
                 }
 
                 @Test
                 void betweenExclusive_returns_true() {
-                    assertTrue(is(a).betweenExclusive(b, c));
+                    assertTrue(ComparableUtils.is(a).betweenExclusive(b, c));
                 }
 
                 @Test
@@ -124,27 +124,27 @@ void static_betweenExclusive_returns_true() {
 
             @Test
             void equalTo_returns_false() {
-                assertFalse(is(a).equalTo(b));
+                assertFalse(ComparableUtils.is(a).equalTo(b));
             }
 
             @Test
             void greaterThan_returns_true() {
-                assertTrue(is(a).greaterThan(b));
+                assertTrue(ComparableUtils.is(a).greaterThan(b));
             }
 
             @Test
             void greaterThanOrEqualTo_returns_true() {
-                assertTrue(is(a).greaterThanOrEqualTo(b));
+                assertTrue(ComparableUtils.is(a).greaterThanOrEqualTo(b));
             }
 
             @Test
             void lessThan_returns_false() {
-                assertFalse(is(a).lessThan(b));
+                assertFalse(ComparableUtils.is(a).lessThan(b));
             }
 
             @Test
             void lessThanOrEqualTo_returns_false() {
-                assertFalse(is(a).lessThanOrEqualTo(b));
+                assertFalse(ComparableUtils.is(a).lessThanOrEqualTo(b));
             }
 
             @Test
@@ -180,12 +180,12 @@ final class C_is_0 {
 
                 @Test
                 void between_returns_true() {
-                    assertTrue(is(a).between(b, c));
+                    assertTrue(ComparableUtils.is(a).between(b, c));
                 }
 
                 @Test
                 void betweenExclusive_returns_false() {
-                    assertFalse(is(a).betweenExclusive(b, c));
+                    assertFalse(ComparableUtils.is(a).betweenExclusive(b, c));
                 }
 
                 @Test
@@ -207,12 +207,12 @@ final class C_is_1 {
 
                 @Test
                 void between_returns_true() {
-                    assertTrue(is(a).between(b, c));
+                    assertTrue(ComparableUtils.is(a).between(b, c));
                 }
 
                 @Test
                 void betweenExclusive_returns_false() {
-                    assertFalse(is(a).betweenExclusive(b, c));
+                    assertFalse(ComparableUtils.is(a).betweenExclusive(b, c));
                 }
 
                 @Test
@@ -234,12 +234,12 @@ final class C_is_10 {
 
                 @Test
                 void between_returns_true() {
-                    assertTrue(is(a).between(b, c));
+                    assertTrue(ComparableUtils.is(a).between(b, c));
                 }
 
                 @Test
                 void betweenExclusive_returns_false() {
-                    assertFalse(is(a).betweenExclusive(b, c));
+                    assertFalse(ComparableUtils.is(a).betweenExclusive(b, c));
                 }
 
                 @Test
@@ -257,27 +257,27 @@ void static_betweenExclusive_returns_false() {
 
             @Test
             void equalTo_returns_true() {
-                assertTrue(is(a).equalTo(b));
+                assertTrue(ComparableUtils.is(a).equalTo(b));
             }
 
             @Test
             void greaterThan_returns_false() {
-                assertFalse(is(a).greaterThan(b));
+                assertFalse(ComparableUtils.is(a).greaterThan(b));
             }
 
             @Test
             void greaterThanOrEqualTo_returns_true() {
-                assertTrue(is(a).greaterThanOrEqualTo(b));
+                assertTrue(ComparableUtils.is(a).greaterThanOrEqualTo(b));
             }
 
             @Test
             void lessThan_returns_false() {
-                assertFalse(is(a).lessThan(b));
+                assertFalse(ComparableUtils.is(a).lessThan(b));
             }
 
             @Test
             void lessThanOrEqualTo_returns_true() {
-                assertTrue(is(a).lessThanOrEqualTo(b));
+                assertTrue(ComparableUtils.is(a).lessThanOrEqualTo(b));
             }
 
             @Test
@@ -313,12 +313,12 @@ final class C_is_0 {
 
                 @Test
                 void between_returns_true() {
-                    assertTrue(is(a).between(b, c));
+                    assertTrue(ComparableUtils.is(a).between(b, c));
                 }
 
                 @Test
                 void betweenExclusive_returns_true() {
-                    assertTrue(is(a).betweenExclusive(b, c));
+                    assertTrue(ComparableUtils.is(a).betweenExclusive(b, c));
                 }
 
                 @Test
@@ -340,12 +340,12 @@ final class C_is_1 {
 
                 @Test
                 void between_returns_true() {
-                    assertTrue(is(a).between(b, c));
+                    assertTrue(ComparableUtils.is(a).between(b, c));
                 }
 
                 @Test
                 void betweenExclusive_returns_false() {
-                    assertFalse(is(a).betweenExclusive(b, c));
+                    assertFalse(ComparableUtils.is(a).betweenExclusive(b, c));
                 }
 
                 @Test
@@ -367,12 +367,12 @@ final class C_is_10 {
 
                 @Test
                 void between_returns_false() {
-                    assertFalse(is(a).between(b, c));
+                    assertFalse(ComparableUtils.is(a).between(b, c));
                 }
 
                 @Test
                 void betweenExclusive_returns_false() {
-                    assertFalse(is(a).betweenExclusive(b, c));
+                    assertFalse(ComparableUtils.is(a).betweenExclusive(b, c));
                 }
 
                 @Test
@@ -390,27 +390,27 @@ void static_betweenExclusive_returns_false() {
 
             @Test
             void equalTo_returns_false() {
-                assertFalse(is(a).equalTo(b));
+                assertFalse(ComparableUtils.is(a).equalTo(b));
             }
 
             @Test
             void greaterThan_returns_false() {
-                assertFalse(is(a).greaterThan(b));
+                assertFalse(ComparableUtils.is(a).greaterThan(b));
             }
 
             @Test
             void greaterThanOrEqualTo_returns_false() {
-                assertFalse(is(a).greaterThanOrEqualTo(b));
+                assertFalse(ComparableUtils.is(a).greaterThanOrEqualTo(b));
             }
 
             @Test
             void lessThan_returns_true() {
-                assertTrue(is(a).lessThan(b));
+                assertTrue(ComparableUtils.is(a).lessThan(b));
             }
 
             @Test
             void lessThanOrEqualTo_returns_true() {
-                assertTrue(is(a).lessThanOrEqualTo(b));
+                assertTrue(ComparableUtils.is(a).lessThanOrEqualTo(b));
             }
 
             @Test
@@ -437,6 +437,61 @@ void static_lt_returns_true() {
         BigDecimal a = BigDecimal.ONE;
     }
 
+    private static class MyComparable implements Comparable<MyComparable> {
+
+        private final int i;
+
+        MyComparable(final int i) {
+            this.i = i;
+        }
+
+        @Override
+        public int compareTo(final MyComparable o) {
+            return Integer.compare(i, o != null ? o.i : 0);
+        }
+
+    }
+
+    @Test
+    void testIsEqualTo() {
+        assertNullPointerException(() -> ComparableUtils.is("a").equalTo(null));
+        assertFalse(ComparableUtils.is(new MyComparable(1)).equalTo(null));
+        assertFalse(ComparableUtils.is((String) null).equalTo("a"));
+        assertTrue(ComparableUtils.is("a").equalTo("a"));
+    }
+
+    @Test
+    void testIsGreaterThan() {
+        assertNullPointerException(() -> ComparableUtils.is("a").greaterThan(null));
+        assertTrue(ComparableUtils.is(new MyComparable(1)).greaterThan(null));
+        assertFalse(ComparableUtils.is((String) null).greaterThan("a"));
+        assertFalse(ComparableUtils.is("a").greaterThan("a"));
+    }
+
+    @Test
+    void testIsGreaterThanOrEqualTo() {
+        assertNullPointerException(() -> ComparableUtils.is("a").greaterThanOrEqualTo(null));
+        assertTrue(ComparableUtils.is(new MyComparable(1)).greaterThanOrEqualTo(null));
+        assertFalse(ComparableUtils.is((String) null).greaterThanOrEqualTo("a"));
+        assertTrue(ComparableUtils.is("a").greaterThanOrEqualTo("a"));
+    }
+
+    @Test
+    void testIsLessThan() {
+        assertNullPointerException(() -> ComparableUtils.is("a").lessThan(null));
+        assertFalse(ComparableUtils.is(new MyComparable(1)).lessThan(null));
+        assertFalse(ComparableUtils.is((String) null).lessThan("a"));
+        assertFalse(ComparableUtils.is("a").lessThan("a"));
+    }
+
+    @Test
+    void testIsLessThanOrEqualTo() {
+        assertNullPointerException(() -> ComparableUtils.is("a").greaterThanOrEqualTo(null));
+        assertTrue(ComparableUtils.is(new MyComparable(1)).greaterThanOrEqualTo(null));
+        assertFalse(ComparableUtils.is((String) null).lessThanOrEqualTo("a"));
+        assertTrue(ComparableUtils.is("a").lessThanOrEqualTo("a"));
+    }
+
     @Test
     void testMax() {
         assertEquals(Instant.MAX, ComparableUtils.max(Instant.MAX, Instant.MAX));