View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.collections4.bloomfilter;
18  
19  import static org.junit.jupiter.api.Assertions.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertTrue;
21  
22  import org.junit.jupiter.params.ParameterizedTest;
23  import org.junit.jupiter.params.provider.CsvSource;
24  
25  public abstract class AbstractHasherTest extends AbstractIndexProducerTest {
26  
27      protected abstract Hasher createEmptyHasher();
28  
29      @Override
30      protected IndexProducer createEmptyProducer() {
31          return createEmptyHasher().indices(getTestShape());
32      }
33  
34      protected abstract Hasher createHasher();
35  
36      @Override
37      protected IndexProducer createProducer() {
38          return createHasher().indices(getTestShape());
39      }
40  
41      /**
42       * A method to get the number of items in a hasher. Mostly applies to
43       * Collections of hashers.
44       * @param hasher the hasher to check.
45       * @return the number of hashers in the hasher
46       */
47      protected abstract int getHasherSize(Hasher hasher);
48  
49      /**
50       * The shape of the Hashers filters for testing.
51       * <ul>
52       *  <li>Hash functions (k) = 17
53       *  <li>Number of bits (m) = 72
54       * </ul>
55       * @return the testing shape.
56       */
57      protected final Shape getTestShape() {
58          return Shape.fromKM(17, 72);
59      }
60  
61      @ParameterizedTest
62      @CsvSource({
63          "17, 72",
64          "3, 14",
65          "5, 67868",
66          "75, 10"
67      })
68      public void testHashing(final int k, final int m) {
69          final int[] count = {0};
70          final Hasher hasher = createHasher();
71          hasher.indices(Shape.fromKM(k, m)).forEachIndex(i -> {
72              assertTrue(i >= 0 && i < m, () -> "Out of range: " + i + ", m=" + m);
73              count[0]++;
74              return true;
75          });
76          assertEquals(k * getHasherSize(hasher), count[0],
77                  () -> String.format("Did not produce k=%d * m=%d indices", k, getHasherSize(hasher)));
78  
79          // test early exit
80          count[0] = 0;
81          hasher.indices(Shape.fromKM(k, m)).forEachIndex(i -> {
82              assertTrue(i >= 0 && i < m, () -> "Out of range: " + i + ", m=" + m);
83              count[0]++;
84              return false;
85          });
86          assertEquals(1, count[0], "did not exit early");
87      }
88  }