/* __ __ __ __ __ ___ * \ \ / / \ \ / / __/ * \ \/ / /\ \ \/ / / * \____/__/ \__\____/__/.ɪᴏ * ᶜᵒᵖʸʳᶦᵍʰᵗ ᵇʸ ᵛᵃᵛʳ ⁻ ˡᶦᶜᵉⁿˢᵉᵈ ᵘⁿᵈᵉʳ ᵗʰᵉ ᵃᵖᵃᶜʰᵉ ˡᶦᶜᵉⁿˢᵉ ᵛᵉʳˢᶦᵒⁿ ᵗʷᵒ ᵈᵒᵗ ᶻᵉʳᵒ */ package io.vavr.test; import io.vavr.Tuple; import io.vavr.collection.Stream; import io.vavr.Tuple2; import io.vavr.collection.List; import org.junit.Test; import java.util.Arrays; import java.util.Random; import java.util.function.Predicate; import java.util.function.Supplier; import static org.assertj.core.api.Assertions.assertThat; public class GenTest { // equally distributed random number generator static final Random RANDOM = new Random(); // number of tries to assert a property static final int TRIES = 1000; // -- of @Test public void shouldIntersperseMultipleGeneratos() throws Exception { Gen<Integer> gen = Gen.of(0).intersperse(Gen.of(1)); assertThat(gen.apply(RANDOM)).isEqualTo(0); assertThat(gen.apply(RANDOM)).isEqualTo(1); assertThat(gen.apply(RANDOM)).isEqualTo(0); assertThat(gen.apply(RANDOM)).isEqualTo(1); } @Test public void shouldCreateConstantGenOfElement() { final Gen<Integer> gen = Gen.of(1); assertThat(gen.apply(RANDOM)).isEqualTo(1); assertThat(gen.apply(RANDOM)).isEqualTo(1); assertThat(gen.apply(RANDOM)).isEqualTo(1); } @Test public void shouldCreateGenOfSeedAndFunction() { final Gen<Integer> gen = Gen.of(1, i -> i + 1); assertThat(gen.apply(RANDOM)).isEqualTo(1); assertThat(gen.apply(RANDOM)).isEqualTo(2); assertThat(gen.apply(RANDOM)).isEqualTo(3); } // -- random number generator (rng) @Test public void shouldUseCustomRandomNumberGenerator() { final Random rng = new Random() { private static final long serialVersionUID = 1L; @Override public int nextInt(int bound) { return 0; } }; final Gen<Integer> gen = Gen.choose(1, 2); final Number actual = Stream.continually(() -> gen.apply(rng)).take(10).sum(); assertThat(actual).isEqualTo(10L); } // -- choose(int, int) @Test public void shouldChooseIntBetweenMinMax() { assertForAll(() -> Gen.choose(-1, 1).apply(RANDOM), i -> i >= -1 && i <= 1); } @Test public void shouldChooseIntWhenMinEqualsMax() { assertForAll(() -> Gen.choose(0, 0).apply(RANDOM), i -> i == 0); } // -- choose(long, long) @Test public void shouldChooseLongBetweenMinMax() { assertForAll(() -> Gen.choose(-1L, 1L).apply(RANDOM), l -> l >= -1L && l <= 1L); } @Test public void shouldChooseLongWhenMinEqualsMax() { assertForAll(() -> Gen.choose(0L, 0L).apply(RANDOM), l -> l == 0L); } // -- choose(double, double) @Test public void shouldChooseDoubleBetweenMinMax() { assertForAll(() -> Gen.choose(-1.0d, 1.0d).apply(RANDOM), d -> d >= -1.0d && d <= 1.0d); } @Test public void shouldChooseDoubleWhenMinEqualsMax() { assertForAll(() -> Gen.choose(0.0d, 0.0d).apply(RANDOM), d -> d == 0.0d); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenChooseDoubleAndMinIsNegativeInfinite() { Gen.choose(Double.NEGATIVE_INFINITY, 0.0d); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenChooseDoubleAndMinIsPositiveInfinite() { Gen.choose(Double.POSITIVE_INFINITY, 0.0d); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenChooseDoubleAndMinIsNotANumber() { Gen.choose(Double.NaN, 0.0d); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenChooseDoubleAndMaxIsNegativeInfinite() { Gen.choose(0.0d, Double.NEGATIVE_INFINITY); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenChooseDoubleAndMaxIsPositiveInfinite() { Gen.choose(0.0d, Double.POSITIVE_INFINITY); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenChooseDoubleAndMaxIsNotANumber() { Gen.choose(0.0d, Double.NaN); } // -- choose(char, char) @Test public void shouldChooseCharBetweenMinMax() { assertForAll(() -> Gen.choose('A', 'Z').apply(RANDOM), c -> c >= 'A' && c <= 'Z'); } @Test public void shouldChooseCharWhenMinEqualsMax() { assertForAll(() -> Gen.choose('a', 'a').apply(RANDOM), c -> c == 'a'); } // -- choose(array) @Test public void shouldChooseFromASingleArray() throws Exception { Integer[] i = { 1 }; assertForAll(() -> Gen.choose(i).apply(RANDOM), c -> c == 1); } @Test(expected = RuntimeException.class) public void shouldFailOnEmptyArray() throws Exception { Integer[] i = {}; Gen.choose(i).apply(RANDOM); } // -- Choose(enum) enum testEnum { value1 } @Test public void shouldChooseFromEnum() throws Exception { assertForAll(() -> Gen.choose(testEnum.class).apply(RANDOM), e -> Arrays.asList(testEnum.values()).contains(e)); } // -- Choose(iterable) @Test public void shouldChooseFromIterable() throws Exception { List<Integer> i = List.of(1); assertForAll(() -> Gen.choose(i).apply(RANDOM), c -> c == 1); } @Test public void shouldChooseFromIterableWithInstancesOfGenericInterface() { List<Supplier<String>> i = List.of(() -> "test", () -> "test"); Supplier<String> supplier = Gen.choose(i).apply(RANDOM); assertThat(supplier.get()).isEqualTo("test"); } @Test(expected = RuntimeException.class) public void shouldFailOnEmptyIterable() throws Exception { List<Integer> i = List.empty(); Gen.choose(i).apply(RANDOM); } // -- fail @Test(expected = RuntimeException.class) public void shouldFailAlwaysWhenCallingFailingGen() { Gen.fail().apply(RANDOM); } // -- frequency(VarArgs) @Test(expected = NullPointerException.class) public void shouldThrowWhenCallingFrequencyOfVarArgsAndArgIsNull() { Gen.frequency((Tuple2<Integer, Gen<Object>>) null); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenCallingFrequencyOfVarArgsAndArgIsEmpty() { @SuppressWarnings("unchecked") final Tuple2<Integer, Gen<Object>>[] empty = (Tuple2<Integer, Gen<Object>>[]) new Tuple2<?, ?>[0]; Gen.frequency(empty); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenCallingFrequencyOfVarArgsAndAllFrequenciesAreNonPositive() { final Gen<Integer> gen = Gen.frequency(Tuple.of(-1, Gen.of(-1)), Tuple.of(0, Gen.of(0))); gen.apply(RANDOM); } @Test public void shouldIgnoreGeneratorsWithNonPositiveFrequency() { final Gen<Integer> gen = Gen.frequency(Tuple.of(-1, Gen.of(-1)), Tuple.of(0, Gen.of(0)), Tuple.of(1, Gen.of(1))); assertForAll(() -> gen.apply(RANDOM), i -> i == 1); } @Test public void shouldGenerateElementsAccordingToFrequencyGivenVarArgs() { final Gen<Integer> gen = Gen.frequency(Tuple.of(0, Gen.of(-1)), Tuple.of(1, Gen.of(1))); assertForAll(() -> gen.apply(RANDOM), i -> i != -1); } // -- frequency(Iterable) @Test(expected = NullPointerException.class) public void shouldThrowWhenCallingFrequencyOfIterableAndArgIsNull() { Gen.frequency((Iterable<Tuple2<Integer, Gen<Object>>>) null); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenCallingFrequencyOfIterableAndArgIsEmpty() { Gen.frequency(List.empty()); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenCallingFrequencyOfIterableAndAllFrequenciesAreNonPositive() { final Gen<Integer> gen = Gen.frequency(List.of(Tuple.of(-1, Gen.of(-1)), Tuple.of(0, Gen.of(0)))); gen.apply(RANDOM); } @Test public void shouldGenerateElementsAccordingToFrequencyGivenAnIterable() { final Gen<Integer> gen = Gen.frequency(List.of(Tuple.of(0, Gen.of(-1)), Tuple.of(1, Gen.of(1)))); assertForAll(() -> gen.apply(RANDOM), i -> i != -1); } // -- oneOf(VarArgs) @Test(expected = NullPointerException.class) public void shouldThrowWhenCallingOneOfAndVarArgsIsNull() { Gen.oneOf((Gen<Object>[]) null); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenCallingOneOfAndVarArgsIsEmpty() { @SuppressWarnings("unchecked") final Gen<Object>[] empty = (Gen<Object>[]) new Gen<?>[0]; Gen.oneOf(empty); } @Test public void shouldReturnOneOfGivenVarArgs() { final Gen<Integer> gen = Gen.oneOf(Gen.of(1), Gen.of(2)); assertForAll(() -> gen.apply(RANDOM), i -> i == 1 || i == 2); } // -- oneOf(Iterable) @Test(expected = NullPointerException.class) public void shouldThrowWhenCallingOneOfAndIterableIsNull() { Gen.oneOf((Iterable<Gen<Object>>) null); } @Test(expected = IllegalArgumentException.class) public void shouldThrowWhenCallingOneOfAndIterableIsEmpty() { Gen.oneOf(List.empty()); } @Test public void shouldReturnOneOfGivenIterable() { final Gen<Integer> gen = Gen.oneOf(List.of(Gen.of(1), Gen.of(2))); assertForAll(() -> gen.apply(RANDOM), i -> i == 1 || i == 2); } // -- arbitrary @Test public void shouldConvertGenToArbitrary() { assertThat(Gen.of(1).arbitrary()).isInstanceOf(Arbitrary.class); } // -- map @Test(expected = NullPointerException.class) public void shouldThrowWhenCallingMapWithNullArg() { Gen.of(1).map(null); } @Test public void shouldMapGen() { final Gen<Integer> gen = Gen.of(1).map(i -> i * 2); assertForAll(() -> gen.apply(RANDOM), i -> i % 2 == 0); } // -- flatMap @Test(expected = NullPointerException.class) public void shouldThrowWhenCallingFlatMapWithNullArg() { Gen.of(1).flatMap(null); } @Test public void shouldFlatMapGen() { final Gen<Integer> gen = Gen.of(1).flatMap(i -> Gen.of(i * 2)); assertForAll(() -> gen.apply(RANDOM), i -> i % 2 == 0); } // -- filter @Test(expected = NullPointerException.class) public void shouldThrowWhenCallingFilterWithNullArg() { Gen.of(1).filter(null); } @Test public void shouldFilterGenerator() { final Gen<Integer> gen = Gen.choose(1, 2).filter(i -> i % 2 == 0); assertForAll(() -> gen.apply(RANDOM), i -> i == 2); } @Test(expected = IllegalStateException.class) public void shouldDetectEmptyFilter() { Gen.of(1).filter(ignored -> false).apply(RANDOM); } // -- peek @Test public void shouldPeekArbitrary() { final int[] actual = new int[] { -1 }; final int expected = Gen.of(1).peek(i -> actual[0] = i).apply(new Random()); assertThat(actual[0]).isEqualTo(expected); } // -- transform @Test public void shouldTransformGen() { final String s = Gen.of(1).transform(gen -> gen.apply(RANDOM).toString()); assertThat(s).isEqualTo("1"); } // helpers <T> void assertForAll(Supplier<T> supplier, Predicate<T> property) { for (int i = 0; i < TRIES; i++) { final T element = supplier.get(); if (!property.test(element)) { throw new AssertionError("predicate did not hold for " + element); } } } }