/** * Tests that the the {@link CombineFn}, when applied to the provided input, produces the provided * output. Tests a variety of permutations of the input. */ public static <InputT, AccumT, OutputT> void testCombineFn( CombineFn<InputT, AccumT, OutputT> fn, List<InputT> input, final OutputT expected) { testCombineFn(fn, input, is(expected)); Collections.shuffle(input); testCombineFn(fn, input, is(expected)); }
private static <InputT, AccumT, OutputT> void checkCombineFnShardsMultipleOrders( CombineFn<InputT, AccumT, OutputT> fn, List<? extends Iterable<InputT>> shards, Matcher<? super OutputT> matcher) { checkCombineFnShardsSingleMerge(fn, shards, matcher); checkCombineFnShardsWithEmptyAccumulators(fn, shards, matcher); checkCombineFnShardsIncrementalMerging(fn, shards, matcher); Collections.shuffle(shards); checkCombineFnShardsSingleMerge(fn, shards, matcher); checkCombineFnShardsWithEmptyAccumulators(fn, shards, matcher); checkCombineFnShardsIncrementalMerging(fn, shards, matcher); }
public static <InputT, AccumT, OutputT> void testCombineFn( CombineFn<InputT, AccumT, OutputT> fn, List<InputT> input, Matcher<? super OutputT> matcher) { int size = input.size(); checkCombineFnShardsMultipleOrders(fn, Collections.singletonList(input), matcher); checkCombineFnShardsMultipleOrders(fn, shardEvenly(input, 2), matcher); if (size > 4) { checkCombineFnShardsMultipleOrders(fn, shardEvenly(input, size / 2), matcher); checkCombineFnShardsMultipleOrders( fn, shardEvenly(input, (int) (size / Math.sqrt(size))), matcher); } checkCombineFnShardsMultipleOrders(fn, shardExponentially(input, 1.4), matcher); checkCombineFnShardsMultipleOrders(fn, shardExponentially(input, 2), matcher); checkCombineFnShardsMultipleOrders(fn, shardExponentially(input, Math.E), matcher); }
private static <InputT, AccumT, OutputT> void checkCombineFnShardsWithEmptyAccumulators( CombineFn<InputT, AccumT, OutputT> fn, Iterable<? extends Iterable<InputT>> shards, Matcher<? super OutputT> matcher) { List<AccumT> accumulators = combineInputs(fn, shards); accumulators.add(0, fn.createAccumulator()); accumulators.add(fn.createAccumulator()); AccumT merged = fn.mergeAccumulators(accumulators); assertThat(fn.extractOutput(merged), matcher); }
private static <InputT, AccumT, OutputT> void checkCombineFnShardsSingleMerge( CombineFn<InputT, AccumT, OutputT> fn, Iterable<? extends Iterable<InputT>> shards, Matcher<? super OutputT> matcher) { List<AccumT> accumulators = combineInputs(fn, shards); AccumT merged = fn.mergeAccumulators(accumulators); assertThat(fn.extractOutput(merged), matcher); }
@Test public void testBinaryCombineFnWithNulls() { testCombineFn(new NullCombiner(), Arrays.asList(3, 3, 5), 45); testCombineFn(new NullCombiner(), Arrays.asList(null, 3, 5), 30); testCombineFn(new NullCombiner(), Arrays.asList(3, 3, null), 18); testCombineFn(new NullCombiner(), Arrays.asList(null, 3, null), 12); testCombineFn(new NullCombiner(), Arrays.asList(null, null, null), 8); }
private static <InputT, AccumT, OutputT> void checkCombineFnShardsIncrementalMerging( CombineFn<InputT, AccumT, OutputT> fn, List<? extends Iterable<InputT>> shards, Matcher<? super OutputT> matcher) { AccumT accumulator = shards.isEmpty() ? fn.createAccumulator() : null; for (AccumT inputAccum : combineInputs(fn, shards)) { if (accumulator == null) { accumulator = inputAccum; } else { accumulator = fn.mergeAccumulators(Arrays.asList(accumulator, inputAccum)); } fn.extractOutput(accumulator); // Extract output to simulate multiple firings } assertThat(fn.extractOutput(accumulator), matcher); }
@Test public void testLotsOfDuplicates() { List<Integer> all = new ArrayList<>(); all.add(1); for (int i = 1; i < 300; i++) { all.add(2); } for (int i = 300; i < 1000; i++) { all.add(3); } testCombineFn(ApproximateQuantilesCombineFn.create(5), all, Arrays.asList(1, 2, 3, 3, 3)); }
@Test public void testLogDistribution() { List<Integer> all = new ArrayList<>(); for (int i = 1; i < 1000; i++) { all.add((int) Math.log(i)); } testCombineFn(ApproximateQuantilesCombineFn.create(5), all, Arrays.asList(0, 5, 6, 6, 6)); }
@Test public void testZipfianDistribution() { List<Integer> all = new ArrayList<>(); for (int i = 1; i < 1000; i++) { all.add(1000 / i); } testCombineFn(ApproximateQuantilesCombineFn.create(5), all, Arrays.asList(1, 1, 2, 4, 1000)); }
@Test public void testSingleton() { testCombineFn( ApproximateQuantilesCombineFn.create(5), Arrays.asList(389), Arrays.asList(389, 389, 389, 389, 389)); }
@Test public void testAlternateComparator() { List<String> inputs = Arrays.asList("aa", "aaa", "aaaa", "b", "ccccc", "dddd", "zz"); testCombineFn( ApproximateQuantilesCombineFn.create(3), inputs, Arrays.asList("aa", "b", "zz")); testCombineFn( ApproximateQuantilesCombineFn.create(3, new OrderByLength()), inputs, Arrays.asList("b", "aaa", "ccccc")); }
@Test public void testDuplicates() { int size = 101; List<Integer> all = new ArrayList<>(); for (int i = 0; i < 10; i++) { all.addAll(intRange(size)); } testCombineFn( ApproximateQuantilesCombineFn.create(5), all, Arrays.asList(0, 25, 50, 75, 100)); }
@Test public void testSimpleQuantiles() { testCombineFn( ApproximateQuantilesCombineFn.create(5), intRange(101), Arrays.asList(0, 25, 50, 75, 100)); }
CombineFnTester.testCombineFn(combineFn, Arrays.asList(1, 2, 3, 4, 5), 15); assertThat(sawEmpty.get(), is(true));
CombineFnTester.testCombineFn( combineFn, Arrays.asList(1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3), 30); assertThat(sawManyShards.get(), is(true));
@Test public void testCombineFn() { CombineFnTester.testCombineFn( Sample.combineFn(limit), lines, allOf(Matchers.iterableWithSize(Math.min(lines.size(), limit)), everyItem(isIn(lines)))); } }
CombineFnTester.testCombineFn(combineFn, Arrays.asList(1, 1, 2, 2, 3, 3, 4, 4, 5, 5), 30); assertThat(sawMultipleMerges.get(), is(true));
private void runCombineFnTest(long elementCount, long uniqueCount, int sampleSize) { List<Double> input = LongStream.range(0, elementCount) .mapToObj(i -> 1.0 / (i % uniqueCount + 1)) .collect(Collectors.toList()); CombineFnTester.testCombineFn( new ApproximateUniqueCombineFn<>(sampleSize, DoubleCoder.of()), input, estimateIsWithinRangeFor(uniqueCount, sampleSize)); }
@Test public void usesMatcher() { final AtomicBoolean matcherUsed = new AtomicBoolean(); Matcher<Integer> matcher = new TypeSafeMatcher<Integer>() { @Override public void describeTo(Description description) {} @Override protected boolean matchesSafely(Integer item) { matcherUsed.set(true); return item == 30; } }; CombineFnTester.testCombineFn( Sum.ofIntegers(), Arrays.asList(1, 1, 2, 2, 3, 3, 4, 4, 5, 5), matcher); assertThat(matcherUsed.get(), is(true)); try { CombineFnTester.testCombineFn( Sum.ofIntegers(), Arrays.asList(1, 2, 3, 4, 5), Matchers.not(Matchers.equalTo(15))); } catch (AssertionError ignored) { // Success! Return to avoid the call to fail(); return; } fail("The matcher should have failed, throwing an error"); } }