diff --git a/src/test/java/org/apache/commons/collections4/bloomfilter/AbstractBloomFilterTest.java b/src/test/java/org/apache/commons/collections4/bloomfilter/AbstractBloomFilterTest.java index e1c8ab91b..089051e1f 100644 --- a/src/test/java/org/apache/commons/collections4/bloomfilter/AbstractBloomFilterTest.java +++ b/src/test/java/org/apache/commons/collections4/bloomfilter/AbstractBloomFilterTest.java @@ -23,8 +23,12 @@ import static org.junit.Assert.fail; import java.util.List; import java.util.PrimitiveIterator.OfInt; +import java.util.function.BiFunction; +import java.util.function.IntConsumer; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; + import org.apache.commons.collections4.bloomfilter.hasher.HashFunctionIdentity; import org.apache.commons.collections4.bloomfilter.hasher.Hasher; import org.apache.commons.collections4.bloomfilter.hasher.Shape; @@ -36,6 +40,41 @@ import org.junit.Test; */ public abstract class AbstractBloomFilterTest { + /** + * An implementation of BloomFilter that is used to test merge and cardinality + * operations with a filter type that does not match the type of the filter + * being tested. + */ + private static class TestBloomFilter extends AbstractBloomFilter { + /** The bits. */ + final BitSet bits; + + protected TestBloomFilter(Shape shape, BitSet bits) { + super(shape); + this.bits = bits; + } + + @Override + public long[] getBits() { + return bits.toLongArray(); + } + + @Override + public StaticHasher getHasher() { + return new StaticHasher(bits.stream().iterator(), getShape()); + } + + @Override + public void merge(BloomFilter other) { + throw new UnsupportedOperationException(); + } + + @Override + public void merge(Hasher hasher) { + throw new UnsupportedOperationException(); + } + } + /** * A HashFunctionIdentity for testing. */ @@ -108,6 +147,23 @@ public abstract class AbstractBloomFilterTest { */ @Test public final void andCardinalityTest() { + andCardinalityTest(this::createFilter); + } + + /** + * Tests that the andCardinality calculations are correct with a generic BloomFilter. + */ + @Test + public final void andCardinalityTest_GenenicBloomFilter() { + andCardinalityTest(this::createGenericFilter); + } + + /** + * Tests that the andCardinality calculations are correct. + * + * @param filterFactory the factory function to create the filter + */ + private void andCardinalityTest(BiFunction filterFactory) { final List lst = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17); final Hasher hasher = new StaticHasher(lst.iterator(), shape); @@ -116,7 +172,7 @@ public abstract class AbstractBloomFilterTest { final List lst2 = Arrays.asList(11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27); final Hasher hasher2 = new StaticHasher(lst2.iterator(), shape); - final BloomFilter bf2 = createFilter(hasher2, shape); + final BloomFilter bf2 = filterFactory.apply(hasher2, shape); assertEquals(7, bf.andCardinality(bf2)); } @@ -303,12 +359,25 @@ public abstract class AbstractBloomFilterTest { /** * Create the BloomFilter implementation we are testing. * - * @param hasher the hasher to use to create the filter.. + * @param hasher the hasher to use to create the filter. * @param shape the shape of the filter. * @return a BloomFilter implementation. */ protected abstract AbstractBloomFilter createFilter(Hasher hasher, Shape shape); + /** + * Create a generic BloomFilter implementation. + * + * @param hasher the hasher to use to create the filter. + * @param shape the shape of the filter. + * @return a BloomFilter implementation. + */ + private AbstractBloomFilter createGenericFilter(Hasher hasher, Shape shape) { + BitSet bits = new BitSet(); + hasher.getBits(shape).forEachRemaining((IntConsumer) bits::set); + return new TestBloomFilter(shape, bits); + } + /** * Tests that getBits() works correctly when multiple long values are returned. */ @@ -370,6 +439,23 @@ public abstract class AbstractBloomFilterTest { */ @Test public final void mergeTest_BloomFilter() { + mergeTest_BloomFilter(this::createFilter); + } + + /** + * Tests that merging bloom filters works as expected with a generic BloomFilter. + */ + @Test + public final void mergeTest_GenenicBloomFilter() { + mergeTest_BloomFilter(this::createGenericFilter); + } + + /** + * Tests that merging bloom filters works as expected. + * + * @param filterFactory the factory function to create the filter + */ + private void mergeTest_BloomFilter(BiFunction filterFactory) { final List lst = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17); final Hasher hasher = new StaticHasher(lst.iterator(), shape); @@ -377,7 +463,8 @@ public abstract class AbstractBloomFilterTest { final List lst2 = Arrays.asList(11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27); final Hasher hasher2 = new StaticHasher(lst2.iterator(), shape); - final BloomFilter bf2 = createFilter(hasher2, shape); + + final BloomFilter bf2 = filterFactory.apply(hasher2, shape); bf.merge(bf2); assertEquals(27, bf.cardinality()); @@ -450,6 +537,23 @@ public abstract class AbstractBloomFilterTest { */ @Test public final void orCardinalityTest() { + orCardinalityTest(this::createFilter); + } + + /** + * Tests that the orCardinality calculations are correct with a generic BloomFilter. + */ + @Test + public final void orCardinalityTest_GenenicBloomFilter() { + orCardinalityTest(this::createGenericFilter); + } + + /** + * Tests that the andCardinality calculations are correct. + * + * @param filterFactory the factory function to create the filter + */ + private void orCardinalityTest(BiFunction filterFactory) { final List lst = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17); final Hasher hasher = new StaticHasher(lst.iterator(), shape); @@ -458,7 +562,7 @@ public abstract class AbstractBloomFilterTest { final List lst2 = Arrays.asList(11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27); final Hasher hasher2 = new StaticHasher(lst2.iterator(), shape); - final BloomFilter bf2 = createFilter(hasher2, shape); + final BloomFilter bf2 = filterFactory.apply(hasher2, shape); assertEquals(27, bf.orCardinality(bf2)); } @@ -483,10 +587,27 @@ public abstract class AbstractBloomFilterTest { } /** - * Tests that the zorCardinality calculations are correct. + * Tests that the xorCardinality calculations are correct. */ @Test public final void xorCardinalityTest() { + xorCardinalityTest(this::createFilter); + } + + /** + * Tests that the xorCardinality calculations are correct with a generic BloomFilter. + */ + @Test + public final void xorCardinalityTest_GenenicBloomFilter() { + xorCardinalityTest(this::createGenericFilter); + } + + /** + * Tests that the andCardinality calculations are correct. + * + * @param filterFactory the factory function to create the filter + */ + private void xorCardinalityTest(BiFunction filterFactory) { final List lst = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17); final Hasher hasher = new StaticHasher(lst.iterator(), shape); @@ -494,7 +615,8 @@ public abstract class AbstractBloomFilterTest { final List lst2 = Arrays.asList(11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27); final Hasher hasher2 = new StaticHasher(lst2.iterator(), shape); - final BloomFilter bf2 = createFilter(hasher2, shape); + + final BloomFilter bf2 = filterFactory.apply(hasher2, shape); assertEquals(20, bf.xorCardinality(bf2)); } diff --git a/src/test/java/org/apache/commons/collections4/bloomfilter/BitSetBloomFilterTest.java b/src/test/java/org/apache/commons/collections4/bloomfilter/BitSetBloomFilterTest.java index c98bf1368..5c5aef7cb 100644 --- a/src/test/java/org/apache/commons/collections4/bloomfilter/BitSetBloomFilterTest.java +++ b/src/test/java/org/apache/commons/collections4/bloomfilter/BitSetBloomFilterTest.java @@ -16,47 +16,13 @@ */ package org.apache.commons.collections4.bloomfilter; -import static org.junit.Assert.assertEquals; -import java.util.Arrays; -import java.util.List; - import org.apache.commons.collections4.bloomfilter.hasher.Hasher; import org.apache.commons.collections4.bloomfilter.hasher.Shape; -import org.apache.commons.collections4.bloomfilter.hasher.StaticHasher; -import org.junit.Test; /** * Tests for the {@link BitSetBloomFilter}. */ public class BitSetBloomFilterTest extends AbstractBloomFilterTest { - - /** - * Test that andCardinality works for BitSetBloomFilter arguments. - */ - @Test - public void andCardinalityTest_BitSetBloomFilter() { - final Hasher hasher = new StaticHasher(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).iterator(), shape); - - final BitSetBloomFilter bf = createFilter(hasher, shape); - - Hasher hasher2 = new StaticHasher(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).iterator(), shape); - BitSetBloomFilter bf2 = createFilter(hasher2, shape); - - assertEquals(10, bf.andCardinality(bf2)); - assertEquals(10, bf2.andCardinality(bf)); - - hasher2 = new StaticHasher(Arrays.asList(1, 2, 3, 4, 5).iterator(), shape); - bf2 = createFilter(hasher2, shape); - - assertEquals(5, bf.andCardinality(bf2)); - assertEquals(5, bf2.andCardinality(bf)); - - hasher2 = new StaticHasher(Arrays.asList(11, 12, 13, 14, 15).iterator(), shape); - bf2 = createFilter(hasher2, shape); - assertEquals(0, bf.andCardinality(bf2)); - assertEquals(0, bf2.andCardinality(bf)); - } - @Override protected BitSetBloomFilter createEmptyFilter(final Shape shape) { return new BitSetBloomFilter(shape); @@ -66,51 +32,4 @@ public class BitSetBloomFilterTest extends AbstractBloomFilterTest { protected BitSetBloomFilter createFilter(final Hasher hasher, final Shape shape) { return new BitSetBloomFilter(hasher, shape); } - - /** - * Test that merge() works for BitSetBloomFilter arguments. - */ - @Test - public void mergeTest_BitSetBloomFilter() { - - final List lst = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17); - final Hasher hasher = new StaticHasher(lst.iterator(), shape); - - final BitSetBloomFilter bf = createFilter(hasher, shape); - - final List lst2 = Arrays.asList(11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27); - final Hasher hasher2 = new StaticHasher(lst2.iterator(), shape); - final BloomFilter bf2 = new BitSetBloomFilter(hasher2, shape); - - bf.merge(bf2); - - assertEquals(27, bf.cardinality()); - } - - /** - * Test that xorCardinality works for BitSetBloomFilter arguments. - */ - @Test - public void xorCardinalityTest_BitSetBloomFilter() { - final Hasher hasher = new StaticHasher(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).iterator(), shape); - - final BitSetBloomFilter bf = createFilter(hasher, shape); - - Hasher hasher2 = new StaticHasher(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).iterator(), shape); - BitSetBloomFilter bf2 = createFilter(hasher2, shape); - - assertEquals(0, bf.xorCardinality(bf2)); - assertEquals(0, bf2.xorCardinality(bf)); - - hasher2 = new StaticHasher(Arrays.asList(1, 2, 3, 4, 5).iterator(), shape); - bf2 = createFilter(hasher2, shape); - - assertEquals(5, bf.xorCardinality(bf2)); - assertEquals(5, bf2.xorCardinality(bf)); - - hasher2 = new StaticHasher(Arrays.asList(11, 12, 13, 14, 15).iterator(), shape); - bf2 = createFilter(hasher2, shape); - assertEquals(15, bf.xorCardinality(bf2)); - assertEquals(15, bf2.xorCardinality(bf)); - } }