Skip to content

Commit

Permalink
added coco driven test cases.
Browse files Browse the repository at this point in the history
  • Loading branch information
Claudenw committed Jul 7, 2023
1 parent 6188866 commit 2967b1e
Show file tree
Hide file tree
Showing 12 changed files with 403 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.apache.commons.collections4.bloomfilter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.BiPredicate;
import java.util.function.Predicate;
Expand All @@ -27,6 +28,7 @@
* @since 4.5
*/
public interface BloomFilterProducer {

/**
* Executes a Bloom filter Predicate on each Bloom filter in the collection. The
* ordering of the Bloom filters is not specified by this interface.
Expand Down Expand Up @@ -65,4 +67,36 @@ default boolean forEachBloomFilterPair(final BloomFilterProducer other,
final CountingPredicate<BloomFilter> p = new CountingPredicate<>(asBloomFilterArray(), func);
return other.forEachBloomFilter(p) && p.forEachRemaining();
}

/**
* Creates a BloomFilterProducer from an array of Bloom filters.
*
* @param filters The filters to be returned by the producer.
* @return THe BloomFilterProducer containing the filters.
*/
static BloomFilterProducer fromBloomFilterArray(BloomFilter... filters) {
return new BloomFilterProducer() {
@Override
public boolean forEachBloomFilter(final Predicate<BloomFilter> predicate) {
for (final BloomFilter filter : filters) {
if (!predicate.test(filter)) {
return false;
}
}
return true;
}

@Override
public BloomFilter[] asBloomFilterArray() {
return Arrays.copyOf(filters, filters.length);
}

@Override
public boolean forEachBloomFilterPair(final BloomFilterProducer other,
final BiPredicate<BloomFilter, BloomFilter> func) {
final CountingPredicate<BloomFilter> p = new CountingPredicate<>(filters, func);
return other.forEachBloomFilter(p) && p.forEachRemaining();
}
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,6 @@ public static final Predicate<LayerManager> advanceOnSaturation(double maxN) {
throw new IllegalArgumentException("'maxN' must be greater than 0");
}
return manager -> {
if (manager.filters.isEmpty()) {
return false;
}
BloomFilter bf = manager.filters.peekLast();
return maxN <= bf.getShape().estimateN(bf.cardinality());
};
Expand All @@ -152,7 +149,7 @@ private Cleanup() {
};

private static final Consumer<LinkedList<BloomFilter>> REMOVE_EMPTY_TARGET = x -> {
if (!x.isEmpty() && x.getLast().cardinality() == 0) {
if (x.getLast().cardinality() == 0) {
x.removeLast();
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,10 @@
* <p>The counting Bloom filter extends the Bloom filter by counting the number of times a specific bit has been
* enabled or disabled. This allows the removal (opposite of merge) of Bloom filters at the expense of additional
* overhead.</p>
*
*
* <h3>LayeredBloomFilter</h3>
*
* <p>The layered Bloom filter extends the Bloom filter by creating layers of Bloom filters that can be queried as a single
* <p>The layered Bloom filter extends the Bloom filter by creating layers of Bloom filters that can be queried as a single
* Filter or as a set of filters. This adds the ability to perform windowing on streams of data.</p>
*
* <h3>Shape</h3>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections4.bloomfilter;

import static org.junit.Assert.assertFalse;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.function.BiPredicate;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public abstract class AbstractBloomFilterProducerTest {
private Shape shape = Shape.fromKM(17, 72);

BloomFilter one = new SimpleBloomFilter(shape);
BloomFilter two = new SimpleBloomFilter(shape);
int[] nullCount = { 0, 0 };
int[] equalityCount = { 0 };
BiPredicate<BloomFilter, BloomFilter> counter = (x, y) -> {
if (x == null) {
nullCount[0]++;
}
if (y == null) {
nullCount[1]++;
}
if (x != null && y != null && x.cardinality() == y.cardinality()) {
equalityCount[0]++;
}
return true;
};

@BeforeEach
public void setup() {
one.clear();
one.merge(IndexProducer.fromIndexArray(1));
two.clear();
two.merge(IndexProducer.fromIndexArray(1, 2));
nullCount[0] = 0;
nullCount[1] = 0;
equalityCount[0] = 0;
}

/**
* Creates a BloomFilterProducer that returns the filters (or their copy) in the order presented.
* @param filters The filters to return.
* @return A BloomFilterProducer that returns the filters in order.
*/
protected abstract BloomFilterProducer createUnderTest(BloomFilter... filters);

private BloomFilterProducer createUnderTest() {
return createUnderTest(one, two);
}

@Test
public void testAsBloomFilterArray() {
BloomFilter[] result = createUnderTest().asBloomFilterArray();
assertEquals(2, result.length);
assertEquals(1, result[0].cardinality());
assertEquals(2, result[1].cardinality());
}

@Test
public void testForEachPairCompleteMatch() {
assertTrue(createUnderTest().forEachBloomFilterPair(createUnderTest(), counter));
assertArrayEquals(new int[] { 0, 0 }, nullCount);
assertEquals(2, equalityCount[0]);
}

@Test
public void testForEachPairArrayTooShort() {
assertTrue(createUnderTest().forEachBloomFilterPair(BloomFilterProducer.fromBloomFilterArray(one), counter));
assertEquals(0, nullCount[0]);
assertEquals(1, nullCount[1]);
assertEquals(1, equalityCount[0]);
}

@Test
public void testForEachPairArrayTooLong() {
assertTrue(createUnderTest().forEachBloomFilterPair(BloomFilterProducer.fromBloomFilterArray(one, two, one),
counter));
assertEquals(1, nullCount[0]);
assertEquals(0, nullCount[1]);
assertEquals(2, equalityCount[0]);
}

@Test
public void testForEachPairReturnFalseLate() {
assertFalse(createUnderTest().forEachBloomFilterPair(BloomFilterProducer.fromBloomFilterArray(one, two, one),
counter.and((x, y) -> x != null && y != null)));
assertEquals(1, nullCount[0]);
assertEquals(0, nullCount[1]);
assertEquals(2, equalityCount[0]);
}

@Test
public void testForEachPairReturnFalseLateShortArray() {
assertFalse(createUnderTest().forEachBloomFilterPair(BloomFilterProducer.fromBloomFilterArray(one),
counter.and((x, y) -> x != null && y != null)));
assertEquals(0, nullCount[0]);
assertEquals(1, nullCount[1]);
assertEquals(1, equalityCount[0]);
}

@Test
public void testForEachPairReturnFalseEarly() {
assertFalse(createUnderTest().forEachBloomFilterPair(BloomFilterProducer.fromBloomFilterArray(one, two, one),
(x, y) -> false));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,16 @@ protected void testCardinalityAndIsEmpty(BloomFilter bf) {
assertFalse(bf.isEmpty(), "Wrong value at " + i);
assertEquals(i + 1, bf.cardinality(), "Wrong value at " + i);
}

// check operations in reverse order
bf.clear();
assertEquals(0, bf.cardinality());
assertTrue(bf.isEmpty());
for (int i = 0; i < getTestShape().getNumberOfBits(); i++) {
bf.merge(IndexProducer.fromIndexArray(i));
assertEquals(i + 1, bf.cardinality(), "Wrong value at " + i);
assertFalse(bf.isEmpty(), "Wrong value at " + i);
}
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections4.bloomfilter;

public class BloomFilterProducerFromBloomFilterArrayTest extends AbstractBloomFilterProducerTest{

@Override
protected BloomFilterProducer createUnderTest(BloomFilter... filters) {
return BloomFilterProducer.fromBloomFilterArray(filters);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections4.bloomfilter;

public class BloomFilterProducerFromLayeredBloomFilterTest extends AbstractBloomFilterProducerTest{

@Override
protected BloomFilterProducer createUnderTest(BloomFilter... filters) {
Shape shape = filters[0].getShape();
LayerManager layerManager = LayerManager.builder().supplier( () -> new SimpleBloomFilter(shape) )
.extendCheck( LayerManager.ExtendCheck.advanceOnPopulated())
.cleanup(LayerManager.Cleanup.noCleanup()).build();
LayeredBloomFilter underTest = new LayeredBloomFilter(shape, layerManager);
for (BloomFilter bf : filters) {
underTest.merge(bf);
}
return underTest;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections4.bloomfilter;

import static org.junit.Assert.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.Test;

public class CountingPredicateTest {

@Test
public void testAryShort() {
CountingPredicate<Integer> cp = new CountingPredicate<>(new Integer[0], (x, y) -> x == null);
assertTrue(cp.test(Integer.valueOf(1)));
}

@Test
public void testAryLong() {
Integer[] ary = { Integer.valueOf(1), Integer.valueOf(2) };
CountingPredicate<Integer> cp = new CountingPredicate<>(ary, (x, y) -> y == null);
assertTrue(cp.forEachRemaining());

// test last item not checked
cp = new CountingPredicate<>(ary, (x, y) -> y == Integer.valueOf(2));
assertFalse(cp.forEachRemaining());

// test last item fails
cp = new CountingPredicate<>(ary, (x, y) -> y == Integer.valueOf(1));
assertFalse(cp.forEachRemaining());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections4.bloomfilter;

import java.util.function.Predicate;

public class DefaultBloomFilterProducerTest extends AbstractBloomFilterProducerTest {

@Override
protected BloomFilterProducer createUnderTest(BloomFilter... filters) {
return new BloomFilterProducer() {
@Override
public boolean forEachBloomFilter(Predicate<BloomFilter> bloomFilterPredicate) {
for (BloomFilter bf : filters) {
if (!bloomFilterPredicate.test(bf)) {
return false;
}
}
return true;
}
};
}
}
Loading

0 comments on commit 2967b1e

Please sign in to comment.