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

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

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

import java.lang.reflect.*;

import net.jqwik.api.*;
import net.jqwik.api.domains.*;
import net.jqwik.api.lifecycle.*;
import net.jqwik.api.lifecycle.SkipExecutionHook.*;
import net.jqwik.engine.descriptor.*;
import net.jqwik.engine.execution.lifecycle.*;
import net.jqwik.engine.execution.pipeline.*;
import net.jqwik.engine.execution.reporting.*;
import net.jqwik.engine.support.*;

class PropertyTaskCreator {

	ExecutionTask createTask(
		PropertyMethodDescriptor methodDescriptor,
		LifecycleHooksSupplier lifecycleSupplier,
		boolean reportOnlyFailures
	) {
		return ExecutionTask.from(
			(listener, predecessorResult) -> {

				if (!predecessorResult.successful()) {
					String reason = String.format("Skipped due to container failure: %s", predecessorResult.throwable().orElse(null));
					listener.executionSkipped(methodDescriptor, reason);
					return predecessorResult;
				}

				PropertyLifecycleContext propertyLifecycleContext;

				try {
					propertyLifecycleContext = createLifecycleContext(methodDescriptor, lifecycleSupplier, listener);

					SkipResult skipResult = CurrentTestDescriptor.runWithDescriptor(methodDescriptor, () -> {
						SkipExecutionHook skipExecutionHook = lifecycleSupplier.skipExecutionHook(methodDescriptor);
						return skipExecutionHook.shouldBeSkipped(propertyLifecycleContext);
					});

					if (skipResult.isSkipped()) {
						listener.executionSkipped(methodDescriptor, skipResult.reason().orElse(null));
						return TaskExecutionResult.success();
					}

					listener.executionStarted(methodDescriptor);

					try {
						DomainContext domainContext = createDomainContext(methodDescriptor, propertyLifecycleContext);
						CurrentDomainContext.runWithContext(domainContext, () -> {
							PropertyExecutionResult executionResult = executeTestMethod(
								methodDescriptor, propertyLifecycleContext, lifecycleSupplier, reportOnlyFailures
							);
							listener.executionFinished(methodDescriptor, executionResult);
							return null;
						});
					} finally {
						StoreRepository.getCurrent().finishScope(methodDescriptor);
					}

				} catch (Throwable throwable) {
					JqwikExceptionSupport.rethrowIfBlacklisted(throwable);
					handleExceptionDuringTestInstanceCreation(methodDescriptor, listener, throwable);
				}

				return TaskExecutionResult.success();
			},
			methodDescriptor,
			"executing " + methodDescriptor.getDisplayName()
		);
	}

	private DomainContext createDomainContext(
		PropertyMethodDescriptor methodDescriptor,
		PropertyLifecycleContext propertyLifecycleContext
	) {
		DomainContextFactory domainContextFactory = new DomainContextFactory(propertyLifecycleContext, methodDescriptor);
		return domainContextFactory.createCombinedDomainContext();
	}

	private PropertyLifecycleContext createLifecycleContext(
		PropertyMethodDescriptor methodDescriptor,
		LifecycleHooksSupplier lifecycleSupplier,
		PropertyExecutionListener listener
	) {
		PropertyLifecycleContext propertyLifecycleContext;
		ResolveParameterHook resolveParameterHook = lifecycleSupplier.resolveParameterHook(methodDescriptor);
		Reporter reporter = new DefaultReporter(listener::reportingEntryPublished, methodDescriptor);
		ContainerInstances testInstances = createTestInstances(methodDescriptor, lifecycleSupplier, reporter);
		propertyLifecycleContext = new DefaultPropertyLifecycleContext(methodDescriptor, testInstances, reporter, resolveParameterHook);
		return propertyLifecycleContext;
	}

	private void handleExceptionDuringTestInstanceCreation(
		PropertyMethodDescriptor methodDescriptor,
		PropertyExecutionListener listener,
		Throwable throwable
	) {
		listener.executionStarted(methodDescriptor);
		PropertyExecutionResult executionResult =
			PlainExecutionResult.failed(throwable, methodDescriptor.getConfiguration().getSeed());
		listener.executionFinished(methodDescriptor, executionResult);
	}

	private ContainerInstances createTestInstances(
		PropertyMethodDescriptor methodDescriptor,
		LifecycleHooksSupplier lifecycleSupplier,
		Reporter reporter
	) {
		try {
			return methodDescriptor.getParent().map(
				containerDescriptor -> {
					//TODO: Hand context in from outside to always have the same instance.
					//  This will require a major overhaul of task creation :-(
					ResolveParameterHook resolveParameterHook = lifecycleSupplier.resolveParameterHook(containerDescriptor);
					ProvidePropertyInstanceHook providePropertyInstanceHook = lifecycleSupplier.providePropertyInstanceHook(containerDescriptor);
					ContainerLifecycleContext containerLifecycleContext = new DefaultContainerLifecycleContext(
						(ContainerClassDescriptor) containerDescriptor,
						reporter,
						resolveParameterHook
					);
					return CurrentTestDescriptor.runWithDescriptor(
						containerDescriptor,
						() -> createTestInstancesWithResolvedParameters(
							containerLifecycleContext,
							(ContainerClassDescriptor) containerDescriptor,
							providePropertyInstanceHook
						)
					);
				}).orElseThrow(() -> new JqwikException("Method descriptors must have a parent"));
		} catch (JqwikException jqwikException) {
			throw jqwikException;
		} catch (Throwable throwable) {
			JqwikExceptionSupport.rethrowIfBlacklisted(throwable);
			String message = String.format(
				"Cannot create instance of class '%s'",
				methodDescriptor.getContainerClass()
			);
			if (throwable instanceof InvocationTargetException) {
				throwable = ((InvocationTargetException) throwable).getTargetException();
			}
			throw new JqwikException(message, throwable);
		}
	}

	private ContainerInstances createTestInstancesWithResolvedParameters(
		ContainerLifecycleContext containerLifecycleContext,
		ContainerClassDescriptor containerDescriptor,
		ProvidePropertyInstanceHook providePropertyInstanceHook
	) {
		ContainerInstancesCreator testInstancesCreator = new ContainerInstancesCreator(
			containerLifecycleContext,
			containerDescriptor,
			providePropertyInstanceHook
		);
		return testInstancesCreator.create();
	}

	private PropertyExecutionResult executeTestMethod(
		PropertyMethodDescriptor methodDescriptor,
		PropertyLifecycleContext propertyLifecycleContext,
		LifecycleHooksSupplier lifecycleSupplier,
		boolean reportOnlyFailures
	) {
		PropertyMethodExecutor executor = new PropertyMethodExecutor(methodDescriptor, propertyLifecycleContext, reportOnlyFailures);
		return executor.execute(lifecycleSupplier);
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy