You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by br...@apache.org on 2013/10/15 20:31:40 UTC

svn commit: r1532476 - in /commons/proper/lang/trunk/src: changes/changes.xml main/java/org/apache/commons/lang3/BooleanUtils.java test/java/org/apache/commons/lang3/BooleanUtilsTest.java

Author: britter
Date: Tue Oct 15 18:31:40 2013
New Revision: 1532476

URL: http://svn.apache.org/r1532476
Log:
LANG-921 - BooleanUtils.xor(boolean...) produces wrong results

Modified:
    commons/proper/lang/trunk/src/changes/changes.xml
    commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/BooleanUtils.java
    commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/BooleanUtilsTest.java

Modified: commons/proper/lang/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/changes/changes.xml?rev=1532476&r1=1532475&r2=1532476&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/changes/changes.xml (original)
+++ commons/proper/lang/trunk/src/changes/changes.xml Tue Oct 15 18:31:40 2013
@@ -22,6 +22,7 @@
   <body>
 
   <release version="3.2" date="TBA" description="Next release">
+    <action issue="LANG-921" type="fix" dev="britter">BooleanUtils.xor(boolean...) produces wrong results</action>
     <action issue="LANG-910" type="update" due-to="Timur Yarosh">StringUtils.normalizeSpace now handles non-breaking spaces (Unicode 00A0)</action>
     <action issue="LANG-804" type="update" dev="britter" due-to="Allon Mureinik">Redundant check for zero in HashCodeBuilder ctor</action>
     <action issue="LANG-893" type="add" dev="oheger" due-to="Woonsan Ko">StrSubstitutor now supports default values for variables</action>

Modified: commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/BooleanUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/BooleanUtils.java?rev=1532476&r1=1532475&r2=1532476&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/BooleanUtils.java (original)
+++ commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/BooleanUtils.java Tue Oct 15 18:31:40 2013
@@ -1028,14 +1028,6 @@ public class BooleanUtils {
      *   BooleanUtils.xor(true, false)  = true
      * </pre>
      *
-     * <p>Note that this method behaves different from using the binary XOR operator (^). Instead of combining the given
-     * booleans using the XOR operator from left to right, this method counts the appearances of true in the given
-     * array. It will only return true if exactly one boolean in the given array is true:</p>
-     * <pre>
-     *   true ^ true ^ false ^ true                 = true
-     *   BooleanUtils.xor(true, true, false, true)  = false
-     * </pre>
-     *
      * @param array  an array of {@code boolean}s
      * @return {@code true} if the xor is successful.
      * @throws IllegalArgumentException if {@code array} is {@code null}
@@ -1050,22 +1042,13 @@ public class BooleanUtils {
             throw new IllegalArgumentException("Array is empty");
         }
 
-        // Loops through array, comparing each item
-        int trueCount = 0;
+        // false if the neutral element of the xor operator
+        boolean result = false;
         for (final boolean element : array) {
-            // If item is true, and trueCount is < 1, increments count
-            // Else, xor fails
-            if (element) {
-                if (trueCount < 1) {
-                    trueCount++;
-                } else {
-                    return false;
-                }
-            }
+            result ^= element;
         }
 
-        // Returns true if there was exactly 1 true item
-        return trueCount == 1;
+        return result;
     }
 
     /**
@@ -1077,9 +1060,6 @@ public class BooleanUtils {
      *   BooleanUtils.xor(new Boolean[] { Boolean.TRUE, Boolean.FALSE })  = Boolean.TRUE
      * </pre>
      *
-     * <p>Note that this method behaves different from using the binary XOR operator (^). See
-     * {@link #xor(boolean...)}.</p>
-     *
      * @param array  an array of {@code Boolean}s
      * @return {@code true} if the xor is successful.
      * @throws IllegalArgumentException if {@code array} is {@code null}

Modified: commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/BooleanUtilsTest.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/BooleanUtilsTest.java?rev=1532476&r1=1532475&r2=1532476&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/BooleanUtilsTest.java (original)
+++ commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/BooleanUtilsTest.java Tue Oct 15 18:31:40 2013
@@ -446,56 +446,68 @@ public class BooleanUtilsTest {
 
     @Test
     public void testXor_primitive_validInput_2items() {
-        assertTrue(
-            "True result for (true, true)",
-            ! BooleanUtils.xor(new boolean[] { true, true }));
-
-        assertTrue(
-            "True result for (false, false)",
-            ! BooleanUtils.xor(new boolean[] { false, false }));
-
-        assertTrue(
-            "False result for (true, false)",
+        assertEquals(
+            "true ^ true",
+            true ^ true ,
+            BooleanUtils.xor(new boolean[] { true, true }));
+
+        assertEquals(
+            "false ^ false",
+            false ^ false,
+            BooleanUtils.xor(new boolean[] { false, false }));
+
+        assertEquals(
+            "true ^ false",
+            true ^ false,
             BooleanUtils.xor(new boolean[] { true, false }));
 
-        assertTrue(
-            "False result for (false, true)",
+        assertEquals(
+            "false ^ true",
+            false ^ true,
             BooleanUtils.xor(new boolean[] { false, true }));
     }
 
     @Test
     public void testXor_primitive_validInput_3items() {
-        assertTrue(
-            "False result for (false, false, true)",
+        assertEquals(
+            "false ^ false ^ false",
+            false ^ false ^ false,
+            BooleanUtils.xor(new boolean[] { false, false, false }));
+
+        assertEquals(
+            "false ^ false ^ true",
+            false ^ false ^ true,
             BooleanUtils.xor(new boolean[] { false, false, true }));
 
-        assertTrue(
-            "False result for (false, true, false)",
+        assertEquals(
+            "false ^ true ^ false",
+            false ^ true ^ false,
             BooleanUtils.xor(new boolean[] { false, true, false }));
 
-        assertTrue(
-            "False result for (true, false, false)",
+        assertEquals(
+            "false ^ true ^ true",
+            false ^ true ^ true,
+            BooleanUtils.xor(new boolean[] { false, true, true }));
+
+        assertEquals(
+            "true ^ false ^ false",
+            true ^ false ^ false,
             BooleanUtils.xor(new boolean[] { true, false, false }));
 
-        assertTrue(
-            "True result for (true, true, true)",
-            ! BooleanUtils.xor(new boolean[] { true, true, true }));
-
-        assertTrue(
-            "True result for (false, false)",
-            ! BooleanUtils.xor(new boolean[] { false, false, false }));
-
-        assertTrue(
-            "True result for (true, true, false)",
-            ! BooleanUtils.xor(new boolean[] { true, true, false }));
-
-        assertTrue(
-            "True result for (true, false, true)",
-            ! BooleanUtils.xor(new boolean[] { true, false, true }));
-
-        assertTrue(
-            "False result for (false, true, true)",
-            ! BooleanUtils.xor(new boolean[] { false, true, true }));
+        assertEquals(
+            "true ^ false ^ true",
+            true ^ false ^ true,
+            BooleanUtils.xor(new boolean[] { true, false, true }));
+
+        assertEquals(
+            "true ^ true ^ false",
+            true ^ true ^ false,
+            BooleanUtils.xor(new boolean[] { true, true, false }));
+
+        assertEquals(
+            "true ^ true ^ true",
+            true ^ true ^ true,
+            BooleanUtils.xor(new boolean[] { true, true, true }));
     }
 
     @Test(expected = IllegalArgumentException.class)
@@ -515,35 +527,50 @@ public class BooleanUtilsTest {
 
     @Test
     public void testXor_object_validInput_2items() {
-        assertTrue(
-            "True result for (true, true)",
-            ! BooleanUtils
-                .xor(new Boolean[] { Boolean.TRUE, Boolean.TRUE })
+        assertEquals(
+            "false ^ false",
+            false ^ false,
+            BooleanUtils
+                .xor(new Boolean[] { Boolean.FALSE, Boolean.FALSE })
                 .booleanValue());
 
-        assertTrue(
-            "True result for (false, false)",
-            ! BooleanUtils
-                .xor(new Boolean[] { Boolean.FALSE, Boolean.FALSE })
+        assertEquals(
+            "false ^ true",
+            false ^ true,
+            BooleanUtils
+                .xor(new Boolean[] { Boolean.FALSE, Boolean.TRUE })
                 .booleanValue());
 
-        assertTrue(
-            "False result for (true, false)",
+        assertEquals(
+            "true ^ false",
+            true ^ false,
             BooleanUtils
                 .xor(new Boolean[] { Boolean.TRUE, Boolean.FALSE })
                 .booleanValue());
 
-        assertTrue(
-            "False result for (false, true)",
+        assertEquals(
+            "true ^ true",
+            true ^ true,
             BooleanUtils
-                .xor(new Boolean[] { Boolean.FALSE, Boolean.TRUE })
+                .xor(new Boolean[] { Boolean.TRUE, Boolean.TRUE })
                 .booleanValue());
     }
 
     @Test
     public void testXor_object_validInput_3items() {
-        assertTrue(
-            "False result for (false, false, true)",
+        assertEquals(
+                "false ^ false ^ false",
+                false ^ false ^ false,
+                BooleanUtils.xor(
+                        new Boolean[] {
+                                Boolean.FALSE,
+                                Boolean.FALSE,
+                                Boolean.FALSE })
+                        .booleanValue());
+
+        assertEquals(
+            "false ^ false ^ true",
+            false ^ false ^ true,
             BooleanUtils
                 .xor(
                     new Boolean[] {
@@ -552,8 +579,9 @@ public class BooleanUtilsTest {
                         Boolean.TRUE })
                 .booleanValue());
 
-        assertTrue(
-            "False result for (false, true, false)",
+        assertEquals(
+            "false ^ true ^ false",
+            false ^ true ^ false,
             BooleanUtils
                 .xor(
                     new Boolean[] {
@@ -562,8 +590,9 @@ public class BooleanUtilsTest {
                         Boolean.FALSE })
                 .booleanValue());
 
-        assertTrue(
-            "False result for (true, false, false)",
+        assertEquals(
+            "true ^ false ^ false",
+            true ^ false ^ false,
             BooleanUtils
                 .xor(
                     new Boolean[] {
@@ -572,47 +601,42 @@ public class BooleanUtilsTest {
                         Boolean.FALSE })
                 .booleanValue());
 
-        assertTrue(
-            "True result for (true, true, true)",
-            ! BooleanUtils
-                .xor(new Boolean[] { Boolean.TRUE, Boolean.TRUE, Boolean.TRUE })
-                .booleanValue());
-
-        assertTrue(
-            "True result for (false, false)",
-            ! BooleanUtils.xor(
-                    new Boolean[] {
-                        Boolean.FALSE,
-                        Boolean.FALSE,
-                        Boolean.FALSE })
-                .booleanValue());
-
-        assertTrue(
-            "True result for (true, true, false)",
-            ! BooleanUtils.xor(
+        assertEquals(
+                "true ^ false ^ true",
+                true ^ false ^ true,
+                BooleanUtils.xor(
+                        new Boolean[] {
+                                Boolean.TRUE,
+                                Boolean.FALSE,
+                                Boolean.TRUE })
+                        .booleanValue());
+
+        assertEquals(
+            "true ^ true ^ false",
+            true ^ true ^ false,
+            BooleanUtils.xor(
                     new Boolean[] {
                         Boolean.TRUE,
                         Boolean.TRUE,
                         Boolean.FALSE })
                 .booleanValue());
 
-        assertTrue(
-            "True result for (true, false, true)",
-            ! BooleanUtils.xor(
-                    new Boolean[] {
-                        Boolean.TRUE,
-                        Boolean.FALSE,
-                        Boolean.TRUE })
-                .booleanValue());
-
-        assertTrue(
-            "False result for (false, true, true)",
-            ! BooleanUtils.xor(
+        assertEquals(
+            "false ^ true ^ true",
+            false ^ true ^ true,
+            BooleanUtils.xor(
                     new Boolean[] {
                         Boolean.FALSE,
                         Boolean.TRUE,
                         Boolean.TRUE })
                 .booleanValue());
+
+        assertEquals(
+                "true ^ true ^ true",
+                true ^ true ^ true,
+                BooleanUtils
+                        .xor(new Boolean[] { Boolean.TRUE, Boolean.TRUE, Boolean.TRUE })
+                        .booleanValue());
     }
 
     //  testAnd