All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.jqwik.engine.properties.shrinking.ShrinkableList Maven / Gradle / Ivy

The newest version!
package net.jqwik.engine.properties.shrinking;

import java.util.*;
import java.util.stream.*;

import net.jqwik.api.*;
import net.jqwik.engine.properties.*;
import net.jqwik.engine.support.*;

import org.jspecify.annotations.*;

import static net.jqwik.engine.properties.UniquenessChecker.*;

public class ShrinkableList extends ShrinkableContainer, E> {

	// Only used in tests
	ShrinkableList(List> elements, int minSize, int maxSize) {
		this(elements, minSize, maxSize, Collections.emptySet(), null);
	}

	public ShrinkableList(
		List> elements,
		int minSize, int maxSize,
		Collection> uniquenessExtractors,
		Arbitrary elementArbitrary
	) {
		super(elements, minSize, maxSize, uniquenessExtractors, elementArbitrary);
	}

	@Override
	List createValue(List> shrinkables) {
		// Using loop instead of stream to make stack traces more readable
		List values = new ArrayList<>(shrinkables.size());
		for (Shrinkable shrinkable : shrinkables) {
			values.add(shrinkable.value());
		}
		return values;
	}

	@Override
	Shrinkable> createShrinkable(List> shrunkElements) {
		return new ShrinkableList<>(shrunkElements, minSize, maxSize, uniquenessExtractors, elementArbitrary);
	}

	@Override
	public Stream>> shrink() {
		return JqwikStreamSupport.concat(
				super.shrink(),
				sortElements(),
				moveIndividualValuesTowardsEnd()
		);
	}

	// TODO: Simplify and clean up
	@SuppressWarnings("OverlyLongMethod")
	private Stream>> moveIndividualValuesTowardsEnd() {
		ShrinkingDistance distance = distance();
		return Combinatorics
					   .distinctPairs(elements.size())
					   .map(pair -> {
						   int firstIndex = Math.min(pair.get1(), pair.get2());
						   int secondIndex = Math.max(pair.get1(), pair.get2());
						   Shrinkable first = elements.get(firstIndex);
						   Shrinkable second = elements.get(secondIndex);
						   return Tuple.of(firstIndex, first, secondIndex, second);
					   })
					   .filter(quadruple -> quadruple.get2().compareTo(quadruple.get4()) <= 0)
					   .flatMap(quadruple -> {
						   int firstIndex = quadruple.get1();
						   Shrinkable first = quadruple.get2();
						   int secondIndex = quadruple.get3();
						   Shrinkable second = quadruple.get4();
						   return first.shrink()
									   .map(after -> {
										   Optional> grow = second.grow(first, after);
										   return Tuple.of(after, grow);
									   })
									   .filter(tuple -> tuple.get2().isPresent())
									   .map(tuple -> {
										   List> pairMove = new ArrayList<>(elements);
										   pairMove.set(firstIndex, tuple.get1());
										   pairMove.set(secondIndex, tuple.get2().get());
										   return pairMove;
									   })
									   .filter(shrinkables -> checkUniquenessOfShrinkables(uniquenessExtractors, shrinkables))
									   .map(this::createShrinkable);

					   })
					   // In rare cases of nested lists shrinkGrow can increase the distance
					   .filter(s -> s.distance().compareTo(distance) <= 0);
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy