Remove HashFunctionIdentity comparators.

The comparators are never used to perform ordering of functions. The
only current use is to determine that two hash functions are
functionally equivalent. A replacement utility class has been added to
test for equality.
This commit is contained in:
aherbert 2020-02-18 13:35:58 +00:00
parent 66b418f3e9
commit 55cb720ccf
10 changed files with 197 additions and 401 deletions

View File

@ -212,6 +212,9 @@ public abstract class AbstractBloomFilter implements BloomFilter {
* @param hasher the Hasher to check * @param hasher the Hasher to check
*/ */
protected void verifyHasher(final Hasher hasher) { protected void verifyHasher(final Hasher hasher) {
// It is assumed that the filter and hasher have been constructed using the
// same hash function. Use the signature for a fast check the hash function is equal.
// Collisions will occur at a rate of 1 in 2^64.
if (shape.getHashFunctionIdentity().getSignature() != hasher.getHashFunctionIdentity().getSignature()) { if (shape.getHashFunctionIdentity().getSignature() != hasher.getHashFunctionIdentity().getSignature()) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
String.format("Hasher (%s) is not the hasher for shape (%s)", String.format("Hasher (%s) is not the hasher for shape (%s)",

View File

@ -177,13 +177,8 @@ public class DynamicHasher implements Hasher {
*/ */
@Override @Override
public PrimitiveIterator.OfInt getBits(final Shape shape) { public PrimitiveIterator.OfInt getBits(final Shape shape) {
if (HashFunctionIdentity.COMMON_COMPARATOR.compare(getHashFunctionIdentity(), HashFunctionValidator.checkAreEqual(getHashFunctionIdentity(),
shape.getHashFunctionIdentity()) != 0) { shape.getHashFunctionIdentity());
throw new IllegalArgumentException(
String.format("Shape hasher %s is not %s",
HashFunctionIdentity.asCommonString(shape.getHashFunctionIdentity()),
HashFunctionIdentity.asCommonString(getHashFunctionIdentity())));
}
// Use optimised iterator for no values // Use optimised iterator for no values
return buffers.isEmpty() ? NoValuesIterator.INSTANCE : new Iterator(shape); return buffers.isEmpty() ? NoValuesIterator.INSTANCE : new Iterator(shape);
} }

View File

@ -18,7 +18,6 @@
package org.apache.commons.collections4.bloomfilter.hasher; package org.apache.commons.collections4.bloomfilter.hasher;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Comparator;
import java.util.Locale; import java.util.Locale;
/** /**
@ -63,39 +62,6 @@ public interface HashFunctionIdentity {
SIGNED, UNSIGNED SIGNED, UNSIGNED
} }
/**
* A comparator implementation that performs the most common comparison using the
* HashFunctionIdentity name, signedness, and process.
*/
Comparator<HashFunctionIdentity> COMMON_COMPARATOR = new Comparator<HashFunctionIdentity>() {
@Override
public int compare(final HashFunctionIdentity identity1, final HashFunctionIdentity identity2) {
int result = identity1.getName().compareToIgnoreCase(identity2.getName());
if (result == 0) {
result = identity1.getSignedness().compareTo(identity2.getSignedness());
}
if (result == 0) {
result = identity1.getProcessType().compareTo(identity2.getProcessType());
}
return result;
}
};
/**
* A comparator implementation that performs the comparison using all the properties of the
* HashFunctionIdentity: name, signedness, process, and provider.
*/
Comparator<HashFunctionIdentity> DEEP_COMPARATOR = new Comparator<HashFunctionIdentity>() {
@Override
public int compare(final HashFunctionIdentity identity1, final HashFunctionIdentity identity2) {
int result = COMMON_COMPARATOR.compare(identity1, identity2);
if (result == 0) {
result = identity1.getProvider().compareToIgnoreCase(identity2.getProvider());
}
return result;
}
};
/** /**
* Gets a common formatted string for general display. * Gets a common formatted string for general display.
* *
@ -119,7 +85,6 @@ public interface HashFunctionIdentity {
* @return the signature buffer for the identity * @return the signature buffer for the identity
*/ */
static byte[] prepareSignatureBuffer(final HashFunctionIdentity identity) { static byte[] prepareSignatureBuffer(final HashFunctionIdentity identity) {
return String.format("%s-%s-%s", return String.format("%s-%s-%s",
identity.getName().toUpperCase(Locale.ROOT), identity.getSignedness(), identity.getName().toUpperCase(Locale.ROOT), identity.getSignedness(),
identity.getProcessType()).getBytes(StandardCharsets.UTF_8); identity.getProcessType()).getBytes(StandardCharsets.UTF_8);

View File

@ -0,0 +1,61 @@
/*
* 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.hasher;
/**
* Contains validation for hash functions.
*/
final class HashFunctionValidator {
/** Do not instantiate. */
private HashFunctionValidator() {}
/**
* Compares the identity of the two hash functions. The functions are considered
* equal if the signedness, process type and name are equal. The name is not
* case specific.
*
* <p>A pair of functions that are equal would be expected to produce the same
* hash output from the same input.
*
* @param a First hash function.
* @param b Second hash function.
* @return true, if successful
* @see String#equalsIgnoreCase(String)
*/
static boolean areEqual(HashFunctionIdentity a, HashFunctionIdentity b) {
return (a.getSignedness() == b.getSignedness() &&
a.getProcessType() == b.getProcessType() &&
a.getName().equalsIgnoreCase(b.getName()));
}
/**
* Compares the identity of the two hash functions and throws an exception if they
* are not equal.
*
* @param a First hash function.
* @param b Second hash function.
* @see #areEqual(HashFunctionIdentity, HashFunctionIdentity)
* @throws IllegalArgumentException if the hash functions are not equal
*/
static void checkAreEqual(HashFunctionIdentity a, HashFunctionIdentity b) {
if (!areEqual(a, b)) {
throw new IllegalArgumentException(String.format("Hash functions are not equal: (%s) != (%s)",
HashFunctionIdentity.asCommonString(a), HashFunctionIdentity.asCommonString(b)));
}
}
}

View File

@ -232,7 +232,7 @@ public class Shape {
* @param numberOfBits the number of bits in the filter. * @param numberOfBits the number of bits in the filter.
* @return the optimal number of hash functions. * @return the optimal number of hash functions.
*/ */
private int calculateNumberOfHashFunctions(final int numberOfItems, final int numberOfBits) { private static int calculateNumberOfHashFunctions(final int numberOfItems, final int numberOfBits) {
/* /*
* k = round((m / n) * log(2)) We change order so that we use real math rather * k = round((m / n) * log(2)) We change order so that we use real math rather
* than integer math. * than integer math.
@ -258,8 +258,8 @@ public class Shape {
return return
other.getNumberOfBits() == getNumberOfBits() && other.getNumberOfBits() == getNumberOfBits() &&
other.getNumberOfHashFunctions() == getNumberOfHashFunctions() && other.getNumberOfHashFunctions() == getNumberOfHashFunctions() &&
HashFunctionIdentity.COMMON_COMPARATOR.compare(getHashFunctionIdentity(), HashFunctionValidator.areEqual(getHashFunctionIdentity(),
other.getHashFunctionIdentity()) == 0; other.getHashFunctionIdentity());
} }
return false; return false;
} }

View File

@ -48,11 +48,8 @@ public final class StaticHasher implements Hasher {
*/ */
public StaticHasher(final Hasher hasher, final Shape shape) { public StaticHasher(final Hasher hasher, final Shape shape) {
this(hasher.getBits(shape), shape); this(hasher.getBits(shape), shape);
if (HashFunctionIdentity.COMMON_COMPARATOR.compare(hasher.getHashFunctionIdentity(), HashFunctionValidator.checkAreEqual(hasher.getHashFunctionIdentity(),
shape.getHashFunctionIdentity()) != 0) { shape.getHashFunctionIdentity());
throw new IllegalArgumentException(String.format("Hasher (%s) is not the same as for shape (%s)",
HashFunctionIdentity.asCommonString(hasher.getHashFunctionIdentity()), shape.toString()));
}
} }
/** /**

View File

@ -1,161 +0,0 @@
/*
* 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.hasher;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.TreeSet;
import org.apache.commons.collections4.bloomfilter.hasher.HashFunctionIdentity.ProcessType;
import org.apache.commons.collections4.bloomfilter.hasher.HashFunctionIdentity.Signedness;
import org.junit.Test;
/**
* Tests of the {@link HashFunctionIdentity#COMMON_COMPARATOR}.
*/
public class CommonComparatorTest {
private static void assertAfter(final HashFunctionIdentity identity1, final HashFunctionIdentity identity2) {
assertTrue(0 < HashFunctionIdentity.COMMON_COMPARATOR.compare(identity1, identity2));
}
private static void assertBefore(final HashFunctionIdentity identity1, final HashFunctionIdentity identity2) {
assertTrue(0 > HashFunctionIdentity.COMMON_COMPARATOR.compare(identity1, identity2));
}
/**
* Tests the name ordering is not affected by case.
*/
@Test
public void nameOrderTestDifferentCapitalization() {
final HashFunctionIdentityImpl impl1 = new HashFunctionIdentityImpl("Testing Suite", "impl1", Signedness.SIGNED,
ProcessType.CYCLIC, 300L);
final HashFunctionIdentityImpl impl2 = new HashFunctionIdentityImpl("Testing Suite", "IMPL1", Signedness.SIGNED,
ProcessType.CYCLIC, 300L);
assertEquals(0, HashFunctionIdentity.COMMON_COMPARATOR.compare(impl1, impl2));
}
/**
* Tests the name ordering.
*/
@Test
public void nameOrderTestDifferentNames() {
final HashFunctionIdentityImpl impl1 = new HashFunctionIdentityImpl("Testing Suite", "impl1", Signedness.SIGNED,
ProcessType.CYCLIC, 300L);
final HashFunctionIdentityImpl impl2 = new HashFunctionIdentityImpl("Testing Suite", "impl2", Signedness.SIGNED,
ProcessType.CYCLIC, 300L);
assertBefore(impl1, impl2);
assertEquals(0, HashFunctionIdentity.COMMON_COMPARATOR.compare(impl1, impl1));
assertEquals(0, HashFunctionIdentity.COMMON_COMPARATOR.compare(impl2, impl2));
assertAfter(impl2, impl1);
}
/**
* Tests that the process type ordering in correct.
*/
@Test
public void processTypeOrder() {
final HashFunctionIdentityImpl impl1 = new HashFunctionIdentityImpl("Testing Suite", "impl1", Signedness.SIGNED,
ProcessType.CYCLIC, 300L);
final HashFunctionIdentityImpl impl2 = new HashFunctionIdentityImpl("Testing Suite", "impl1", Signedness.SIGNED,
ProcessType.ITERATIVE, 300L);
assertBefore(impl1, impl2);
assertEquals(0, HashFunctionIdentity.COMMON_COMPARATOR.compare(impl1, impl1));
assertEquals(0, HashFunctionIdentity.COMMON_COMPARATOR.compare(impl2, impl2));
assertAfter(impl2, impl1);
}
/**
* Tests that a change in producer does not change the order.
*/
@Test
public void producerDoesNotChangeOrder() {
final HashFunctionIdentityImpl impl1 = new HashFunctionIdentityImpl("Testing Suite", "impl1", Signedness.SIGNED,
ProcessType.CYCLIC, 300L);
final HashFunctionIdentityImpl impl2 = new HashFunctionIdentityImpl("Testing Suite2", "impl1", Signedness.SIGNED,
ProcessType.CYCLIC, 300L);
assertEquals(0, HashFunctionIdentity.COMMON_COMPARATOR.compare(impl1, impl2));
}
/**
* Tests that signedness ordering is correct.
*/
@Test
public void signednessOrder() {
final HashFunctionIdentityImpl impl1 = new HashFunctionIdentityImpl("Testing Suite", "impl1", Signedness.SIGNED,
ProcessType.CYCLIC, 300L);
final HashFunctionIdentityImpl impl2 = new HashFunctionIdentityImpl("Testing Suite", "impl1", Signedness.UNSIGNED,
ProcessType.CYCLIC, 300L);
assertBefore(impl1, impl2);
assertEquals(0, HashFunctionIdentity.COMMON_COMPARATOR.compare(impl1, impl1));
assertEquals(0, HashFunctionIdentity.COMMON_COMPARATOR.compare(impl2, impl2));
assertAfter(impl2, impl1);
}
/**
* Tests that the ordering is correct when applied ot a collection.
*/
@Test
public void testSortOrder() {
// in this test the signature is the position in the final collection for the ID
final TreeSet<HashFunctionIdentity> result = new TreeSet<>(
HashFunctionIdentity.COMMON_COMPARATOR);
final List<HashFunctionIdentity> collection = new ArrayList<>();
collection
.add(new HashFunctionIdentityImpl("Testing Suite", "impl1", Signedness.SIGNED, ProcessType.CYCLIC, 0));
collection
.add(new HashFunctionIdentityImpl("Testing Suite", "impl1", Signedness.SIGNED, ProcessType.ITERATIVE, 1));
collection
.add(new HashFunctionIdentityImpl("Testing Suite", "impl1", Signedness.UNSIGNED, ProcessType.CYCLIC, 2));
collection
.add(new HashFunctionIdentityImpl("Testing Suite", "impl1", Signedness.UNSIGNED, ProcessType.ITERATIVE, 3));
collection
.add(new HashFunctionIdentityImpl("Testing Suite", "impl2", Signedness.SIGNED, ProcessType.CYCLIC, 4));
collection
.add(new HashFunctionIdentityImpl("Testing Suite", "impl2", Signedness.SIGNED, ProcessType.ITERATIVE, 5));
collection
.add(new HashFunctionIdentityImpl("Testing Suite", "impl2", Signedness.UNSIGNED, ProcessType.CYCLIC, 6));
collection
.add(new HashFunctionIdentityImpl("Testing Suite", "impl2", Signedness.UNSIGNED, ProcessType.ITERATIVE, 7));
Collections.shuffle(collection);
result.addAll(collection);
long idx = 0;
for (final HashFunctionIdentity id : result) {
assertEquals("Unexpected order for " + HashFunctionIdentity.asCommonString(id), idx++, id.getSignature());
}
}
}

View File

@ -1,188 +0,0 @@
/*
* 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.hasher;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.TreeSet;
import org.apache.commons.collections4.bloomfilter.hasher.HashFunctionIdentity.ProcessType;
import org.apache.commons.collections4.bloomfilter.hasher.HashFunctionIdentity.Signedness;
import org.junit.Test;
/**
* Tests of the {@link HashFunctionIdentity#DEEP_COMPARATOR}.
*/
public class DeepComparatorTest {
private static void assertAfter(final HashFunctionIdentity identity1, final HashFunctionIdentity identity2) {
assertTrue(0 < HashFunctionIdentity.DEEP_COMPARATOR.compare(identity1, identity2));
}
private static void assertBefore(final HashFunctionIdentity identity1, final HashFunctionIdentity identity2) {
assertTrue(0 > HashFunctionIdentity.DEEP_COMPARATOR.compare(identity1, identity2));
}
/**
* Tests that name order is not affected by case.
*/
@Test
public void nameOrderTestDifferentCapitalization() {
final HashFunctionIdentityImpl impl1 = new HashFunctionIdentityImpl("Testing Suite", "impl1", Signedness.SIGNED,
ProcessType.CYCLIC, 300L);
final HashFunctionIdentityImpl impl2 = new HashFunctionIdentityImpl("Testing Suite", "IMPL1", Signedness.SIGNED,
ProcessType.CYCLIC, 300L);
assertEquals(0, HashFunctionIdentity.DEEP_COMPARATOR.compare(impl1, impl2));
}
/**
* Tests that name order is correct.
*/
@Test
public void nameOrderTestDifferentNames() {
final HashFunctionIdentityImpl impl1 = new HashFunctionIdentityImpl("Testing Suite", "impl1", Signedness.SIGNED,
ProcessType.CYCLIC, 300L);
final HashFunctionIdentityImpl impl2 = new HashFunctionIdentityImpl("Testing Suite", "impl2", Signedness.SIGNED,
ProcessType.CYCLIC, 300L);
assertBefore(impl1, impl2);
assertEquals(0, HashFunctionIdentity.DEEP_COMPARATOR.compare(impl1, impl1));
assertEquals(0, HashFunctionIdentity.DEEP_COMPARATOR.compare(impl2, impl2));
assertAfter(impl2, impl1);
}
/**
* Tests that process type order is correct.
*/
@Test
public void processTypeOrder() {
final HashFunctionIdentityImpl impl1 = new HashFunctionIdentityImpl("Testing Suite", "impl1", Signedness.SIGNED,
ProcessType.CYCLIC, 300L);
final HashFunctionIdentityImpl impl2 = new HashFunctionIdentityImpl("Testing Suite", "impl1", Signedness.SIGNED,
ProcessType.ITERATIVE, 300L);
assertBefore(impl1, impl2);
assertEquals(0, HashFunctionIdentity.DEEP_COMPARATOR.compare(impl1, impl1));
assertEquals(0, HashFunctionIdentity.DEEP_COMPARATOR.compare(impl2, impl2));
assertAfter(impl2, impl1);
}
/**
* Tests that producer order is correct.
*/
@Test
public void producerOrder() {
final HashFunctionIdentityImpl impl1 = new HashFunctionIdentityImpl("Testing Suite", "impl1", Signedness.SIGNED,
ProcessType.CYCLIC, 300L);
final HashFunctionIdentityImpl impl2 = new HashFunctionIdentityImpl("Testing Suite2", "impl1", Signedness.SIGNED,
ProcessType.CYCLIC, 300L);
assertBefore(impl1, impl2);
assertEquals(0, HashFunctionIdentity.DEEP_COMPARATOR.compare(impl1, impl1));
assertEquals(0, HashFunctionIdentity.DEEP_COMPARATOR.compare(impl2, impl2));
assertAfter(impl2, impl1);
}
/**
* Tests that signedness order is correct.
*/
@Test
public void signednessOrder() {
final HashFunctionIdentityImpl impl1 = new HashFunctionIdentityImpl("Testing Suite", "impl1", Signedness.SIGNED,
ProcessType.CYCLIC, 300L);
final HashFunctionIdentityImpl impl2 = new HashFunctionIdentityImpl("Testing Suite", "impl1", Signedness.UNSIGNED,
ProcessType.CYCLIC, 300L);
assertBefore(impl1, impl2);
assertEquals(0, HashFunctionIdentity.DEEP_COMPARATOR.compare(impl1, impl1));
assertEquals(0, HashFunctionIdentity.DEEP_COMPARATOR.compare(impl2, impl2));
assertAfter(impl2, impl1);
}
/**
* Tests that the ordering is correct when applied ot a collection.
*/
@Test
public void testSortOrder() {
// in this test the signature is the position in the final collection for the ID
final TreeSet<HashFunctionIdentity> result = new TreeSet<>(HashFunctionIdentity.DEEP_COMPARATOR);
final List<HashFunctionIdentity> collection = new ArrayList<>();
collection
.add(new HashFunctionIdentityImpl("Testing Suite", "impl1", Signedness.SIGNED, ProcessType.CYCLIC, 0));
collection
.add(new HashFunctionIdentityImpl("Testing Suite", "impl1", Signedness.SIGNED, ProcessType.ITERATIVE, 2));
collection
.add(new HashFunctionIdentityImpl("Testing Suite", "impl1", Signedness.UNSIGNED, ProcessType.CYCLIC, 4));
collection
.add(new HashFunctionIdentityImpl("Testing Suite", "impl1", Signedness.UNSIGNED, ProcessType.ITERATIVE, 6));
collection
.add(new HashFunctionIdentityImpl("Testing Suite", "impl2", Signedness.SIGNED, ProcessType.CYCLIC, 8));
collection
.add(new HashFunctionIdentityImpl("Testing Suite", "impl2", Signedness.SIGNED, ProcessType.ITERATIVE, 10));
collection
.add(new HashFunctionIdentityImpl("Testing Suite", "impl2", Signedness.UNSIGNED, ProcessType.CYCLIC, 12));
collection.add(
new HashFunctionIdentityImpl("Testing Suite", "impl2", Signedness.UNSIGNED, ProcessType.ITERATIVE, 14));
collection
.add(new HashFunctionIdentityImpl("Testing Suite2", "impl1", Signedness.SIGNED, ProcessType.CYCLIC, 1));
collection
.add(new HashFunctionIdentityImpl("Testing Suite2", "impl1", Signedness.SIGNED, ProcessType.ITERATIVE, 3));
collection
.add(new HashFunctionIdentityImpl("Testing Suite2", "impl1", Signedness.UNSIGNED, ProcessType.CYCLIC, 5));
collection.add(
new HashFunctionIdentityImpl("Testing Suite2", "impl1", Signedness.UNSIGNED, ProcessType.ITERATIVE, 7));
collection
.add(new HashFunctionIdentityImpl("Testing Suite2", "impl2", Signedness.SIGNED, ProcessType.CYCLIC, 9));
collection
.add(new HashFunctionIdentityImpl("Testing Suite2", "impl2", Signedness.SIGNED, ProcessType.ITERATIVE, 11));
collection
.add(new HashFunctionIdentityImpl("Testing Suite2", "impl2", Signedness.UNSIGNED, ProcessType.CYCLIC, 13));
collection.add(
new HashFunctionIdentityImpl("Testing Suite2", "impl2", Signedness.UNSIGNED, ProcessType.ITERATIVE, 15));
Collections.shuffle(collection);
result.addAll(collection);
long idx = 0;
for (final HashFunctionIdentity id : result) {
assertEquals("Unexpected order for " + id.getProvider() + ":" + HashFunctionIdentity.asCommonString(id),
idx++, id.getSignature());
}
}
}

View File

@ -0,0 +1,120 @@
/*
* 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.hasher;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.apache.commons.collections4.bloomfilter.hasher.HashFunctionIdentity.ProcessType;
import org.apache.commons.collections4.bloomfilter.hasher.HashFunctionIdentity.Signedness;
import org.junit.Test;
/**
* Tests of the {@link HashFunctionValidator}.
*/
public class HashFuctionValidatorTest {
/**
* Tests that name is used in the equality check.
*/
@Test
public void testName() {
final HashFunctionIdentityImpl impl1 = new HashFunctionIdentityImpl("Testing Suite", "impl1", Signedness.SIGNED,
ProcessType.CYCLIC, 300L);
final HashFunctionIdentityImpl impl2 = new HashFunctionIdentityImpl("Testing Suite", "impl2", Signedness.SIGNED,
ProcessType.CYCLIC, 300L);
assertTrue(HashFunctionValidator.areEqual(impl1, impl1));
assertTrue(HashFunctionValidator.areEqual(impl2, impl2));
assertFalse(HashFunctionValidator.areEqual(impl1, impl2));
assertFalse(HashFunctionValidator.areEqual(impl2, impl1));
}
/**
* Tests that name is not affected by case.
*/
@Test
public void testNameIsCaseInsensitive() {
final HashFunctionIdentityImpl impl1 = new HashFunctionIdentityImpl("Testing Suite", "impl1", Signedness.SIGNED,
ProcessType.CYCLIC, 300L);
final HashFunctionIdentityImpl impl2 = new HashFunctionIdentityImpl("Testing Suite", "IMPL1", Signedness.SIGNED,
ProcessType.CYCLIC, 300L);
assertTrue(HashFunctionValidator.areEqual(impl1, impl2));
}
/**
* Tests that process type is used in the equality check.
*/
@Test
public void testProcessType() {
final HashFunctionIdentityImpl impl1 = new HashFunctionIdentityImpl("Testing Suite", "impl1", Signedness.SIGNED,
ProcessType.CYCLIC, 300L);
final HashFunctionIdentityImpl impl2 = new HashFunctionIdentityImpl("Testing Suite", "impl1", Signedness.SIGNED,
ProcessType.ITERATIVE, 300L);
assertTrue(HashFunctionValidator.areEqual(impl1, impl1));
assertTrue(HashFunctionValidator.areEqual(impl2, impl2));
assertFalse(HashFunctionValidator.areEqual(impl1, impl2));
assertFalse(HashFunctionValidator.areEqual(impl2, impl1));
}
/**
* Tests that provider is <strong>not</strong> used in the equality check.
*/
@Test
public void testProviderIsNotUsedInEqualityCheck() {
final HashFunctionIdentityImpl impl1 = new HashFunctionIdentityImpl("Testing Suite", "impl1", Signedness.SIGNED,
ProcessType.CYCLIC, 300L);
final HashFunctionIdentityImpl impl2 = new HashFunctionIdentityImpl("Testing Suite2", "impl1", Signedness.SIGNED,
ProcessType.CYCLIC, 300L);
assertTrue(HashFunctionValidator.areEqual(impl1, impl1));
assertTrue(HashFunctionValidator.areEqual(impl2, impl2));
assertTrue(HashFunctionValidator.areEqual(impl1, impl2));
assertTrue(HashFunctionValidator.areEqual(impl2, impl1));
}
/**
* Tests that signedness is used in the equality check.
*/
@Test
public void testSignedness() {
final HashFunctionIdentityImpl impl1 = new HashFunctionIdentityImpl("Testing Suite", "impl1", Signedness.SIGNED,
ProcessType.CYCLIC, 300L);
final HashFunctionIdentityImpl impl2 = new HashFunctionIdentityImpl("Testing Suite", "impl1", Signedness.UNSIGNED,
ProcessType.CYCLIC, 300L);
assertTrue(HashFunctionValidator.areEqual(impl1, impl1));
assertTrue(HashFunctionValidator.areEqual(impl2, impl2));
assertFalse(HashFunctionValidator.areEqual(impl1, impl2));
assertFalse(HashFunctionValidator.areEqual(impl2, impl1));
}
/**
* Test the check method throws when the two hash functions are not equal.
*/
@Test(expected=IllegalArgumentException.class)
public void testCheckThrows() {
final HashFunctionIdentityImpl impl1 = new HashFunctionIdentityImpl("Testing Suite", "impl1", Signedness.SIGNED,
ProcessType.CYCLIC, 300L);
final HashFunctionIdentityImpl impl2 = new HashFunctionIdentityImpl("Testing Suite", "impl1", Signedness.UNSIGNED,
ProcessType.CYCLIC, 300L);
HashFunctionValidator.checkAreEqual(impl1, impl2);
}
}

View File

@ -187,7 +187,11 @@ public class StaticHasherTest {
assertEquals(5, hasher.size()); assertEquals(5, hasher.size());
assertEquals(shape, hasher.getShape()); assertEquals(shape, hasher.getShape());
assertEquals(0, HashFunctionIdentity.DEEP_COMPARATOR.compare(testFunction, hasher.getHashFunctionIdentity())); // All function properties are equal
assertEquals(testFunction.getName(), hasher.getHashFunctionIdentity().getName());
assertEquals(testFunction.getProcessType(), hasher.getHashFunctionIdentity().getProcessType());
assertEquals(testFunction.getProvider(), hasher.getHashFunctionIdentity().getProvider());
assertEquals(testFunction.getSignedness(), hasher.getHashFunctionIdentity().getSignedness());
iter = hasher.getBits(shape); iter = hasher.getBits(shape);
int idx = 0; int idx = 0;