From d05bc92689d6379a17412ef4898b41c1c766536f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Mon, 26 Mar 2018 14:21:19 +0200 Subject: [PATCH] Update tests for PriorityQueue. --- .../org/insa/algo/utils/BinaryHeapTest.java | 235 +--------------- .../insa/algo/utils/BinarySearchTreeTest.java | 235 +--------------- .../insa/algo/utils/PriorityQueueTest.java | 259 ++++++++++++++++++ 3 files changed, 273 insertions(+), 456 deletions(-) create mode 100644 src/test/org/insa/algo/utils/PriorityQueueTest.java diff --git a/src/test/org/insa/algo/utils/BinaryHeapTest.java b/src/test/org/insa/algo/utils/BinaryHeapTest.java index 8f89d70..60b046b 100644 --- a/src/test/org/insa/algo/utils/BinaryHeapTest.java +++ b/src/test/org/insa/algo/utils/BinaryHeapTest.java @@ -1,236 +1,15 @@ package org.insa.algo.utils; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +public class BinaryHeapTest extends PriorityQueueTest { -import java.util.Arrays; -import java.util.HashSet; -import java.util.stream.IntStream; - -import org.junit.Before; -import org.junit.Test; - -public class BinaryHeapTest { - - class MutableInteger implements Comparable { - - // Actual value - private int value; - - public MutableInteger(int value) { - this.value = value; - } - - /** - * @return The integer value stored inside this MutableInteger. - */ - public int get() { - return this.value; - } - - /** - * Update the integer value stored inside this MutableInteger. - * - * @param value New value to set. - */ - public void set(int value) { - this.value = value; - } - - @Override - public int compareTo(MutableInteger other) { - return Integer.compare(this.value, other.value); - } - - }; - - // Raw data arrays. - private MutableInteger[] data1 = IntStream.range(0, 20).mapToObj(MutableInteger::new) - .toArray(MutableInteger[]::new); - private MutableInteger[] data2 = Arrays.stream(new int[] { 8, 1, 6, 3, 4, 5, 9 }) - .mapToObj(MutableInteger::new).toArray(MutableInteger[]::new); - - // Actual heap. - private BinaryHeap heap1, heap2; - - @Before - public void init() { - // Create the range heap - this.heap1 = new BinaryHeap<>(); - this.heap2 = new BinaryHeap<>(); - - for (MutableInteger v: data1) { - this.heap1.insert(v); - } - - for (MutableInteger v: data2) { - this.heap2.insert(v); - } + @Override + public PriorityQueue createQueue() { + return new BinaryHeap<>(); } - @Test - public void testIsEmpty() { - BinaryHeap tree = new BinaryHeap<>(); - assertTrue(tree.isEmpty()); - assertFalse(this.heap1.isEmpty()); - assertFalse(this.heap2.isEmpty()); - } - - @Test - public void testSize() { - BinaryHeap tree = new BinaryHeap<>(); - assertEquals(0, tree.size()); - assertEquals(20, this.heap1.size()); - assertEquals(7, this.heap2.size()); - } - - @Test - public void testInsert() { - BinaryHeap heap = new BinaryHeap<>(); - int size = 0; - for (MutableInteger x: data1) { - heap.insert(x); - assertEquals(++size, heap.size()); - } - assertEquals(data1.length, heap.size()); - - heap = new BinaryHeap<>(); - size = 0; - for (MutableInteger x: data2) { - heap.insert(x); - assertEquals(++size, heap.size()); - } - assertEquals(data2.length, heap.size()); - } - - @Test(expected = EmptyPriorityQueueException.class) - public void testEmptyFindMin() { - BinaryHeap heap = new BinaryHeap<>(); - heap.findMin(); - } - - @Test - public void testFindMin() { - assertEquals(0, heap1.findMin().get()); - assertEquals(1, heap2.findMin().get()); - } - - @Test(expected = EmptyPriorityQueueException.class) - public void testEmptyDeleteMin() { - BinaryHeap heap = new BinaryHeap<>(); - heap.deleteMin(); - } - - @Test - public void testDeleteMin() { - // range 1 (sorted) - int size = data1.length; - assertEquals(heap1.size(), size); - for (MutableInteger x: data1) { - assertEquals(x, heap1.deleteMin()); - size -= 1; - assertEquals(size, heap1.size()); - } - assertEquals(0, heap1.size()); - assertTrue(heap1.isEmpty()); - - // range 2 (was not sorted) - MutableInteger[] range2 = Arrays.copyOf(data2, data2.length); - Arrays.sort(range2); - size = range2.length; - assertEquals(heap2.size(), size); - for (MutableInteger x: range2) { - assertEquals(x.get(), heap2.deleteMin().get()); - size -= 1; - assertEquals(size, heap2.size()); - } - assertEquals(0, heap2.size()); - assertTrue(heap2.isEmpty()); - } - - @Test(expected = ElementNotFoundException.class) - public void testRemoveEmpty() { - BinaryHeap heap = new BinaryHeap<>(); - heap.remove(new MutableInteger(0)); - } - - @Test(expected = ElementNotFoundException.class) - public void testRemoveNotFound() { - heap1.remove(new MutableInteger(20)); - } - - @Test - public void testRemove() { - // heap 1 - int size1 = heap1.size(); - int[] deleteOrder1 = new int[] { 12, 17, 18, 19, 4, 5, 3, 2, 0, 9, 10, 16, 8, 14, 13, 15, 7, - 6, 1, 11 }; - for (int i = 0; i < deleteOrder1.length; ++i) { - // Remove from structure - heap1.remove(this.data1[deleteOrder1[i]]); - - // Copy the remaining elements - BinaryHeap copyTree = new BinaryHeap<>(heap1); - - // Retrieve all remaining elements in both structures - MutableInteger[] remains_in = new MutableInteger[deleteOrder1.length - i - 1], - remains_cp = new MutableInteger[deleteOrder1.length - i - 1]; - for (int j = 0; j < remains_cp.length; ++j) { - remains_in[j] = this.data1[deleteOrder1[i + j + 1]]; - remains_cp[j] = copyTree.deleteMin(); - } - - // Check that the copy is now empty, and that both list contains all - // elements. - assertTrue(copyTree.isEmpty()); - assertEquals(new HashSet<>(Arrays.asList(remains_in)), - new HashSet<>(Arrays.asList(remains_cp))); - - // Check that the size of the original tree is correct. - assertEquals(--size1, heap1.size()); - } - assertTrue(heap1.isEmpty()); - - // heap 2 - int size2 = heap2.size(); - int[] deleteOrder2 = new int[] { 6, 5, 0, 1, 4, 2, 3 }; - for (int i = 0; i < deleteOrder2.length; ++i) { - // Remove from structure - heap2.remove(this.data2[deleteOrder2[i]]); - - // Copy the remaining elements - BinaryHeap copyTree = new BinaryHeap<>(heap2); - - // Retrieve all remaining elements in both structures - MutableInteger[] remains_in = new MutableInteger[deleteOrder2.length - i - 1], - remains_cp = new MutableInteger[deleteOrder2.length - i - 1]; - for (int j = 0; j < remains_cp.length; ++j) { - remains_in[j] = this.data2[deleteOrder2[i + j + 1]]; - remains_cp[j] = copyTree.deleteMin(); - } - - // Check that the copy is now empty, and that both list contains all - // elements. - assertTrue(copyTree.isEmpty()); - assertEquals(new HashSet<>(Arrays.asList(remains_in)), - new HashSet<>(Arrays.asList(remains_cp))); - - // Check that the size of the original tree is correct. - assertEquals(--size2, heap2.size()); - } - assertTrue(heap2.isEmpty()); - } - - @Test - public void testRemoveThenAdd() { - MutableInteger mi5 = this.data1[6]; - heap1.remove(mi5); - assertEquals(19, heap1.size()); - mi5.set(-20); - heap1.insert(mi5); - assertEquals(20, heap1.size()); - assertEquals(-20, heap1.findMin().get()); + @Override + public PriorityQueue createQueue(PriorityQueue queue) { + return new BinaryHeap<>((BinaryHeap) queue); } } diff --git a/src/test/org/insa/algo/utils/BinarySearchTreeTest.java b/src/test/org/insa/algo/utils/BinarySearchTreeTest.java index adb50c1..e4c351b 100644 --- a/src/test/org/insa/algo/utils/BinarySearchTreeTest.java +++ b/src/test/org/insa/algo/utils/BinarySearchTreeTest.java @@ -1,236 +1,15 @@ package org.insa.algo.utils; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +public class BinarySearchTreeTest extends PriorityQueueTest { -import java.util.Arrays; -import java.util.HashSet; -import java.util.stream.IntStream; - -import org.junit.Before; -import org.junit.Test; - -public class BinarySearchTreeTest { - - class MutableInteger implements Comparable { - - // Actual value - private int value; - - public MutableInteger(int value) { - this.value = value; - } - - /** - * @return The integer value stored inside this MutableInteger. - */ - public int get() { - return this.value; - } - - /** - * Update the integer value stored inside this MutableInteger. - * - * @param value New value to set. - */ - public void set(int value) { - this.value = value; - } - - @Override - public int compareTo(MutableInteger other) { - return Integer.compare(this.value, other.value); - } - - }; - - // Raw data arrays. - private MutableInteger[] data1 = IntStream.range(0, 20).mapToObj(MutableInteger::new) - .toArray(MutableInteger[]::new); - private MutableInteger[] data2 = Arrays.stream(new int[] { 8, 1, 6, 3, 4, 5, 9 }) - .mapToObj(MutableInteger::new).toArray(MutableInteger[]::new); - - // Actual searchTree. - private BinarySearchTree searchTree1, searchTree2; - - @Before - public void init() { - // Create the range searchTree - this.searchTree1 = new BinarySearchTree<>(); - this.searchTree2 = new BinarySearchTree<>(); - - for (MutableInteger v: data1) { - this.searchTree1.insert(v); - } - - for (MutableInteger v: data2) { - this.searchTree2.insert(v); - } + @Override + public PriorityQueue createQueue() { + return new BinarySearchTree<>(); } - @Test - public void testIsEmpty() { - BinarySearchTree tree = new BinarySearchTree<>(); - assertTrue(tree.isEmpty()); - assertFalse(this.searchTree1.isEmpty()); - assertFalse(this.searchTree2.isEmpty()); - } - - @Test - public void testSize() { - BinarySearchTree tree = new BinarySearchTree<>(); - assertEquals(0, tree.size()); - assertEquals(20, this.searchTree1.size()); - assertEquals(7, this.searchTree2.size()); - } - - @Test - public void testInsert() { - BinarySearchTree searchTree = new BinarySearchTree<>(); - int size = 0; - for (MutableInteger x: data1) { - searchTree.insert(x); - assertEquals(++size, searchTree.size()); - } - assertEquals(data1.length, searchTree.size()); - - searchTree = new BinarySearchTree<>(); - size = 0; - for (MutableInteger x: data2) { - searchTree.insert(x); - assertEquals(++size, searchTree.size()); - } - assertEquals(data2.length, searchTree.size()); - } - - @Test(expected = EmptyPriorityQueueException.class) - public void testEmptyFindMin() { - BinarySearchTree searchTree = new BinarySearchTree<>(); - searchTree.findMin(); - } - - @Test - public void testFindMin() { - assertEquals(0, searchTree1.findMin().get()); - assertEquals(1, searchTree2.findMin().get()); - } - - @Test(expected = EmptyPriorityQueueException.class) - public void testEmptyDeleteMin() { - BinarySearchTree searchTree = new BinarySearchTree<>(); - searchTree.deleteMin(); - } - - @Test - public void testDeleteMin() { - // range 1 (sorted) - int size = data1.length; - assertEquals(searchTree1.size(), size); - for (MutableInteger x: data1) { - assertEquals(x, searchTree1.deleteMin()); - size -= 1; - assertEquals(size, searchTree1.size()); - } - assertEquals(0, searchTree1.size()); - assertTrue(searchTree1.isEmpty()); - - // range 2 (was not sorted) - MutableInteger[] range2 = Arrays.copyOf(data2, data2.length); - Arrays.sort(range2); - size = range2.length; - assertEquals(searchTree2.size(), size); - for (MutableInteger x: range2) { - assertEquals(x.get(), searchTree2.deleteMin().get()); - size -= 1; - assertEquals(size, searchTree2.size()); - } - assertEquals(0, searchTree2.size()); - assertTrue(searchTree2.isEmpty()); - } - - @Test(expected = ElementNotFoundException.class) - public void testRemoveEmpty() { - BinarySearchTree searchTree = new BinarySearchTree<>(); - searchTree.remove(new MutableInteger(0)); - } - - @Test(expected = ElementNotFoundException.class) - public void testRemoveNotFound() { - searchTree1.remove(new MutableInteger(20)); - } - - @Test - public void testRemove() { - // searchTree 1 - int size1 = searchTree1.size(); - int[] deleteOrder1 = new int[] { 12, 17, 18, 19, 4, 5, 3, 2, 0, 9, 10, 16, 8, 14, 13, 15, 7, - 6, 1, 11 }; - for (int i = 0; i < deleteOrder1.length; ++i) { - // Remove from structure - searchTree1.remove(this.data1[deleteOrder1[i]]); - - // Copy the remaining elements - BinarySearchTree copyTree = new BinarySearchTree<>(searchTree1); - - // Retrieve all remaining elements in both structures - MutableInteger[] remains_in = new MutableInteger[deleteOrder1.length - i - 1], - remains_cp = new MutableInteger[deleteOrder1.length - i - 1]; - for (int j = 0; j < remains_cp.length; ++j) { - remains_in[j] = this.data1[deleteOrder1[i + j + 1]]; - remains_cp[j] = copyTree.deleteMin(); - } - - // Check that the copy is now empty, and that both list contains all - // elements. - assertTrue(copyTree.isEmpty()); - assertEquals(new HashSet<>(Arrays.asList(remains_in)), - new HashSet<>(Arrays.asList(remains_cp))); - - // Check that the size of the original tree is correct. - assertEquals(--size1, searchTree1.size()); - } - assertTrue(searchTree1.isEmpty()); - - // searchTree 2 - int size2 = searchTree2.size(); - int[] deleteOrder2 = new int[] { 6, 5, 0, 1, 4, 2, 3 }; - for (int i = 0; i < deleteOrder2.length; ++i) { - // Remove from structure - searchTree2.remove(this.data2[deleteOrder2[i]]); - - // Copy the remaining elements - BinarySearchTree copyTree = new BinarySearchTree<>(searchTree2); - - // Retrieve all remaining elements in both structures - MutableInteger[] remains_in = new MutableInteger[deleteOrder2.length - i - 1], - remains_cp = new MutableInteger[deleteOrder2.length - i - 1]; - for (int j = 0; j < remains_cp.length; ++j) { - remains_in[j] = this.data2[deleteOrder2[i + j + 1]]; - remains_cp[j] = copyTree.deleteMin(); - } - - // Check that the copy is now empty, and that both list contains all - // elements. - assertTrue(copyTree.isEmpty()); - assertEquals(new HashSet<>(Arrays.asList(remains_in)), - new HashSet<>(Arrays.asList(remains_cp))); - - // Check that the size of the original tree is correct. - assertEquals(--size2, searchTree2.size()); - } - assertTrue(searchTree2.isEmpty()); - } - - @Test - public void testRemoveThenAdd() { - MutableInteger mi5 = this.data1[6]; - searchTree1.remove(mi5); - assertEquals(19, searchTree1.size()); - mi5.set(-20); - searchTree1.insert(mi5); - assertEquals(20, searchTree1.size()); - assertEquals(-20, searchTree1.findMin().get()); + @Override + public PriorityQueue createQueue(PriorityQueue queue) { + return new BinarySearchTree<>((BinarySearchTree) queue); } } diff --git a/src/test/org/insa/algo/utils/PriorityQueueTest.java b/src/test/org/insa/algo/utils/PriorityQueueTest.java new file mode 100644 index 0000000..183ab24 --- /dev/null +++ b/src/test/org/insa/algo/utils/PriorityQueueTest.java @@ -0,0 +1,259 @@ +package org.insa.algo.utils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.stream.IntStream; + +import org.junit.Assume; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; + +@RunWith(Parameterized.class) +public abstract class PriorityQueueTest { + + /** + * Needs to be implemented by child class to actually provide priority queue + * implementation. + * + * @return A new instance of a PriorityQueue implementation. + */ + public abstract PriorityQueue createQueue(); + + /** + * Needs to be implemented by child class to actually provide priority queue + * implementation. + * + * @param queue Queue to copy. + * + * @return Copy of the given queue. + */ + public abstract PriorityQueue createQueue(PriorityQueue queue); + + protected static class MutableInteger implements Comparable { + + // Actual value + private int value; + + public MutableInteger(int value) { + this.value = value; + } + + /** + * @return The integer value stored inside this MutableInteger. + */ + public int get() { + return this.value; + } + + /** + * Update the integer value stored inside this MutableInteger. + * + * @param value New value to set. + */ + public void set(int value) { + this.value = value; + } + + @Override + public int compareTo(MutableInteger other) { + return Integer.compare(this.value, other.value); + } + + }; + + protected static class TestParameters> { + + // Data to insert + public final E[] data; + public final int[] deleteOrder; + + public TestParameters(E[] data, int[] deleteOrder) { + this.data = data; + this.deleteOrder = deleteOrder; + } + + }; + + /** + * Set of parameters. + * + */ + @Parameters + public static Collection data() { + Collection objects = new ArrayList<>(); + objects.add(new TestParameters<>(new MutableInteger[0], new int[0])); + objects.add(new TestParameters<>( + IntStream.range(0, 50).mapToObj(MutableInteger::new).toArray(MutableInteger[]::new), + IntStream.range(0, 50).toArray())); + objects.add(new TestParameters<>( + IntStream.range(0, 20).mapToObj(MutableInteger::new).toArray(MutableInteger[]::new), + new int[] { 12, 17, 18, 19, 4, 5, 3, 2, 0, 9, 10, 16, 8, 14, 13, 15, 7, 6, 1, + 11 })); + objects.add( + new TestParameters<>( + Arrays.stream(new int[] { 8, 1, 6, 3, 4, 5, 9 }) + .mapToObj(MutableInteger::new).toArray(MutableInteger[]::new), + new int[] { 6, 5, 0, 1, 4, 2, 3 })); + return objects; + } + + @Parameter + public TestParameters parameters; + + // Actual queue. + private PriorityQueue queue; + + @Before + public void init() { + // Create the range queue + this.queue = createQueue(); + + for (MutableInteger v: parameters.data) { + this.queue.insert(v); + } + } + + @Test + public void testIsEmpty() { + assertEquals(parameters.data.length == 0, this.queue.isEmpty()); + } + + @Test + public void testSize() { + assertEquals(parameters.data.length, this.queue.size()); + } + + @Test + public void testInsert() { + PriorityQueue queue = createQueue(); + int size = 0; + for (MutableInteger x: parameters.data) { + queue.insert(x); + assertEquals(++size, queue.size()); + } + assertEquals(parameters.data.length, queue.size()); + MutableInteger[] range = Arrays.copyOf(parameters.data, parameters.data.length); + Arrays.sort(range); + + for (MutableInteger mi: range) { + assertEquals(mi.get(), queue.deleteMin().value); + assertEquals(--size, queue.size()); + } + } + + @Test(expected = EmptyPriorityQueueException.class) + public void testEmptyFindMin() { + Assume.assumeTrue(queue.isEmpty()); + queue.findMin(); + } + + @Test + public void testFindMin() { + Assume.assumeFalse(queue.isEmpty()); + assertEquals(Collections.min(Arrays.asList(parameters.data)).get(), queue.findMin().get()); + } + + @Test(expected = EmptyPriorityQueueException.class) + public void testEmptyDeleteMin() { + Assume.assumeTrue(queue.isEmpty()); + queue.deleteMin(); + } + + @Test + public void testDeleteMin() { + int size = parameters.data.length; + assertEquals(queue.size(), size); + MutableInteger[] range = Arrays.copyOf(parameters.data, parameters.data.length); + Arrays.sort(range); + for (MutableInteger x: range) { + assertEquals(x, queue.deleteMin()); + size -= 1; + assertEquals(size, queue.size()); + } + assertEquals(0, queue.size()); + assertTrue(queue.isEmpty()); + } + + @Test(expected = ElementNotFoundException.class) + public void testRemoveEmpty() { + Assume.assumeTrue(queue.isEmpty()); + queue.remove(new MutableInteger(0)); + } + + @Test(expected = ElementNotFoundException.class) + public void testRemoveNotFound() { + Assume.assumeFalse(queue.isEmpty()); + List data = Arrays.asList(parameters.data); + queue.remove(new MutableInteger(Collections.min(data).get() - 1)); + queue.remove(new MutableInteger(Collections.max(data).get() + 1)); + } + + @Test(expected = ElementNotFoundException.class) + public void testDeleteThenRemove() { + Assume.assumeFalse(queue.isEmpty()); + MutableInteger min = queue.deleteMin(); + queue.remove(min); + } + + @Test(expected = ElementNotFoundException.class) + public void testRemoveTwice() { + Assume.assumeFalse(queue.isEmpty()); + queue.remove(parameters.data[4 % parameters.data.length]); + queue.remove(parameters.data[4 % parameters.data.length]); + } + + @Test + public void testRemove() { + int size1 = queue.size(); + for (int i = 0; i < parameters.deleteOrder.length; ++i) { + // Remove from structure + queue.remove(parameters.data[parameters.deleteOrder[i]]); + + // Copy the remaining elements + PriorityQueue copyTree = createQueue(queue); + + // Retrieve all remaining elements in both structures + ArrayList remains_in = new ArrayList<>(), + remains_cp = new ArrayList<>(); + for (int j = i + 1; j < parameters.deleteOrder.length; ++j) { + remains_in.add(parameters.data[parameters.deleteOrder[j]]); + remains_cp.add(copyTree.deleteMin()); + } + Collections.sort(remains_in); + + // Check that the copy is now empty, and that both list contains all + // elements. + assertTrue(copyTree.isEmpty()); + assertEquals(remains_in, remains_cp); + + // Check that the size of the original tree is correct. + assertEquals(--size1, queue.size()); + } + assertTrue(queue.isEmpty()); + } + + @Test + public void testRemoveThenAdd() { + Assume.assumeFalse(queue.isEmpty()); + int min = Collections.min(Arrays.asList(parameters.data)).get(); + for (MutableInteger mi: parameters.data) { + queue.remove(mi); + assertEquals(parameters.data.length - 1, queue.size()); + mi.set(--min); + queue.insert(mi); + assertEquals(parameters.data.length, queue.size()); + assertEquals(min, queue.findMin().get()); + } + } + +}