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

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

There is a newer version: 1.9.1
Show newest version
package net.jqwik.engine.properties.shrinking;

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

import net.jqwik.api.*;

public class ElementsShrinkingSequence implements ShrinkingSequence> {
	private final Falsifier> listFalsifier;
	private final List> currentResults;
	private final Function>, ShrinkingDistance> distanceFunction;

	private int currentShrinkingPosition = 0;
	private ShrinkingSequence currentShrinkingSequence = null;
	private Throwable currentThrowable;

	public ElementsShrinkingSequence(
		List> currentElements,
		Falsifier> listFalsifier,
		Function>, ShrinkingDistance> distanceFunction
	) {
		this.currentResults =
			currentElements
				.stream()
				.map(FalsificationResult::falsified)
				.collect(Collectors.toList());
		this.listFalsifier = listFalsifier;
		this.distanceFunction = distanceFunction;
	}

	@Override
	public void init(FalsificationResult> initialCurrent) {
		this.currentThrowable = initialCurrent.throwable().orElse(null);

		for (int i = 0; i < currentResults.size(); i++) {
			FalsificationResult newResult = FalsificationResult.falsified(currentResults.get(i).shrinkable(), currentThrowable);
			currentResults.set(i, newResult);
		}
	}

	@Override
	public boolean next(Runnable count, Consumer>> falsifiedReporter) {
		if (isShrinkingDone())
			return false;
		return shrinkCurrentPosition(count, falsifiedReporter);
	}

	private boolean isShrinkingDone() {
		return currentShrinkingPosition >= currentResults.size();
	}

	private boolean shrinkCurrentPosition(Runnable count, Consumer>> falsifiedReporter) {
		if (currentShrinkingSequence == null) {
			currentShrinkingSequence = createShrinkingSequence(currentShrinkingPosition);
		}
		if (!currentShrinkingSequence.next(count, currentFalsifiedReporter(falsifiedReporter))) {
			return advanceToNextShrinkingPosition(count, falsifiedReporter);
		}
		replaceCurrentPosition(currentShrinkingSequence.current());
		return true;
	}

	private boolean advanceToNextShrinkingPosition(
		Runnable count, Consumer>> falsifiedReporter
	) {
		currentShrinkingSequence = null;
		currentShrinkingPosition++;
		return next(count, falsifiedReporter);
	}

	private Consumer> currentFalsifiedReporter(
		Consumer>> listReporter
	) {
		if (isShrinkingDone()) return ignore -> {};
		return resultOnCurrentShrinkingPosition -> { //
			listReporter.accept(resultOnCurrentShrinkingPosition.map(shrinkable -> shrinkable.map(valueOnCurrentShrinkingPosition -> {
				List values = toValueList(currentResults);
				values.set(currentShrinkingPosition, resultOnCurrentShrinkingPosition.value());
				return values;
			})));
		};
	}

	private void replaceCurrentPosition(FalsificationResult falsificationResult) {
		currentResults.set(currentShrinkingPosition, falsificationResult);
		currentThrowable = falsificationResult.throwable().orElse(null);
	}

	private ShrinkingSequence createShrinkingSequence(int position) {
		FalsificationResult positionResult = currentResults.get(position);
		Falsifier positionFalsifier = falsifierForPosition(position, currentResults);
		return positionResult.shrinkable().shrink(positionFalsifier);
	}

	private Falsifier falsifierForPosition(int position, List> falsificationResults) {
		return elementValue -> {
			List effectiveParams = toValueList(falsificationResults);
			effectiveParams.set(position, elementValue);
			return listFalsifier.test(effectiveParams);
		};
	}

	@Override
	public FalsificationResult> current() {
		return FalsificationResult.falsified(createCurrent(currentResults), currentThrowable);
	}

	private Shrinkable> createCurrent(List> falsificationResults) {
		return new Shrinkable>() {
			final List value = toValueList(falsificationResults);

			@Override
			public List value() {
				return value;
			}

			@Override
			public ShrinkingSequence> shrink(Falsifier> falsifier) {
				return ElementsShrinkingSequence.this;
			}

			@Override
			public ShrinkingDistance distance() {
				return distanceFunction.apply(toShrinkableList(falsificationResults));
			}
		};
	}

	private List toValueList(List> results) {
		return results
				   .stream()
				   .map(FalsificationResult::value)
				   .collect(Collectors.toList());
	}

	private List> toShrinkableList(List> results) {
		return results
				   .stream()
				   .map(FalsificationResult::shrinkable)
				   .collect(Collectors.toList());
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy