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

net.jqwik.engine.facades.SampleStreamFacade Maven / Gradle / Ivy

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

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

import org.jspecify.annotations.*;
import org.junit.platform.engine.*;
import org.junit.platform.engine.support.descriptor.*;

import net.jqwik.api.*;
import net.jqwik.engine.*;
import net.jqwik.engine.execution.lifecycle.*;
import net.jqwik.engine.support.*;

import static org.junit.platform.engine.TestDescriptor.Type.*;

class SampleStreamFacade {

	private static final TestDescriptor SAMPLE_STREAM_DESCRIPTOR = new AbstractTestDescriptor(
		UniqueId.root("jqwik", "samples"),
		"Streaming samples outside jqwik thread"
	) {
		@Override
		public Type getType() {
			return TEST;
		}
	};

	private static final Map, RandomGenerator> generators = new LruCache<>(500);

	@SuppressWarnings("unchecked")
	private static  RandomGenerator getGeneratorForSampling(Arbitrary arbitrary) {
		return runInDescriptor(() -> getGenerator((Arbitrary) arbitrary));
	}

	@SuppressWarnings("unchecked")
	private static  RandomGenerator getGenerator(Arbitrary arbitrary) {
		RandomGenerator generator = generators.get(arbitrary);
		if (generator == null) {
			generator = arbitrary.generator(JqwikProperties.DEFAULT_TRIES, true);
			generators.put(arbitrary, generator);
		}
		return (RandomGenerator) generator;

		// Using computeIfAbsent will throw CurrentModificationException when getting
		// the generator from the arbitrary will itself add another generator
		// to the map of generators:
		// return (RandomGenerator) generators.computeIfAbsent(
		// 		arbitrary,
		// 		a -> a.generator(JqwikProperties.DEFAULT_TRIES, true)
		// );
	}

	private static  Supplier wrapInDescriptor(Supplier code) {
		return () -> runInDescriptor(code);
	}

	private static  T runInDescriptor(Supplier code) {
		if (CurrentTestDescriptor.isEmpty()) {
			return CurrentTestDescriptor.runWithDescriptor(SAMPLE_STREAM_DESCRIPTOR, code);
		} else {
			return code.get();
		}
	}

	 Stream sampleStream(Arbitrary arbitrary) {
		RandomGenerator generator = getGeneratorForSampling(arbitrary);
		return Stream.generate(wrapInDescriptor(() -> generator.next(SourceOfRandomness.current())))
					 .map(shrinkable -> runInDescriptor(shrinkable::value));
	}
}