You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ah...@apache.org on 2020/04/04 21:16:39 UTC

[commons-numbers] 09/09: Fixed test coverage in CombinationsTest

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

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

commit dc0071f91f110f7e7974f568ff54bf77f13e72ac
Author: Alex Herbert <ah...@apache.org>
AuthorDate: Sat Apr 4 22:09:31 2020 +0100

    Fixed test coverage in CombinationsTest
---
 .../numbers/combinatorics/Combinations.java        | 10 +---
 .../numbers/combinatorics/CombinationsTest.java    | 61 +++++++++++++++++++---
 2 files changed, 57 insertions(+), 14 deletions(-)

diff --git a/commons-numbers-combinatorics/src/main/java/org/apache/commons/numbers/combinatorics/Combinations.java b/commons-numbers-combinatorics/src/main/java/org/apache/commons/numbers/combinatorics/Combinations.java
index 86ef55a..6d19160 100644
--- a/commons-numbers-combinatorics/src/main/java/org/apache/commons/numbers/combinatorics/Combinations.java
+++ b/commons-numbers-combinatorics/src/main/java/org/apache/commons/numbers/combinatorics/Combinations.java
@@ -123,8 +123,7 @@ public final class Combinations implements Iterable<int[]> {
      * Combinations, D. Knuth, 2004.</p>
      * <p>
      * The degenerate cases {@code k == 0} and {@code k == n} are NOT handled by this
-     * implementation.  If constructor arguments satisfy {@code k == 0}
-     * or {@code k >= n}, no exception is generated, but the iterator is empty.
+     * implementation. It is assumed that {@code n > k > 0}.
      * </p>
      */
     private static class LexicographicIterator implements Iterator<int[]> {
@@ -151,8 +150,7 @@ public final class Combinations implements Iterable<int[]> {
          * Construct a CombinationIterator to enumerate {@code k}-sets from a set
          * of size {@code n}.
          * <p>
-         * NOTE: If {@code k === 0} or {@code k >= n}, the Iterator will be empty
-         * (that is, {@link #hasNext()} will return {@code false} immediately.
+         * NOTE: It is assumed that {@code n > k > 0}.
          * </p>
          *
          * @param n Size of the set from which subsets are enumerated.
@@ -161,10 +159,6 @@ public final class Combinations implements Iterable<int[]> {
         LexicographicIterator(int n, int k) {
             this.k = k;
             c = new int[k + 3];
-            if (k == 0 || k >= n) {
-                more = false;
-                return;
-            }
             // Initialize c to start with lexicographically first k-set
             for (int i = 1; i <= k; i++) {
                 c[i] = i - 1;
diff --git a/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/CombinationsTest.java b/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/CombinationsTest.java
index fba85bb..ca3ead1 100644
--- a/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/CombinationsTest.java
+++ b/commons-numbers-combinatorics/src/test/java/org/apache/commons/numbers/combinatorics/CombinationsTest.java
@@ -17,6 +17,7 @@
 package org.apache.commons.numbers.combinatorics;
 
 import java.util.Iterator;
+import java.util.NoSuchElementException;
 import java.util.Comparator;
 
 import org.junit.jupiter.api.Assertions;
@@ -48,6 +49,7 @@ public class CombinationsTest {
         checkLexicographicIterator(6, 1);
         checkLexicographicIterator(3, 3);
         checkLexicographicIterator(1, 1);
+        checkLexicographicIterator(2, 0);
         checkLexicographicIterator(1, 0);
         checkLexicographicIterator(0, 0);
         checkLexicographicIterator(4, 2);
@@ -55,6 +57,13 @@ public class CombinationsTest {
     }
 
     @Test
+    public void testLexicographicIteratorThrows() {
+        checkLexicographicIteratorThrows(2, 1);
+        // Only 1 combination
+        checkLexicographicIteratorThrows(1, 1);
+    }
+
+    @Test
     public void testLexicographicComparatorWrongIterate1() {
         final int n = 5;
         final int k = 3;
@@ -182,14 +191,54 @@ public class CombinationsTest {
         Assertions.assertEquals(BinomialCoefficient.value(n, k), numIterates);
     }
 
+    /**
+     * Verifies that the iterator throws exceptions when misused.
+     *
+     * @param n Size of the set from which subsets are selected.
+     * @param k Size of the subsets to be enumerated.
+     */
+    private static void checkLexicographicIteratorThrows(int n,
+                                                         int k) {
+        Iterator<int[]> iter = Combinations.of(n, k).iterator();
+
+        // First call
+        iter.next();
+        // Check remove is not supported
+        Assertions.assertThrows(UnsupportedOperationException.class, () -> iter.remove());
+
+        // Consume the rest
+        final long numIterates = BinomialCoefficient.value(n, k);
+        for (long i = 1; i < numIterates; i++) {
+            iter.next();
+        }
+        Assertions.assertThrows(NoSuchElementException.class, () -> iter.next());
+    }
+
     @Test
-    public void testCombinationsPrecondition1() {
-        Assertions.assertThrows(IllegalArgumentException.class,
-            () -> Combinations.of(4, 5));
+    public void testBinomialCoefficientKLargerThanN() {
+        Assertions.assertThrows(CombinatoricsException.class,
+            () -> Combinations.of(4, 5)
+        );
     }
+
     @Test
-    public void testCombinationsPrecondition2() {
-        Assertions.assertThrows(IllegalArgumentException.class,
-            () -> Combinations.of(-1, -2));
+    public void testBinomialCoefficientNegativeN() {
+        Assertions.assertThrows(CombinatoricsException.class,
+            () -> Combinations.of(-1, 1)
+        );
+    }
+
+    @Test
+    public void testBinomialCoefficientNegativeK() {
+        Assertions.assertThrows(CombinatoricsException.class,
+            () -> Combinations.of(10, -1)
+        );
+    }
+
+    @Test
+    public void testBinomialCoefficientKAboveN() {
+        Assertions.assertThrows(CombinatoricsException.class,
+            () -> Combinations.of(10, 20)
+        );
     }
 }