@Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class) public void testOps(String name, TestData.OfRef<Integer> data) { // @@@ More things to test here: // - Every value in data is present in right bucket // - Total number of values equals size of data for (MapperData<Integer, ?> md : getMapperData(data)) { Collector<Integer, ?, Map<Object, List<Integer>>> tab = Collectors.groupingBy(md.m); Map<Object, List<Integer>> result = withData(data) .terminal(s -> s, s -> s.collect(tab)) .resultAsserter((act, exp, ord, par) -> { if (par & !ord) { GroupByOpTest.assertMultiMapEquals(act, exp); } else { GroupByOpTest.assertObjectEquals(act, exp); } }) .exercise(); assertEquals(result.keySet().size(), md.expectedSize); } }
private<T, M extends Map> void exerciseMapCollection(TestData<T, Stream<T>> data, Collector<T, ?, ? extends M> collector, CollectorAssertion<T, M> assertion) throws ReflectiveOperationException { boolean ordered = !collector.characteristics().contains(Collector.Characteristics.UNORDERED); M m = withData(data) .terminal(s -> s.collect(collector)) .resultAsserter(mapTabulationAsserter(ordered)) .exercise(); assertion.assertValue(m, () -> data.stream(), ordered); m = withData(data) .terminal(s -> s.unordered().collect(collector)) .resultAsserter(mapTabulationAsserter(ordered)) .exercise(); assertion.assertValue(m, () -> data.stream(), false); }
private<T, M extends Map> void exerciseMapTabulation(TestData<T, Stream<T>> data, Collector<T, ?, ? extends M> collector, TabulationAssertion<T, M> assertion) throws ReflectiveOperationException { boolean ordered = !collector.characteristics().contains(Collector.Characteristics.UNORDERED); M m = withData(data) .terminal(s -> s.collect(collector)) .resultAsserter(mapTabulationAsserter(ordered)) .exercise(); assertion.assertValue(m, () -> data.stream(), ordered); m = withData(data) .terminal(s -> s.unordered().collect(collector)) .resultAsserter(mapTabulationAsserter(ordered)) .exercise(); assertion.assertValue(m, () -> data.stream(), false); }
@Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class) public void testOps(String name, TestData.OfLong data) { long expectedCount = data.size(); withData(data). terminal(LongStream::count). expectedResult(expectedCount). exercise(); withData(data). terminal(s -> s.filter(e -> true), LongStream::count). expectedResult(expectedCount). exercise(); expectedCount = data.into(new HashSet<>()).size(); withData(data). terminal(LongStream::distinct, LongStream::count). expectedResult(expectedCount). exercise(); withData(data). terminal(s -> s.unordered().distinct(), LongStream::count). expectedResult(expectedCount). exercise(); }
@Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class) public void testOps(String name, TestData.OfInt data) { long expectedCount = data.size(); withData(data). terminal(IntStream::count). expectedResult(expectedCount). exercise(); withData(data). terminal(s -> s.filter(e -> true), IntStream::count). expectedResult(expectedCount). exercise(); expectedCount = data.into(new HashSet<>()).size(); withData(data). terminal(IntStream::distinct, IntStream::count). expectedResult(expectedCount). exercise(); withData(data). terminal(s -> s.unordered().distinct(), IntStream::count). expectedResult(expectedCount). exercise(); }
List<MapperData<Integer, ?>> getMapperData(TestData.OfRef<Integer> data) { int uniqueSize = data.into(new HashSet<>()).size(); return Arrays.asList( new MapperData<>(mId, uniqueSize), new MapperData<>(mZero, Math.min(1, data.size())), new MapperData<>(mDoubler, uniqueSize), new MapperData<>(LambdaTestHelpers.compose(mId, mDoubler), uniqueSize), new MapperData<>(LambdaTestHelpers.compose(mDoubler, mDoubler), uniqueSize), new MapperData<>(LambdaTestHelpers.forPredicate(pFalse, true, false), Math.min(1, uniqueSize)), new MapperData<>(LambdaTestHelpers.forPredicate(pTrue, true, false), Math.min(1, uniqueSize)), new MapperData<>(LambdaTestHelpers.forPredicate(pEven, true, false), Math.min(2, uniqueSize)), new MapperData<>(LambdaTestHelpers.forPredicate(pOdd, true, false), Math.min(2, uniqueSize)) ); }
private void testWhileMulti(TestData.OfRef<Integer> data, ResultAsserter<Iterable<Integer>> ra, Function<Stream<Integer>, Stream<Integer>> mRef, Function<IntStream, IntStream> mInt, Function<LongStream, LongStream> mLong, Function<DoubleStream, DoubleStream> mDouble) { Map<String, Function<Stream<Integer>, Stream<Integer>>> ms = new HashMap<>(); ms.put("Ref", mRef); ms.put("Int", s -> mInt.apply(s.mapToInt(e -> e)).mapToObj(e -> e)); ms.put("Long", s -> mLong.apply(s.mapToLong(e -> e)).mapToObj(e -> (int) e)); ms.put("Double", s -> mDouble.apply(s.mapToDouble(e -> e)).mapToObj(e -> (int) e)); ms.put("Ref using defaults", s -> mRef.apply(DefaultMethodStreams.delegateTo(s))); ms.put("Int using defaults", s -> mInt.apply(DefaultMethodStreams.delegateTo(s.mapToInt(e -> e))).mapToObj(e -> e)); ms.put("Long using defaults", s -> mLong.apply(DefaultMethodStreams.delegateTo(s.mapToLong(e -> e))).mapToObj(e -> (int) e)); ms.put("Double using defaults", s -> mDouble.apply(DefaultMethodStreams.delegateTo(s.mapToDouble(e -> e))).mapToObj(e -> (int) e)); testWhileMulti(data, ra, ms); }
@Test public void testStable() { // Create N instances of Integer all with the same value List<Integer> input = IntStream.rangeClosed(0, 1000) .mapToObj(i -> new Integer(1000)) // explicit construction .collect(Collectors.toList()); Integer expectedElement = input.get(0); TestData<Integer, Stream<Integer>> data = TestData.Factory.ofCollection( "1000 instances of Integer with the same value", input); withData(data) .stream(Stream::distinct) .resultAsserter((actual, expected, isOrdered, isParallel) -> { List<Integer> l = new ArrayList<>(); actual.forEach(l::add); // Assert stability // The single result element should be equal in identity to // the first input element assertEquals(l.size(), 1); assertEquals(System.identityHashCode(l.get(0)), System.identityHashCode(expectedElement)); }) .exercise(); }
@Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class) public void testSimpleGroupingBy(String name, TestData.OfRef<Integer> data) throws ReflectiveOperationException { Function<Integer, Integer> classifier = i -> i % 3; // Single-level groupBy exerciseMapCollection(data, groupingBy(classifier), new GroupingByAssertion<>(classifier, HashMap.class, new ToListAssertion<>())); exerciseMapCollection(data, groupingByConcurrent(classifier), new GroupingByAssertion<>(classifier, ConcurrentHashMap.class, new ToListAssertion<>())); // With explicit constructors exerciseMapCollection(data, groupingBy(classifier, TreeMap::new, toCollection(HashSet::new)), new GroupingByAssertion<>(classifier, TreeMap.class, new ToCollectionAssertion<Integer>(HashSet.class, false))); exerciseMapCollection(data, groupingByConcurrent(classifier, ConcurrentSkipListMap::new, toCollection(HashSet::new)), new GroupingByAssertion<>(classifier, ConcurrentSkipListMap.class, new ToCollectionAssertion<Integer>(HashSet.class, false))); }
@Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class, groups = { "serialization-hostile" }) public void testSkipOps(String name, TestData.OfRef<Integer> data) { List<Integer> skips = sizes(data.size()); for (int s : skips) { setContext("skip", s); testSliceMulti(data, sliceSize(data.size(), s), st -> st.skip(s), st -> st.skip(s), st -> st.skip(s), st -> st.skip(s)); testSliceMulti(data, sliceSize(sliceSize(data.size(), s), s/2), st -> st.skip(s).skip(s / 2), st -> st.skip(s).skip(s / 2), st -> st.skip(s).skip(s / 2), st -> st.skip(s).skip(s / 2)); } }
@Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class) public void testStream(String name, TestData.OfRef<Integer> data) { for (Predicate<Integer> p : INTEGER_PREDICATES) { setContext("p", p); for (Kind kind : Kind.values()) { setContext("kind", kind); exerciseTerminalOps(data, this.<Integer>kinds().get(kind).apply(p)); exerciseTerminalOps(data, s -> s.filter(pFalse), this.<Integer>kinds().get(kind).apply(p)); exerciseTerminalOps(data, s -> s.filter(pEven), this.<Integer>kinds().get(kind).apply(p)); } } }
@Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) public void testDoubleStream(String name, TestData.OfDouble data) { for (DoublePredicate p : DOUBLE_PREDICATES) { setContext("p", p); for (Kind kind : Kind.values()) { setContext("kind", kind); exerciseTerminalOps(data, doubleKinds.get(kind).apply(p)); exerciseTerminalOps(data, s -> s.filter(dpFalse), doubleKinds.get(kind).apply(p)); exerciseTerminalOps(data, s -> s.filter(dpEven), doubleKinds.get(kind).apply(p)); } } }
@Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class) public void testDoubleOps(String name, TestData.OfDouble data) { Collection<Double> result = exerciseOps(data, s -> s.flatMap(i -> Collections.singleton(i).stream().mapToDouble(j -> j))); assertEquals(data.size(), result.size()); assertContents(data, result); result = exerciseOps(data, s -> DoubleStream.empty()); assertEquals(0, result.size()); }
@Test(dataProvider = "Patterns") public void testMatchResults(String description, String input, Pattern pattern) { // Derive expected result from Matcher.find Matcher m = pattern.matcher(input); List<MatchResultHolder> expected = new ArrayList<>(); while (m.find()) { expected.add(new MatchResultHolder(m)); } Supplier<Stream<MatchResult>> ss = () -> pattern.matcher(input).results(); withData(TestData.Factory.ofSupplier(description, ss)) .stream(s -> s.map(MatchResultHolder::new)) .expectedResult(expected) .exercise(); }
@Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class) public void testDistinctDistinct(String name, TestData.OfRef<Integer> data) { Collection<Integer> result = exerciseOpsInt( data, s -> s.distinct().distinct(), s -> s.distinct().distinct(), s -> s.distinct().distinct(), s -> s.distinct().distinct()); assertUnique(result); }
@Test(dataProvider = "Stream.limit") public void testUnorderedGenerator(String description, UnaryOperator<Stream<Long>> fs) { // Source is spliterator of infinite size TestData.OfRef<Long> generator = TestData.Factory.ofSupplier( "[1L, 1L, ...]", () -> Stream.generate(() -> 1L)); withData(generator). stream(s -> fs.apply(s.filter(i -> true).unordered())). exercise(); }
@Test(dataProvider = "IntStream.limit") public void testIntUnorderedGenerator(String description, UnaryOperator<IntStream> fs) { // Source is spliterator of infinite size TestData.OfInt generator = TestData.Factory.ofIntSupplier( "[1, 1, ...]", () -> IntStream.generate(() -> 1)); withData(generator). stream(s -> fs.apply(s.filter(i -> true).unordered())). exercise(); }
@Test(dataProvider = "LongStream.limit") public void testLongUnorderedGenerator(String description, UnaryOperator<LongStream> fs) { // Source is spliterator of infinite size TestData.OfLong generator = TestData.Factory.ofLongSupplier( "[1L, 1L, ...]", () -> LongStream.generate(() -> 1)); withData(generator). stream(s -> fs.apply(s.filter(i -> true).unordered())). exercise(); }
@Test(dataProvider = "DoubleStream.limit") public void testDoubleUnorderedGenerator(String description, UnaryOperator<DoubleStream> fs) { // Source is spliterator of infinite size TestData.OfDouble generator = TestData.Factory.ofDoubleSupplier( "[1.0, 1.0, ...]", () -> DoubleStream.generate(() -> 1.0)); withData(generator). stream(s -> fs.apply(s.filter(i -> true).unordered())). exercise(); }
@Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class) public void testOps(String name, TestData.OfRef<Integer> data) { assertEquals(0, (int) exerciseTerminalOps(data, s -> s.filter(pFalse), s -> s.reduce(0, rPlus, rPlus))); Optional<Integer> seedless = exerciseTerminalOps(data, s -> s.reduce(rPlus)); Integer folded = exerciseTerminalOps(data, s -> s.reduce(0, rPlus, rPlus)); assertEquals(folded, seedless.orElse(0)); seedless = exerciseTerminalOps(data, s -> s.reduce(rMin)); folded = exerciseTerminalOps(data, s -> s.reduce(Integer.MAX_VALUE, rMin, rMin)); assertEquals(folded, seedless.orElse(Integer.MAX_VALUE)); seedless = exerciseTerminalOps(data, s -> s.reduce(rMax)); folded = exerciseTerminalOps(data, s -> s.reduce(Integer.MIN_VALUE, rMax, rMax)); assertEquals(folded, seedless.orElse(Integer.MIN_VALUE)); seedless = exerciseTerminalOps(data, s -> s.map(mDoubler), s -> s.reduce(rPlus)); folded = exerciseTerminalOps(data, s -> s.map(mDoubler), s -> s.reduce(0, rPlus, rPlus)); assertEquals(folded, seedless.orElse(0)); seedless = exerciseTerminalOps(data, s -> s.map(mDoubler), s -> s.reduce(rMin)); folded = exerciseTerminalOps(data, s -> s.map(mDoubler), s -> s.reduce(Integer.MAX_VALUE, rMin, rMin)); assertEquals(folded, seedless.orElse(Integer.MAX_VALUE)); seedless = exerciseTerminalOps(data, s -> s.map(mDoubler), s -> s.reduce(rMax)); folded = exerciseTerminalOps(data, s -> s.map(mDoubler), s -> s.reduce(Integer.MIN_VALUE, rMax, rMax)); assertEquals(folded, seedless.orElse(Integer.MIN_VALUE)); }
@Test(dataProvider = "doubles") public void testDoubles(TestData.OfDouble data, ResultAsserter<Iterable<Double>> ra) { withData(data). stream(s -> s). without(DoubleStreamTestScenario.CLEAR_SIZED_SCENARIOS). resultAsserter(ra). exercise(); }
@Test(dataProvider = "LongStream.limit") public void testLongUnorderedIteration(String description, UnaryOperator<LongStream> fs) { // Source is a right-balanced tree of infinite size TestData.OfLong iterator = TestData.Factory.ofLongSupplier( "[1L, 2L, 3L, ...]", () -> LongStream.iterate(1, i -> i + 1)); // Ref withData(iterator). stream(s -> fs.apply(s.unordered())). resultAsserter(unorderedAsserter()). exercise(); }
@Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class) public void testOps(String name, TestData.OfRef<Integer> data) { exerciseOpsInt(data, s -> Stream.concat(s, data.stream()), s -> IntStream.concat(s, data.stream().mapToInt(Integer::intValue)), s -> LongStream.concat(s, data.stream().mapToLong(Integer::longValue)), s -> DoubleStream.concat(s, data.stream().mapToDouble(Integer::doubleValue))); }
private final void testWhileMulti(TestData.OfRef<Integer> data, ResultAsserter<Iterable<Integer>> ra, Map<String, Function<Stream<Integer>, Stream<Integer>>> ms) { for (Map.Entry<String, Function<Stream<Integer>, Stream<Integer>>> e : ms.entrySet()) { setContext("shape", e.getKey()); withData(data) .stream(e.getValue()) .resultAsserter(ra) .exercise(); } }
private<T> String join(TestData.OfRef<T> data, String delim) { StringBuilder sb = new StringBuilder(); boolean first = true; for (T i : data) { if (!first) sb.append(delim); sb.append(i.toString()); first = false; } return sb.toString(); }
@Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class) public void testSimplePartition(String name, TestData.OfRef<Integer> data) throws ReflectiveOperationException { Predicate<Integer> classifier = i -> i % 3 == 0; // Single-level partition to downstream List exerciseMapTabulation(data, partitioningBy(classifier), new PartitionAssertion<>(classifier, new ListAssertion<>())); exerciseMapTabulation(data, partitioningBy(classifier, toList()), new PartitionAssertion<>(classifier, new ListAssertion<>())); }
@Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class) public void testComposeFinisher(String name, TestData.OfRef<Integer> data) throws ReflectiveOperationException { List<Integer> asList = exerciseTerminalOps(data, s -> s.collect(toList())); List<Integer> asImmutableList = exerciseTerminalOps(data, s -> s.collect(collectingAndThen(toList(), Collections::unmodifiableList))); assertEquals(asList, asImmutableList); try { asImmutableList.add(0); fail("Expecting immutable result"); } catch (UnsupportedOperationException ignored) { } }
@Test public void testSingleton() { TestData.OfRef<Integer> data = TestData.Factory.ofSupplier("[0, 1)", () -> Stream.of(1)); withData(data). stream(s -> s). expectedResult(Collections.singletonList(1)). exercise(); withData(data). stream(s -> s.map(LambdaTestHelpers.identity())). expectedResult(Collections.singletonList(1)). exercise(); }
private void testStreamBuilder(int size, Function<Integer, Stream<Integer>> supplier) { TestData.OfRef<Integer> data = TestData.Factory.ofSupplier(String.format("[0, %d)", size), () -> supplier.apply(size)); withData(data). stream(s -> s). expectedResult(IntStream.range(0, size).boxed().collect(toList())). exercise(); withData(data). stream(s -> s.map(LambdaTestHelpers.identity())). expectedResult(IntStream.range(0, size).boxed().collect(toList())). exercise(); }
@Test public void testIntSingleton() { TestData.OfInt data = TestData.Factory.ofIntSupplier("[0, 1)", () -> IntStream.of(1)); withData(data). stream(s -> s). expectedResult(Collections.singletonList(1)). exercise(); withData(data). stream(s -> s.map(i -> i)). expectedResult(Collections.singletonList(1)). exercise(); }
private void testIntStreamBuilder(int size, Function<Integer, IntStream> supplier) { TestData.OfInt data = TestData.Factory.ofIntSupplier(String.format("[0, %d)", size), () -> supplier.apply(size)); withData(data). stream(s -> s). expectedResult(IntStream.range(0, size).toArray()). exercise(); withData(data). stream(s -> s.map(i -> i)). expectedResult(IntStream.range(0, size).toArray()). exercise(); }
@Test public void testLongSingleton() { TestData.OfLong data = TestData.Factory.ofLongSupplier("[0, 1)", () -> LongStream.of(1)); withData(data). stream(s -> s). expectedResult(Collections.singletonList(1L)). exercise(); withData(data). stream(s -> s.map(i -> i)). expectedResult(Collections.singletonList(1L)). exercise(); }
private void testDoubleStreamBuilder(int size, Function<Integer, DoubleStream> supplier) { TestData.OfDouble data = TestData.Factory.ofDoubleSupplier(String.format("[0, %d)", size), () -> supplier.apply(size)); withData(data). stream(s -> s). expectedResult(IntStream.range(0, size).asDoubleStream().toArray()). exercise(); withData(data). stream(s -> s.map(i -> i)). expectedResult(IntStream.range(0, size).asDoubleStream().toArray()). exercise(); }
@Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class) public void testGroupingByWithMapping(String name, TestData.OfRef<Integer> data) throws ReflectiveOperationException { Function<Integer, Integer> classifier = i -> i % 3; Function<Integer, Integer> mapper = i -> i * 2; exerciseMapCollection(data, groupingBy(classifier, mapping(mapper, toList())), new GroupingByAssertion<>(classifier, HashMap.class, new MappingAssertion<>(mapper, new ToListAssertion<>()))); }
@Test public void testSingleton() { TestData.OfRef<Integer> data = TestData.Factory.ofSupplier("{1}", () -> Stream.of(1)); withData(data). stream(s -> s). expectedResult(Collections.singletonList(1)). exercise(); withData(data). stream(s -> s.map(LambdaTestHelpers.identity())). expectedResult(Collections.singletonList(1)). exercise(); }
@Test public void testIntSingleton() { TestData.OfInt data = TestData.Factory.ofIntSupplier("{1}", () -> IntStream.of(1)); withData(data). stream(s -> s). expectedResult(Collections.singletonList(1)). exercise(); withData(data). stream(s -> s.map(i -> i)). expectedResult(Collections.singletonList(1)). exercise(); }
@Test public void testDoubleSingleton() { TestData.OfDouble data = TestData.Factory.ofDoubleSupplier("{1}", () -> DoubleStream.of(1)); withData(data). stream(s -> s). expectedResult(Collections.singletonList(1.0)). exercise(); withData(data). stream(s -> s.map(i -> i)). expectedResult(Collections.singletonList(1.0)). exercise(); }
@SafeVarargs private final void testSliceMulti(TestData.OfRef<Integer> data, int expectedSize, Function<Stream<Integer>, Stream<Integer>>... ms) { for (int i = 0; i < ms.length; i++) { setContext("mIndex", i); Function<Stream<Integer>, Stream<Integer>> m = ms[i]; Collection<Integer> sr = withData(data) .stream(m) .resultAsserter(sliceResultAsserter(data, expectedSize)) .exercise(); assertEquals(sr.size(), expectedSize); } }