Update BloomFilterIndex comments and added tests for negative index.

This commit is contained in:
Alex Herbert 2020-03-12 22:44:23 +00:00
parent 391d91e353
commit 3a981a01b7
2 changed files with 48 additions and 9 deletions

View File

@ -77,7 +77,8 @@ final class BloomFilterIndexer {
static long getLongBit(int bitIndex) {
// Bit shifts only use the first 6 bits. Thus it is not necessary to mask this
// using 0x3f (63) or compute bitIndex % 64.
// If the index is negative the shift will be in the opposite direction.
// Note: If the index is negative the shift will be (64 - (bitIndex & 0x3f)) and
// this will identify an incorrect bit.
return 1L << bitIndex;
}
}

View File

@ -19,6 +19,7 @@ package org.apache.commons.collections4.bloomfilter;
import org.junit.Assert;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
@ -34,21 +35,58 @@ public class BloomFilterIndexerTest {
@Test
public void testGetLongIndex() {
final Random rng = ThreadLocalRandom.current();
for (int i = 0; i < 10; i++) {
// Random positive number
final int index = rng.nextInt() >>> 1;
Assert.assertEquals(0, BloomFilterIndexer.getLongIndex(0));
for (final int index : getIndexes()) {
// getLongIndex is expected to identify a block of 64-bits (starting from zero)
Assert.assertEquals(index / Long.SIZE, BloomFilterIndexer.getLongIndex(index));
// Verify the behaviour for negatives. It should produce a negative (invalid)
// as a simple trip for incorrect usage.
Assert.assertTrue(BloomFilterIndexer.getLongIndex(-index) < 0);
// If index is not zero then when negated this is what a signed shift
// of 6-bits actually does
Assert.assertEquals(((1 - index) / Long.SIZE) - 1,
BloomFilterIndexer.getLongIndex(-index));
}
}
@Test
public void testGetLongBit() {
final Random rng = ThreadLocalRandom.current();
for (int i = 0; i < 10; i++) {
// Random positive number
final int index = rng.nextInt() >>> 1;
Assert.assertEquals(1L, BloomFilterIndexer.getLongBit(0));
for (final int index : getIndexes()) {
// getLongBit is expected to identify a single bit in a 64-bit block
Assert.assertEquals(1L << (index % Long.SIZE), BloomFilterIndexer.getLongBit(index));
// Verify the behaviour for negatives
Assert.assertEquals(1L << (64 - (index & 0x3f)), BloomFilterIndexer.getLongBit(-index));
}
}
/**
* Gets non-zero positive indexes for testing.
*
* @return the indices
*/
private static int[] getIndexes() {
final Random rng = ThreadLocalRandom.current();
ArrayList<Integer> indexes = new ArrayList<>(40);
for (int i = 0; i < 10; i++) {
// random positive numbers
indexes.add(rng.nextInt() >>> 1);
indexes.add(rng.nextInt(23647826));
indexes.add(rng.nextInt(245));
}
// Quickly remove zeros (as these cannot be negated)
indexes.removeIf(i -> i == 0);
// Add edge cases here
indexes.add(1);
indexes.add(2);
indexes.add(63);
indexes.add(64);
indexes.add(Integer.MAX_VALUE);
return indexes.stream().mapToInt(Integer::intValue).toArray();
}
}