Skip to content

Commit

Permalink
Simplify extension streaming and invocation algorithms
Browse files Browse the repository at this point in the history
Issue: #232
  • Loading branch information
sbrannen committed May 2, 2016
1 parent 7d84c39 commit b681457
Show file tree
Hide file tree
Showing 10 changed files with 116 additions and 155 deletions.
Expand Up @@ -226,8 +226,7 @@ private static class InnermostAndOutermost implements ExtensionRegistrar {


@Override @Override
public void registerExtensions(ExtensionPointRegistry registry) { public void registerExtensions(ExtensionPointRegistry registry) {
registry.register((BeforeEachCallback) ctx -> callSequence.add("innermostBefore"), registry.register((BeforeEachCallback) ctx -> callSequence.add("innermostBefore"), Position.INNERMOST);
Position.INNERMOST);
registry.register((AfterEachCallback) this::innermostAfter, Position.INNERMOST); registry.register((AfterEachCallback) this::innermostAfter, Position.INNERMOST);
registry.register((BeforeEachCallback) this::outermostBefore, Position.OUTERMOST); registry.register((BeforeEachCallback) this::outermostBefore, Position.OUTERMOST);
registry.register((AfterEachCallback) this::outermostAfter, Position.OUTERMOST); registry.register((AfterEachCallback) this::outermostAfter, Position.OUTERMOST);
Expand Down
Expand Up @@ -17,7 +17,7 @@
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Stream;


import org.junit.gen5.api.Test; import org.junit.gen5.api.Test;
import org.junit.gen5.api.extension.ContainerExecutionCondition; import org.junit.gen5.api.extension.ContainerExecutionCondition;
Expand Down Expand Up @@ -118,12 +118,11 @@ public void canStreamOverRegisteredExtensionPoint() throws Exception {


AtomicBoolean hasRun = new AtomicBoolean(false); AtomicBoolean hasRun = new AtomicBoolean(false);


registry.stream(MyExtensionPoint.class, ExtensionRegistry.ApplicationOrder.FORWARD).forEach( stream(registry, MyExtensionPoint.class).forEach(registeredExtensionPoint -> {
registeredExtensionPoint -> { assertEquals(MyExtension.class.getName(), registeredExtensionPoint.getSource().getClass().getName());
assertEquals(MyExtension.class.getName(), registeredExtensionPoint.getSource().getClass().getName()); assertEquals(Position.DEFAULT, registeredExtensionPoint.getPosition());
assertEquals(Position.DEFAULT, registeredExtensionPoint.getPosition()); hasRun.set(true);
hasRun.set(true); });
});


assertTrue(hasRun.get()); assertTrue(hasRun.get());
} }
Expand Down Expand Up @@ -155,24 +154,24 @@ private void assertBehaviorForExtensionPointRegisteredFromLambdaExpressionOrMeth
ExtensionRegistry registry) throws Exception { ExtensionRegistry registry) throws Exception {
AtomicBoolean hasRun = new AtomicBoolean(false); AtomicBoolean hasRun = new AtomicBoolean(false);


registry.stream(MyExtensionPoint.class, ExtensionRegistry.ApplicationOrder.FORWARD).forEach( stream(registry, MyExtensionPoint.class).forEach(registeredExtensionPoint -> {
registeredExtensionPoint -> { Class<? extends MyExtensionPoint> lambdaType = registeredExtensionPoint.getExtensionPoint().getClass();
Class<? extends MyExtensionPoint> lambdaType = registeredExtensionPoint.getExtensionPoint().getClass(); assertTrue(lambdaType.getName().contains("$Lambda$"));
assertTrue(lambdaType.getName().contains("$Lambda$")); assertEquals(getClass().getName(), registeredExtensionPoint.getSource().getClass().getName());
assertEquals(getClass().getName(), registeredExtensionPoint.getSource().getClass().getName()); assertEquals(Position.DEFAULT, registeredExtensionPoint.getPosition());
assertEquals(Position.DEFAULT, registeredExtensionPoint.getPosition()); hasRun.set(true);
hasRun.set(true); });
});


assertTrue(hasRun.get()); assertTrue(hasRun.get());
} }


private int countExtensionPoints(ExtensionRegistry registry, Class<? extends ExtensionPoint> extensionPointType) private <E extends ExtensionPoint> Stream<RegisteredExtensionPoint<E>> stream(ExtensionRegistry registry,
throws Exception { Class<E> extensionType) {
AtomicInteger counter = new AtomicInteger(); return registry.getRegisteredExtensionPoints(extensionType).stream();
registry.stream(extensionPointType, ExtensionRegistry.ApplicationOrder.FORWARD).forEach( }
registeredExtensionPoint -> counter.incrementAndGet());
return counter.get(); private long countExtensionPoints(ExtensionRegistry registry, Class<? extends ExtensionPoint> extensionType) {
return registry.stream(extensionType).count();
} }


private void assertExtensionRegistered(ExtensionRegistry registry, Class<? extends Extension> extensionClass) { private void assertExtensionRegistered(ExtensionRegistry registry, Class<? extends Extension> extensionClass) {
Expand Down
Expand Up @@ -10,8 +10,12 @@


package org.junit.gen5.engine.junit5.descriptor; package org.junit.gen5.engine.junit5.descriptor;


import java.util.*; import static java.util.stream.Collectors.toCollection;
import java.util.stream.Collectors;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;


import org.junit.gen5.api.extension.ExtensionContext; import org.junit.gen5.api.extension.ExtensionContext;
import org.junit.gen5.engine.EngineExecutionListener; import org.junit.gen5.engine.EngineExecutionListener;
Expand Down Expand Up @@ -68,6 +72,7 @@ public Store getStore(Namespace namespace) {


@Override @Override
public Set<String> getTags() { public Set<String> getTags() {
return testDescriptor.getTags().stream().map(TestTag::getName).collect(Collectors.toSet()); return testDescriptor.getTags().stream().map(TestTag::getName).collect(toCollection(LinkedHashSet::new));
} }

} }
Expand Up @@ -19,7 +19,6 @@
import java.util.Set; import java.util.Set;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Consumer;


import org.junit.gen5.api.AfterAll; import org.junit.gen5.api.AfterAll;
import org.junit.gen5.api.AfterEach; import org.junit.gen5.api.AfterEach;
Expand Down Expand Up @@ -47,7 +46,6 @@
import org.junit.gen5.engine.junit5.execution.TestInstanceProvider; import org.junit.gen5.engine.junit5.execution.TestInstanceProvider;
import org.junit.gen5.engine.junit5.execution.ThrowableCollector; import org.junit.gen5.engine.junit5.execution.ThrowableCollector;
import org.junit.gen5.engine.junit5.extension.ExtensionRegistry; import org.junit.gen5.engine.junit5.extension.ExtensionRegistry;
import org.junit.gen5.engine.junit5.extension.RegisteredExtensionPoint;
import org.junit.gen5.engine.support.descriptor.JavaSource; import org.junit.gen5.engine.support.descriptor.JavaSource;
import org.junit.gen5.engine.support.hierarchical.Container; import org.junit.gen5.engine.support.hierarchical.Container;


Expand Down Expand Up @@ -136,10 +134,8 @@ public SkipResult shouldBeSkipped(JUnit5EngineExecutionContext context) throws E


@Override @Override
public JUnit5EngineExecutionContext beforeAll(JUnit5EngineExecutionContext context) throws Exception { public JUnit5EngineExecutionContext beforeAll(JUnit5EngineExecutionContext context) throws Exception {
ExtensionRegistry extensionRegistry = context.getExtensionRegistry(); invokeBeforeAllCallbacks(context.getExtensionRegistry(),
ContainerExtensionContext containerExtensionContext = (ContainerExtensionContext) context.getExtensionContext(); (ContainerExtensionContext) context.getExtensionContext());

invokeBeforeAllCallbacks(extensionRegistry, containerExtensionContext);


return context; return context;
} }
Expand All @@ -160,25 +156,20 @@ protected TestInstanceProvider testInstanceProvider(JUnit5EngineExecutionContext
return () -> ReflectionUtils.newInstance(testClass); return () -> ReflectionUtils.newInstance(testClass);
} }


private void invokeBeforeAllCallbacks(ExtensionRegistry newExtensionRegistry, private void invokeBeforeAllCallbacks(ExtensionRegistry registry, ContainerExtensionContext context) {
ContainerExtensionContext containerExtensionContext) throws Exception { // @formatter:off

registry.stream(BeforeAllCallback.class)
Consumer<RegisteredExtensionPoint<BeforeAllCallback>> applyBeforeEach = registeredExtensionPoint -> executeAndMaskThrowable( .forEach(extension -> executeAndMaskThrowable(() -> extension.beforeAll(context)));
() -> registeredExtensionPoint.getExtensionPoint().beforeAll(containerExtensionContext)); // @formatter:on

newExtensionRegistry.stream(BeforeAllCallback.class, ExtensionRegistry.ApplicationOrder.FORWARD).forEach(
applyBeforeEach);
} }


private void invokeAfterAllCallbacks(ExtensionRegistry newExtensionRegistry, private void invokeAfterAllCallbacks(ExtensionRegistry registry, ContainerExtensionContext context,
ContainerExtensionContext containerExtensionContext, ThrowableCollector throwableCollector) ThrowableCollector throwableCollector) {
throws Exception {

Consumer<RegisteredExtensionPoint<AfterAllCallback>> applyAfterAll = registeredExtensionPoint -> throwableCollector.execute(
() -> registeredExtensionPoint.getExtensionPoint().afterAll(containerExtensionContext));


newExtensionRegistry.stream(AfterAllCallback.class, ExtensionRegistry.ApplicationOrder.BACKWARD).forEach( // @formatter:off
applyAfterAll); registry.reverseStream(AfterAllCallback.class)
.forEach(extension -> throwableCollector.execute(() -> extension.afterAll(context)));
// @formatter:on
} }


private void registerBeforeAllMethods(ExtensionRegistry extensionRegistry) { private void registerBeforeAllMethods(ExtensionRegistry extensionRegistry) {
Expand Down Expand Up @@ -225,14 +216,14 @@ private AfterAllCallback synthesizeAfterAllCallback(ExtensionRegistry registry,
} }


private BeforeEachCallback synthesizeBeforeEachCallback(ExtensionRegistry registry, Method method) { private BeforeEachCallback synthesizeBeforeEachCallback(ExtensionRegistry registry, Method method) {
return extensionContext -> runMethodInTestExtensionContext(method, extensionContext, registry); return extensionContext -> invokeMethodInTestExtensionContext(method, extensionContext, registry);
} }


private AfterEachCallback synthesizeAfterEachCallback(ExtensionRegistry registry, Method method) { private AfterEachCallback synthesizeAfterEachCallback(ExtensionRegistry registry, Method method) {
return extensionContext -> runMethodInTestExtensionContext(method, extensionContext, registry); return extensionContext -> invokeMethodInTestExtensionContext(method, extensionContext, registry);
} }


private void runMethodInTestExtensionContext(Method method, TestExtensionContext context, private void invokeMethodInTestExtensionContext(Method method, TestExtensionContext context,
ExtensionRegistry registry) { ExtensionRegistry registry) {


// @formatter:off // @formatter:off
Expand Down
Expand Up @@ -10,14 +10,13 @@


package org.junit.gen5.engine.junit5.descriptor; package org.junit.gen5.engine.junit5.descriptor;


import static java.util.stream.Collectors.toList;
import static org.junit.gen5.commons.meta.API.Usage.Internal; import static org.junit.gen5.commons.meta.API.Usage.Internal;
import static org.junit.gen5.engine.junit5.execution.MethodInvocationContextFactory.methodInvocationContext; import static org.junit.gen5.engine.junit5.execution.MethodInvocationContextFactory.methodInvocationContext;


import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Collectors;


import org.junit.gen5.api.extension.AfterEachCallback; import org.junit.gen5.api.extension.AfterEachCallback;
import org.junit.gen5.api.extension.AfterTestMethodCallback; import org.junit.gen5.api.extension.AfterTestMethodCallback;
Expand All @@ -40,8 +39,6 @@
import org.junit.gen5.engine.junit5.execution.MethodInvoker; import org.junit.gen5.engine.junit5.execution.MethodInvoker;
import org.junit.gen5.engine.junit5.execution.ThrowableCollector; import org.junit.gen5.engine.junit5.execution.ThrowableCollector;
import org.junit.gen5.engine.junit5.extension.ExtensionRegistry; import org.junit.gen5.engine.junit5.extension.ExtensionRegistry;
import org.junit.gen5.engine.junit5.extension.ExtensionRegistry.ApplicationOrder;
import org.junit.gen5.engine.junit5.extension.RegisteredExtensionPoint;
import org.junit.gen5.engine.support.descriptor.JavaSource; import org.junit.gen5.engine.support.descriptor.JavaSource;
import org.junit.gen5.engine.support.hierarchical.Leaf; import org.junit.gen5.engine.support.hierarchical.Leaf;


Expand Down Expand Up @@ -156,37 +153,25 @@ public JUnit5EngineExecutionContext execute(JUnit5EngineExecutionContext context
return context; return context;
} }


private void invokeInstancePostProcessors(ExtensionRegistry extensionRegistry, private void invokeInstancePostProcessors(ExtensionRegistry registry, TestExtensionContext context) {
TestExtensionContext testExtensionContext) throws Exception { // @formatter:off

registry.stream(InstancePostProcessor.class)
Consumer<RegisteredExtensionPoint<InstancePostProcessor>> applyInstancePostProcessor = registeredExtensionPoint -> { .forEach(extension -> executeAndMaskThrowable(() -> extension.postProcessTestInstance(context)));
executeAndMaskThrowable( // @formatter:on
() -> registeredExtensionPoint.getExtensionPoint().postProcessTestInstance(testExtensionContext));
};

extensionRegistry.stream(InstancePostProcessor.class).forEach(applyInstancePostProcessor);
} }


private void invokeBeforeEachCallbacks(ExtensionRegistry extensionRegistry, private void invokeBeforeEachCallbacks(ExtensionRegistry registry, TestExtensionContext context) {
TestExtensionContext testExtensionContext) throws Exception { // @formatter:off

registry.stream(BeforeEachCallback.class)
Consumer<RegisteredExtensionPoint<BeforeEachCallback>> applyBeforeEach = registeredExtensionPoint -> { .forEach(extension -> executeAndMaskThrowable(() -> extension.beforeEach(context)));
executeAndMaskThrowable( // @formatter:on
() -> registeredExtensionPoint.getExtensionPoint().beforeEach(testExtensionContext));
};

extensionRegistry.stream(BeforeEachCallback.class).forEach(applyBeforeEach);
} }


private void invokeBeforeTestMethodCallbacks(ExtensionRegistry extensionRegistry, private void invokeBeforeTestMethodCallbacks(ExtensionRegistry registry, TestExtensionContext context) {
TestExtensionContext testExtensionContext) throws Exception { // @formatter:off

registry.stream(BeforeTestMethodCallback.class)
Consumer<RegisteredExtensionPoint<BeforeTestMethodCallback>> action = registeredExtensionPoint -> { .forEach(extension -> executeAndMaskThrowable(() -> extension.beforeTestMethod(context)));
executeAndMaskThrowable( // @formatter:on
() -> registeredExtensionPoint.getExtensionPoint().beforeTestMethod(testExtensionContext));
};

extensionRegistry.stream(BeforeTestMethodCallback.class).forEachOrdered(action);
} }


private void invokeTestMethod(ExtensionRegistry ExtensionRegistry, TestExtensionContext testExtensionContext, private void invokeTestMethod(ExtensionRegistry ExtensionRegistry, TestExtensionContext testExtensionContext,
Expand All @@ -201,58 +186,47 @@ private void invokeTestMethod(ExtensionRegistry ExtensionRegistry, TestExtension
catch (Throwable throwable) { catch (Throwable throwable) {
invokeExceptionHandlers(ExtensionRegistry, testExtensionContext, throwable); invokeExceptionHandlers(ExtensionRegistry, testExtensionContext, throwable);
} }

}); });
} }


private void invokeExceptionHandlers(ExtensionRegistry extensionRegistry, private void invokeExceptionHandlers(ExtensionRegistry registry, TestExtensionContext context, Throwable ex) {
TestExtensionContext testExtensionContext, Throwable throwable) { List<ExceptionHandler> exceptionHandlers = registry.stream(ExceptionHandler.class).collect(toList());


// Necessary because mere streaming over exception handlers does not suffice. invokeExceptionHandlers(ex, exceptionHandlers, context);
List<ExceptionHandler> exceptionHandlers = collectExceptionHandlers(extensionRegistry);
invokeExceptionHandlers(throwable, exceptionHandlers, testExtensionContext);
} }


private List<ExceptionHandler> collectExceptionHandlers(ExtensionRegistry extensionRegistry) { private void invokeExceptionHandlers(Throwable ex, List<ExceptionHandler> handlers, TestExtensionContext context) {
return extensionRegistry.stream(ExceptionHandler.class).map(
RegisteredExtensionPoint::getExtensionPoint).collect(Collectors.toList());
}

private void invokeExceptionHandlers(Throwable throwable, List<ExceptionHandler> exceptionHandlers,
TestExtensionContext testExtensionContext) {


// No handlers left? // No handlers left?
if (exceptionHandlers.isEmpty()) { if (handlers.isEmpty()) {
ExceptionUtils.throwAsUncheckedException(throwable); ExceptionUtils.throwAsUncheckedException(ex);
} }


try { try {
// Invoke next available handler // Invoke next available handler
exceptionHandlers.remove(0).handleException(testExtensionContext, throwable); handlers.remove(0).handleException(context, ex);
} }
catch (Throwable t) { catch (Throwable t) {
invokeExceptionHandlers(t, exceptionHandlers, testExtensionContext); invokeExceptionHandlers(t, handlers, context);
} }
} }


private void invokeAfterTestMethodCallbacks(ExtensionRegistry extensionRegistry, private void invokeAfterTestMethodCallbacks(ExtensionRegistry registry, TestExtensionContext context,
TestExtensionContext testExtensionContext, ThrowableCollector throwableCollector) throws Exception { ThrowableCollector throwableCollector) {


extensionRegistry.stream(AfterTestMethodCallback.class, ApplicationOrder.BACKWARD).forEach( // @formatter:off
registeredExtensionPoint -> { registry.reverseStream(AfterTestMethodCallback.class)
throwableCollector.execute( .forEach(extension -> throwableCollector.execute(() -> extension.afterTestMethod(context)));
() -> registeredExtensionPoint.getExtensionPoint().afterTestMethod(testExtensionContext)); // @formatter:on
});
} }


private void invokeAfterEachCallbacks(ExtensionRegistry extensionRegistry, private void invokeAfterEachCallbacks(ExtensionRegistry registry, TestExtensionContext context,
TestExtensionContext testExtensionContext, ThrowableCollector throwableCollector) throws Exception { ThrowableCollector throwableCollector) {


extensionRegistry.stream(AfterEachCallback.class, ApplicationOrder.BACKWARD).forEach( // @formatter:off
registeredExtensionPoint -> { registry.reverseStream(AfterEachCallback.class)
throwableCollector.execute( .forEach(extension -> throwableCollector.execute(() -> extension.afterEach(context)));
() -> registeredExtensionPoint.getExtensionPoint().afterEach(testExtensionContext)); // @formatter:on
});
} }


} }
Expand Up @@ -21,7 +21,6 @@
import org.junit.gen5.api.extension.TestExtensionContext; import org.junit.gen5.api.extension.TestExtensionContext;
import org.junit.gen5.commons.meta.API; import org.junit.gen5.commons.meta.API;
import org.junit.gen5.engine.junit5.extension.ExtensionRegistry; import org.junit.gen5.engine.junit5.extension.ExtensionRegistry;
import org.junit.gen5.engine.junit5.extension.RegisteredExtensionPoint;


/** /**
* {@code ConditionEvaluator} evaluates {@link ContainerExecutionCondition} * {@code ConditionEvaluator} evaluates {@link ContainerExecutionCondition}
Expand Down Expand Up @@ -51,8 +50,7 @@ public class ConditionEvaluator {
public ConditionEvaluationResult evaluateForContainer(ExtensionRegistry extensionRegistry, public ConditionEvaluationResult evaluateForContainer(ExtensionRegistry extensionRegistry,
ContainerExtensionContext context) { ContainerExtensionContext context) {
// @formatter:off // @formatter:off
return extensionRegistry.stream(ContainerExecutionCondition.class, ExtensionRegistry.ApplicationOrder.FORWARD) return extensionRegistry.stream(ContainerExecutionCondition.class)
.map(RegisteredExtensionPoint::getExtensionPoint)
.map(condition -> evaluate(condition, context)) .map(condition -> evaluate(condition, context))
.filter(ConditionEvaluationResult::isDisabled) .filter(ConditionEvaluationResult::isDisabled)
.findFirst() .findFirst()
Expand All @@ -72,8 +70,7 @@ public ConditionEvaluationResult evaluateForContainer(ExtensionRegistry extensio
public ConditionEvaluationResult evaluateForTest(ExtensionRegistry extensionRegistry, public ConditionEvaluationResult evaluateForTest(ExtensionRegistry extensionRegistry,
TestExtensionContext context) { TestExtensionContext context) {
// @formatter:off // @formatter:off
return extensionRegistry.stream(TestExecutionCondition.class, ExtensionRegistry.ApplicationOrder.FORWARD) return extensionRegistry.stream(TestExecutionCondition.class)
.map(RegisteredExtensionPoint::getExtensionPoint)
.map(condition -> evaluate(condition, context)) .map(condition -> evaluate(condition, context))
.filter(ConditionEvaluationResult::isDisabled) .filter(ConditionEvaluationResult::isDisabled)
.findFirst() .findFirst()
Expand Down
Expand Up @@ -27,7 +27,6 @@
import org.junit.gen5.commons.meta.API; import org.junit.gen5.commons.meta.API;
import org.junit.gen5.commons.util.ReflectionUtils; import org.junit.gen5.commons.util.ReflectionUtils;
import org.junit.gen5.engine.junit5.extension.ExtensionRegistry; import org.junit.gen5.engine.junit5.extension.ExtensionRegistry;
import org.junit.gen5.engine.junit5.extension.RegisteredExtensionPoint;


/** /**
* {@code MethodInvoker} encapsulates the invocation of a method, including * {@code MethodInvoker} encapsulates the invocation of a method, including
Expand Down Expand Up @@ -76,7 +75,6 @@ private Object resolveParameter(Parameter parameter, MethodInvocationContext met
try { try {
// @formatter:off // @formatter:off
List<MethodParameterResolver> matchingResolvers = extensionRegistry.stream(MethodParameterResolver.class) List<MethodParameterResolver> matchingResolvers = extensionRegistry.stream(MethodParameterResolver.class)
.map(RegisteredExtensionPoint::getExtensionPoint)
.filter(extensionPoint -> extensionPoint.supports(parameter, methodInvocationContext, extensionContext)) .filter(extensionPoint -> extensionPoint.supports(parameter, methodInvocationContext, extensionContext))
.collect(toList()); .collect(toList());
// @formatter:on // @formatter:on
Expand Down

0 comments on commit b681457

Please sign in to comment.