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

net.jqwik.engine.execution.GenerationInfo Maven / Gradle / Ivy

The newest version!
package net.jqwik.engine.execution;

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

import net.jqwik.api.*;
import net.jqwik.api.lifecycle.*;
import net.jqwik.engine.properties.shrinking.*;

import org.jspecify.annotations.*;

public class GenerationInfo implements Serializable {

	public final static GenerationInfo NULL = new GenerationInfo(null);

	private final @Nullable String randomSeed;
	private final int generationIndex;

	// Store ordinals instead of enum objects so that serialization
	// in jqwik.database uses less disk space
	private final List> byteSequences;

	public GenerationInfo(@Nullable String randomSeed) {
		this(randomSeed, 0);
	}

	public GenerationInfo(@Nullable String randomSeed, int generationIndex) {
		this(randomSeed, generationIndex, Collections.emptyList());
	}

	private GenerationInfo(@Nullable String randomSeed, int generationIndex, List> byteSequences) {
		this.randomSeed = randomSeed != null ? (randomSeed.isEmpty() ? null : randomSeed) : null;
		this.generationIndex = generationIndex;
		this.byteSequences = byteSequences;
	}

	private List toByteSequence(List shrinkingSequence) {
		return shrinkingSequence.stream().map(status -> (byte) status.ordinal()).collect(Collectors.toList());
	}

	public GenerationInfo appendShrinkingSequence(List toAppend) {
		if (toAppend.isEmpty()) {
			return this;
		}
		List> newByteSequences = new ArrayList<>(byteSequences);
		newByteSequences.add(toByteSequence(toAppend));
		return new GenerationInfo(randomSeed, generationIndex, newByteSequences);
	}

	public Optional randomSeed() {
		return Optional.ofNullable(randomSeed);
	}

	public int generationIndex() {
		return generationIndex;
	}

	public Optional>> generateOn(ParametersGenerator generator, TryLifecycleContext context) {
		List> sample = useGenerationIndex(generator, context);
		return useShrinkingSequences(sample);
	}

	private Optional>> useShrinkingSequences(@Nullable List> sample) {
		Optional>> shrunkSample = Optional.ofNullable(sample);
		for (List shrinkingSequence : shrinkingSequences()) {
			if (!shrunkSample.isPresent()) {
				break;
			}
			shrunkSample = shrink(shrunkSample.get(), shrinkingSequence);
		}
		return shrunkSample;
	}

	private Optional>> shrink(
		List> sample,
		List shrinkingSequence
	) {
		ShrunkSampleRecreator recreator = new ShrunkSampleRecreator(sample);
		return recreator.recreateFrom(shrinkingSequence);
	}

	private @Nullable List> useGenerationIndex(ParametersGenerator generator, TryLifecycleContext context) {
		List> sample = null;
		for (int i = 0; i < generationIndex; i++) {
			if (generator.hasNext()) {
				sample = generator.next(context);
			} else {
				return null;
			}
		}
		return sample;
	}

	public List> shrinkingSequences() {
		return byteSequences.stream()
							.map(this::toShrinkingSequence)
							.collect(Collectors.toList());
	}

	private List toShrinkingSequence(List sequence) {
		return sequence.stream().map(ordinal -> TryExecutionResult.Status.values()[ordinal]).collect(Collectors.toList());
	}

	@Override
	public boolean equals(Object o) {
		if (this == o) return true;
		if (o == null || getClass() != o.getClass()) return false;

		GenerationInfo that = (GenerationInfo) o;
		if (generationIndex != that.generationIndex) return false;
		if (!Objects.equals(randomSeed, that.randomSeed)) return false;
		return byteSequences.equals(that.byteSequences);
	}

	@Override
	public int hashCode() {
		int result = randomSeed != null ? randomSeed.hashCode() : 0;
		result = 31 * result + generationIndex;
		return result;
	}

	@Override
	public String toString() {
		List sizes = byteSequences.stream().map(bytes -> "size=" + bytes.size()).collect(Collectors.toList());
		Tuple.Tuple3> tuple = Tuple.of(randomSeed, generationIndex, sizes);
		return String.format("GenerationInfo%s", tuple);
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy