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

net.jqwik.api.PropertyDefaults Maven / Gradle / Ivy

The newest version!
package net.jqwik.api;

import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.*;

import org.apiguardian.api.*;

import net.jqwik.api.lifecycle.*;

import static org.apiguardian.api.API.Status.*;

import static net.jqwik.api.Property.*;

/**
 * Annotate a container class with {@code @PropertyDefaults}
 * if you want to set defaults of {@code Property} attributes of all contained property methods.
 */
@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@AddLifecycleHook(PropertyDefaults.PropertyDefaultsHook.class)
@Inherited
@API(status = MAINTAINED, since = "1.4.0")
public @interface PropertyDefaults {

	int tries() default Property.TRIES_NOT_SET;

	AfterFailureMode afterFailure() default AfterFailureMode.NOT_SET;

	ShrinkingMode shrinking() default ShrinkingMode.NOT_SET;

	GenerationMode generation() default GenerationMode.NOT_SET;

	EdgeCasesMode edgeCases() default EdgeCasesMode.NOT_SET;

	@API(status = MAINTAINED, since = "1.4.0")
	FixedSeedMode whenFixedSeed() default FixedSeedMode.NOT_SET;

	@API(status = MAINTAINED, since = "1.6.2")
	int maxDiscardRatio() default MAX_DISCARD_RATIO_NOT_SET;

	class PropertyDefaultsHook implements AroundPropertyHook {

		@Override
		public PropertyExecutionResult aroundProperty(PropertyLifecycleContext context, PropertyExecutor property) {
			List propertyDefaults = context.findAnnotationsInContainer(PropertyDefaults.class);

			findTries(propertyDefaults).ifPresent(tries -> {
				PropertyAttributes attributes = context.attributes();
				if (!attributes.tries().isPresent()) {
					attributes.setTries(tries);
				}
			});
			findAfterFailure(propertyDefaults).ifPresent(afterFailure -> {
				PropertyAttributes attributes = context.attributes();
				if (!attributes.afterFailure().isPresent()) {
					attributes.setAfterFailure(afterFailure);
				}
			});
			findShrinking(propertyDefaults).ifPresent(shrinking -> {
				PropertyAttributes attributes = context.attributes();
				if (!attributes.shrinking().isPresent()) {
					attributes.setShrinking(shrinking);
				}
			});
			findGeneration(propertyDefaults).ifPresent(generation -> {
				PropertyAttributes attributes = context.attributes();
				if (!attributes.generation().isPresent()) {
					attributes.setGeneration(generation);
				}
			});
			findEdgeCases(propertyDefaults).ifPresent(edgeCases -> {
				PropertyAttributes attributes = context.attributes();
				if (!attributes.edgeCases().isPresent()) {
					attributes.setEdgeCases(edgeCases);
				}
			});
			findFixedSeedMode(propertyDefaults).ifPresent(mode -> {
				PropertyAttributes attributes = context.attributes();
				if (!attributes.whenFixedSeed().isPresent()) {
					attributes.setWhenFixedSeed(mode);
				}
			});
			findMaxDiscardRation(propertyDefaults).ifPresent(ratio -> {
				PropertyAttributes attributes = context.attributes();
				if (!attributes.maxDiscardRatio().isPresent()) {
					attributes.setMaxDiscardRatio(ratio);
				}
			});

			return property.execute();
		}

		private Optional findTries(List propertyDefaults) {
			return propertyDefaults.stream()
								   .map(PropertyDefaults::tries)
								   .filter(tries -> tries != Property.TRIES_NOT_SET)
								   .findFirst();
		}

		private Optional findAfterFailure(List propertyDefaults) {
			return propertyDefaults.stream()
								   .map(PropertyDefaults::afterFailure)
								   .filter(afterFailure -> afterFailure != AfterFailureMode.NOT_SET)
								   .findFirst();
		}

		private Optional findShrinking(List propertyDefaults) {
			return propertyDefaults.stream()
								   .map(PropertyDefaults::shrinking)
								   .filter(shrinking -> shrinking != ShrinkingMode.NOT_SET)
								   .findFirst();
		}

		private Optional findGeneration(List propertyDefaults) {
			return propertyDefaults.stream()
								   .map(PropertyDefaults::generation)
								   .filter(generation -> generation != GenerationMode.NOT_SET)
								   .findFirst();
		}

		private Optional findEdgeCases(List propertyDefaults) {
			return propertyDefaults.stream()
								   .map(PropertyDefaults::edgeCases)
								   .filter(edgeCases -> edgeCases != EdgeCasesMode.NOT_SET)
								   .findFirst();
		}

		private Optional findFixedSeedMode(List propertyDefaults) {
			return propertyDefaults.stream()
								   .map(PropertyDefaults::whenFixedSeed)
								   .filter(mode -> mode != FixedSeedMode.NOT_SET)
								   .findFirst();
		}

		private Optional findMaxDiscardRation(List propertyDefaults) {
			return propertyDefaults.stream()
								   .map(PropertyDefaults::maxDiscardRatio)
								   .filter(ratio -> ratio != MAX_DISCARD_RATIO_NOT_SET)
								   .findFirst();
		}

		@Override
		public int aroundPropertyProximity() {
			// Somewhat more distant than standard hooks, so that those may change the attributes
			return -10;
		}

		@Override
		public PropagationMode propagateTo() {
			return PropagationMode.ALL_DESCENDANTS;
		}

		@Override
		public boolean appliesTo(Optional element) {
			return element.map(e -> e instanceof Method).orElse(false);
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy