1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.collections4.bloomfilter;
18
19 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
20 import static org.junit.jupiter.api.Assertions.assertEquals;
21 import static org.junit.jupiter.api.Assertions.assertFalse;
22 import static org.junit.jupiter.api.Assertions.assertNotEquals;
23 import static org.junit.jupiter.api.Assertions.assertNotSame;
24 import static org.junit.jupiter.api.Assertions.assertSame;
25 import static org.junit.jupiter.api.Assertions.assertThrows;
26 import static org.junit.jupiter.api.Assertions.assertTrue;
27
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.Deque;
31 import java.util.LinkedList;
32 import java.util.List;
33 import java.util.NoSuchElementException;
34 import java.util.function.Consumer;
35 import java.util.function.Predicate;
36
37 import org.junit.jupiter.api.Test;
38 import org.junit.jupiter.params.ParameterizedTest;
39 import org.junit.jupiter.params.provider.ValueSource;
40
41 public class LayerManagerTest {
42
43 private final Shape shape = Shape.fromKM(17, 72);
44
45 @ParameterizedTest
46 @ValueSource(ints = {4, 10, 2, 1})
47 public void testAdvanceOnCount(final int breakAt) {
48 final Predicate<LayerManager<SimpleBloomFilter>> underTest = LayerManager.ExtendCheck.advanceOnCount(breakAt);
49 final LayerManager<SimpleBloomFilter> layerManager = testingBuilder().get();
50 for (int i = 0; i < breakAt - 1; i++) {
51 assertFalse(underTest.test(layerManager), "at " + i);
52 layerManager.getTarget().merge(TestingHashers.FROM1);
53 }
54 assertTrue(underTest.test(layerManager));
55 }
56
57 @Test
58 public void testAdvanceOnCountInvalidArguments() {
59 assertThrows(IllegalArgumentException.class, () -> LayerManager.ExtendCheck.advanceOnCount(0));
60 assertThrows(IllegalArgumentException.class, () -> LayerManager.ExtendCheck.advanceOnCount(-1));
61 }
62
63 @Test
64 public void testAdvanceOnPopulated() {
65 final Predicate<LayerManager<SimpleBloomFilter>> underTest = LayerManager.ExtendCheck.advanceOnPopulated();
66 final LayerManager<SimpleBloomFilter> layerManager = testingBuilder().get();
67 assertFalse(underTest.test(layerManager));
68 layerManager.getTarget().merge(TestingHashers.FROM1);
69 assertTrue(underTest.test(layerManager));
70 }
71
72 @Test
73 public void testAdvanceOnSaturation() {
74 final double maxN = shape.estimateMaxN();
75 int hashStart = 0;
76 final Predicate<LayerManager<SimpleBloomFilter>> underTest = LayerManager.ExtendCheck.advanceOnSaturation(maxN);
77 final LayerManager<SimpleBloomFilter> layerManager = testingBuilder().get();
78 while (layerManager.getTarget().getShape().estimateN(layerManager.getTarget().cardinality()) < maxN) {
79 assertFalse(underTest.test(layerManager));
80 layerManager.getTarget().merge(new IncrementingHasher(hashStart, shape.getNumberOfHashFunctions()));
81 hashStart += shape.getNumberOfHashFunctions();
82 }
83 assertTrue(underTest.test(layerManager));
84 assertThrows(IllegalArgumentException.class, () -> LayerManager.ExtendCheck.advanceOnSaturation(0));
85 assertThrows(IllegalArgumentException.class, () -> LayerManager.ExtendCheck.advanceOnSaturation(-1));
86 }
87
88 @Test
89 public void testBuilder() {
90 final LayerManager.Builder<SimpleBloomFilter> underTest = LayerManager.builder();
91 NullPointerException npe = assertThrows(NullPointerException.class, underTest::get);
92 assertTrue(npe.getMessage().contains("filterSupplier"));
93 underTest.setSupplier(() -> null).setCleanup(null);
94 npe = assertThrows(NullPointerException.class, underTest::get);
95 assertTrue(npe.getMessage().contains("filterCleanup"));
96 underTest.setCleanup(x -> {
97 }).setExtendCheck(null);
98 npe = assertThrows(NullPointerException.class, underTest::get);
99 assertTrue(npe.getMessage().contains("extendCheck"));
100
101 npe = assertThrows(NullPointerException.class, () -> LayerManager.builder().setSupplier(() -> null).get());
102 assertTrue(npe.getMessage().contains("filterSupplier.get() returned null."));
103
104 }
105
106 @Test
107 public void testClear() {
108 final LayerManager<SimpleBloomFilter> underTest = LayerManager.<SimpleBloomFilter>builder().setSupplier(() -> new SimpleBloomFilter(shape)).get();
109 underTest.getTarget().merge(TestingHashers.randomHasher());
110 underTest.next();
111 underTest.getTarget().merge(TestingHashers.randomHasher());
112 underTest.next();
113 underTest.getTarget().merge(TestingHashers.randomHasher());
114 assertEquals(3, underTest.getDepth());
115 underTest.clear();
116 assertEquals(1, underTest.getDepth());
117 assertEquals(0, underTest.getTarget().cardinality());
118 }
119
120 @Test
121 public void testCopy() {
122 final LayerManager<SimpleBloomFilter> underTest = LayerManager.<SimpleBloomFilter>builder().setSupplier(() -> new SimpleBloomFilter(shape)).get();
123 underTest.getTarget().merge(TestingHashers.randomHasher());
124 underTest.next();
125 underTest.getTarget().merge(TestingHashers.randomHasher());
126 underTest.next();
127 underTest.getTarget().merge(TestingHashers.randomHasher());
128 assertEquals(3, underTest.getDepth());
129
130 final LayerManager<SimpleBloomFilter> copy = underTest.copy();
131 assertNotSame(underTest, copy);
132
133 assertNotEquals(underTest, copy);
134
135 assertEquals(underTest.getDepth(), copy.getDepth());
136 assertTrue(
137 underTest.processBloomFilterPair(copy, (x, y) -> Arrays.equals(x.asBitMapArray(), y.asBitMapArray())));
138 }
139
140 @Test
141 public void testForEachBloomFilter() {
142 final LayerManager<SimpleBloomFilter> underTest = LayerManager.<SimpleBloomFilter>builder().setSupplier(() -> new SimpleBloomFilter(shape))
143 .setExtendCheck(LayerManager.ExtendCheck.advanceOnPopulated()).get();
144
145 final List<SimpleBloomFilter> lst = new ArrayList<>();
146 for (int i = 0; i < 10; i++) {
147 final SimpleBloomFilter bf = new SimpleBloomFilter(shape);
148 bf.merge(TestingHashers.randomHasher());
149 lst.add(bf);
150 underTest.getTarget().merge(bf);
151 }
152 final List<BloomFilter> lst2 = new ArrayList<>();
153 underTest.processBloomFilters(lst2::add);
154 assertEquals(10, lst.size());
155 assertEquals(10, lst2.size());
156 for (int i = 0; i < lst.size(); i++) {
157 assertArrayEquals(lst.get(i).asBitMapArray(), lst2.get(i).asBitMapArray());
158 }
159 }
160
161 @Test
162 public void testGet() {
163 final SimpleBloomFilter f = new SimpleBloomFilter(shape);
164 final LayerManager<SimpleBloomFilter> underTest = LayerManager.<SimpleBloomFilter>builder().setSupplier(() -> f).get();
165 assertEquals(1, underTest.getDepth());
166 assertSame(f, underTest.get(0));
167 assertThrows(NoSuchElementException.class, () -> underTest.get(-1));
168 assertThrows(NoSuchElementException.class, () -> underTest.get(1));
169 }
170
171 private LayerManager.Builder<SimpleBloomFilter> testingBuilder() {
172 return LayerManager.<SimpleBloomFilter>builder().setSupplier(() -> new SimpleBloomFilter(shape));
173 }
174
175 @Test
176 public void testNeverAdvance() {
177 final Predicate<LayerManager<SimpleBloomFilter>> underTest = LayerManager.ExtendCheck.neverAdvance();
178 final LayerManager<SimpleBloomFilter> layerManager = testingBuilder().get();
179 assertFalse(underTest.test(layerManager));
180 for (int i = 0; i < 10; i++) {
181 layerManager.getTarget().merge(TestingHashers.randomHasher());
182 assertFalse(underTest.test(layerManager));
183 }
184 }
185
186 @Test
187 public void testNextAndGetDepth() {
188 final LayerManager<SimpleBloomFilter> underTest = LayerManager.<SimpleBloomFilter>builder().setSupplier(() -> new SimpleBloomFilter(shape)).get();
189 assertEquals(1, underTest.getDepth());
190 underTest.getTarget().merge(TestingHashers.randomHasher());
191 assertEquals(1, underTest.getDepth());
192 underTest.next();
193 assertEquals(2, underTest.getDepth());
194 }
195
196 @Test
197 public void testNoCleanup() {
198 final Consumer<Deque<SimpleBloomFilter>> underTest = LayerManager.Cleanup.noCleanup();
199 final Deque<SimpleBloomFilter> list = new LinkedList<>();
200 for (int i = 0; i < 20; i++) {
201 assertEquals(i, list.size());
202 list.add(new SimpleBloomFilter(shape));
203 underTest.accept(list);
204 }
205 }
206
207 @ParameterizedTest
208 @ValueSource(ints = {5, 100, 2, 1})
209 public void testOnMaxSize(final int maxSize) {
210 final Consumer<Deque<SimpleBloomFilter>> underTest = LayerManager.Cleanup.onMaxSize(maxSize);
211 final LinkedList<SimpleBloomFilter> list = new LinkedList<>();
212 for (int i = 0; i < maxSize; i++) {
213 assertEquals(i, list.size());
214 list.add(new SimpleBloomFilter(shape));
215 underTest.accept(list);
216 }
217 assertEquals(maxSize, list.size());
218
219 for (int i = 0; i < maxSize; i++) {
220 list.add(new SimpleBloomFilter(shape));
221 underTest.accept(list);
222 assertEquals(maxSize, list.size());
223 }
224 }
225
226 @Test
227 public void testOnMaxSizeIllegalValues() {
228 assertThrows(IllegalArgumentException.class, () -> LayerManager.Cleanup.onMaxSize(0));
229 assertThrows(IllegalArgumentException.class, () -> LayerManager.Cleanup.onMaxSize(-1));
230 }
231
232 @Test
233 public void testRemoveEmptyTarget() {
234 final Consumer<Deque<SimpleBloomFilter>> underTest = LayerManager.Cleanup.removeEmptyTarget();
235 final LinkedList<SimpleBloomFilter> list = new LinkedList<>();
236
237
238 final SimpleBloomFilter bf = new SimpleBloomFilter(shape);
239 list.add(bf);
240 assertEquals(bf, list.get(0));
241 underTest.accept(list);
242 assertTrue(list.isEmpty());
243
244
245 bf.merge(IndexExtractor.fromIndexArray(1));
246 list.add(bf);
247 assertEquals(bf, list.get(0));
248 underTest.accept(list);
249 assertEquals(bf, list.get(0));
250
251
252 list.clear();
253 list.add(new SimpleBloomFilter(shape));
254 list.add(bf);
255 assertEquals(2, list.size());
256 underTest.accept(list);
257 assertEquals(2, list.size());
258
259
260
261 list.clear();
262 list.add(bf);
263 list.add(new SimpleBloomFilter(shape));
264 list.add(new SimpleBloomFilter(shape));
265 assertEquals(3, list.size());
266 underTest.accept(list);
267 assertEquals(2, list.size());
268 assertEquals(bf, list.get(0));
269 }
270
271 @Test
272 public void testTarget() {
273 final boolean[] extendCheckCalled = { false };
274 final boolean[] cleanupCalled = { false };
275 final int[] supplierCount = { 0 };
276 final LayerManager<SimpleBloomFilter> underTest = LayerManager.<SimpleBloomFilter>builder().setSupplier(() -> {
277 supplierCount[0]++;
278 return new SimpleBloomFilter(shape);
279 }).setExtendCheck(lm -> {
280 extendCheckCalled[0] = true;
281 return true;
282 }).setCleanup(ll -> {
283 cleanupCalled[0] = true;
284 }).get();
285 assertFalse(extendCheckCalled[0]);
286 assertFalse(cleanupCalled[0]);
287 assertEquals(1, supplierCount[0]);
288 underTest.getTarget();
289 assertTrue(extendCheckCalled[0]);
290 assertTrue(cleanupCalled[0]);
291 assertEquals(2, supplierCount[0]);
292 }
293
294 }