Search in sources :

Example 1 with ReflectiveInvocationContext

use of org.junit.jupiter.api.extension.ReflectiveInvocationContext in project taskana by Taskana.

the class JaasExtension method interceptTestFactoryMethod.

@Override
@SuppressWarnings("unchecked")
public <T> T interceptTestFactoryMethod(Invocation<T> invocation, ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext) {
    WithAccessIds annotation = invocationContext.getExecutable().getAnnotation(WithAccessIds.class);
    if (annotation != null) {
        // our goal is to run each test returned from the test factory X times. X is the amount of
        // WithAccessId annotations. In order to achieve this we are wrapping the result from the
        // factory (the returning tests) in a dynamicContainer for each accessId. Since we don't know
        // what the factory will return we have to check for every possible return type. All possible
        // return types can be found here:
        // https://junit.org/junit5/docs/current/user-guide/#writing-tests-dynamic-tests
        // After checking each return type we abuse the return type of T and hardly change it to
        // Stream<DynamicContainer> no matter what the factory returns. This return type is allowed
        // per definition (See link above), but is not the type T. Hence we have an unchecked cast at
        // the end to keep the compiler happy...
        // we are using the first annotation to run the factory method with.
        T factoryResult = performInvocationWithAccessId(invocation, annotation.value()[0]);
        Iterable<DynamicNode> newChildrenForDynamicContainer;
        // TestFactory must have one of the following return types. See link above for further details
        if (factoryResult instanceof DynamicNode) {
            newChildrenForDynamicContainer = Collections.singleton((DynamicNode) factoryResult);
        } else if (factoryResult instanceof Stream) {
            Stream<DynamicNode> nodes = (Stream<DynamicNode>) factoryResult;
            newChildrenForDynamicContainer = nodes.collect(Collectors.toList());
        } else if (factoryResult instanceof Iterable) {
            newChildrenForDynamicContainer = (Iterable<DynamicNode>) factoryResult;
        } else if (factoryResult instanceof Iterator) {
            newChildrenForDynamicContainer = () -> (Iterator<DynamicNode>) factoryResult;
        } else if (factoryResult instanceof DynamicNode[]) {
            newChildrenForDynamicContainer = Arrays.asList((DynamicNode[]) factoryResult);
        } else {
            throw new SystemException(String.format("Testfactory '%s' did not return a proper type", invocationContext.getExecutable().getName()));
        }
        // Currently, a DynamicContainer has children from this type: Stream<DynamicNode>
        // Because of this the children can only be extracted once (Streams can only be operated
        // once). This is obviously not ok since we want to execute each node X times. So we have to
        // manually insert all children recursively to extract them X times...
        Map<String, List<DynamicNode>> childrenMap = new HashMap<>();
        persistDynamicContainerChildren(newChildrenForDynamicContainer, childrenMap);
        Function<WithAccessId, DynamicContainer> wrapTestsInDynamicContainer = accessId -> DynamicContainer.dynamicContainer(getDisplayNameForAccessId(accessId), StreamSupport.stream(newChildrenForDynamicContainer.spliterator(), false).map(x -> duplicateDynamicNode(x, childrenMap)));
        Store store = getMethodLevelStore(extensionContext);
        return (T) Stream.of(annotation.value()).peek(a -> store.put(ACCESS_IDS_STORE_KEY, a)).map(wrapTestsInDynamicContainer);
    }
    return extractAccessIdAndPerformInvocation(invocation, invocationContext.getExecutable());
}
Also used : AnnotationSupport.isAnnotated(org.junit.platform.commons.support.AnnotationSupport.isAnnotated) Arrays(java.util.Arrays) DynamicContainer(org.junit.jupiter.api.DynamicContainer) HashMap(java.util.HashMap) DynamicNode(org.junit.jupiter.api.DynamicNode) UserPrincipal(pro.taskana.common.api.security.UserPrincipal) ExtensionContext(org.junit.jupiter.api.extension.ExtensionContext) Constructor(java.lang.reflect.Constructor) Function(java.util.function.Function) DynamicTestInvocationContext(org.junit.jupiter.api.extension.DynamicTestInvocationContext) Extension(org.junit.jupiter.api.extension.Extension) GroupPrincipal(pro.taskana.common.api.security.GroupPrincipal) Map(java.util.Map) CheckedFunction.wrapExceptFor(pro.taskana.common.internal.util.CheckedFunction.wrapExceptFor) StreamSupport(java.util.stream.StreamSupport) TestTemplateInvocationContextProvider(org.junit.jupiter.api.extension.TestTemplateInvocationContextProvider) Method(java.lang.reflect.Method) Namespace(org.junit.jupiter.api.extension.ExtensionContext.Namespace) SystemException(pro.taskana.common.api.exceptions.SystemException) Iterator(java.util.Iterator) InvocationInterceptor(org.junit.jupiter.api.extension.InvocationInterceptor) JUnitException(org.junit.platform.commons.JUnitException) TestAbortedException(org.opentest4j.TestAbortedException) PrivilegedAction(java.security.PrivilegedAction) Store(org.junit.jupiter.api.extension.ExtensionContext.Store) Collectors(java.util.stream.Collectors) Subject(javax.security.auth.Subject) ReflectiveInvocationContext(org.junit.jupiter.api.extension.ReflectiveInvocationContext) ParameterContext(org.junit.jupiter.api.extension.ParameterContext) List(java.util.List) AnnotationSupport(org.junit.platform.commons.support.AnnotationSupport) Principal(java.security.Principal) Stream(java.util.stream.Stream) TestTemplateInvocationContext(org.junit.jupiter.api.extension.TestTemplateInvocationContext) WithAccessIds(pro.taskana.common.test.security.WithAccessId.WithAccessIds) Optional(java.util.Optional) Collections(java.util.Collections) ParameterResolver(org.junit.jupiter.api.extension.ParameterResolver) AnnotatedElement(java.lang.reflect.AnnotatedElement) HashMap(java.util.HashMap) Store(org.junit.jupiter.api.extension.ExtensionContext.Store) DynamicContainer(org.junit.jupiter.api.DynamicContainer) SystemException(pro.taskana.common.api.exceptions.SystemException) WithAccessIds(pro.taskana.common.test.security.WithAccessId.WithAccessIds) Iterator(java.util.Iterator) DynamicNode(org.junit.jupiter.api.DynamicNode) Stream(java.util.stream.Stream) List(java.util.List)

Example 2 with ReflectiveInvocationContext

use of org.junit.jupiter.api.extension.ReflectiveInvocationContext in project taskana by Taskana.

the class JaasExtension method interceptTestFactoryMethod.

@Override
@SuppressWarnings("unchecked")
public <T> T interceptTestFactoryMethod(Invocation<T> invocation, ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext) {
    WithAccessIds annotation = invocationContext.getExecutable().getAnnotation(WithAccessIds.class);
    if (annotation != null) {
        // our goal is to run each test returned from the test factory X times. X is the amount of
        // WithAccessId annotations. In order to achieve this we are wrapping the result from the
        // factory (the returning tests) in a dynamicContainer for each accessId. Since we don't know
        // what the factory will return we have to check for every possible return type. All possible
        // return types can be found here:
        // https://junit.org/junit5/docs/current/user-guide/#writing-tests-dynamic-tests
        // After checking each return type we abuse the return type of T and hardly change it to
        // Stream<DynamicContainer> no matter what the factory returns. This return type is allowed
        // per definition (See link above), but is not the type T. Hence we have an unchecked cast at
        // the end to keep the compiler happy...
        // we are using the first annotation to run the factory method with.
        T factoryResult = performInvocationWithAccessId(invocation, annotation.value()[0]);
        Iterable<DynamicNode> newChildrenForDynamicContainer;
        // TestFactory must have one of the following return types. See link above for further details
        if (factoryResult instanceof DynamicNode) {
            newChildrenForDynamicContainer = Collections.singleton((DynamicNode) factoryResult);
        } else if (factoryResult instanceof Stream) {
            Stream<DynamicNode> nodes = (Stream<DynamicNode>) factoryResult;
            newChildrenForDynamicContainer = nodes.collect(Collectors.toList());
        } else if (factoryResult instanceof Iterable) {
            newChildrenForDynamicContainer = (Iterable<DynamicNode>) factoryResult;
        } else if (factoryResult instanceof Iterator) {
            newChildrenForDynamicContainer = () -> (Iterator<DynamicNode>) factoryResult;
        } else if (factoryResult instanceof DynamicNode[]) {
            newChildrenForDynamicContainer = Arrays.asList((DynamicNode[]) factoryResult);
        } else {
            throw new SystemException(String.format("Testfactory '%s' did not return a proper type", invocationContext.getExecutable().getName()));
        }
        // Currently, a DynamicContainer has children from this type: Stream<DynamicNode>
        // Because of this the children can only be extracted once (Streams can only be operated
        // once). This is obviously not ok since we want to execute each node X times. So we have to
        // manually insert all children recursively to extract them X times...
        Map<String, List<DynamicNode>> childrenMap = new HashMap<>();
        persistDynamicContainerChildren(newChildrenForDynamicContainer, childrenMap);
        Function<WithAccessId, DynamicContainer> wrapTestsInDynamicContainer = accessId -> DynamicContainer.dynamicContainer(getDisplayNameForAccessId(accessId), StreamSupport.stream(newChildrenForDynamicContainer.spliterator(), false).map(x -> duplicateDynamicNode(x, childrenMap)));
        Store store = getMethodLevelStore(extensionContext);
        return (T) Stream.of(annotation.value()).peek(a -> store.put(ACCESS_IDS_STORE_KEY, a)).map(wrapTestsInDynamicContainer);
    }
    return extractAccessIdAndPerformInvocation(invocation, invocationContext.getExecutable());
}
Also used : AnnotationSupport.isAnnotated(org.junit.platform.commons.support.AnnotationSupport.isAnnotated) Arrays(java.util.Arrays) DynamicContainer(org.junit.jupiter.api.DynamicContainer) HashMap(java.util.HashMap) DynamicNode(org.junit.jupiter.api.DynamicNode) UserPrincipal(pro.taskana.common.api.security.UserPrincipal) ExtensionContext(org.junit.jupiter.api.extension.ExtensionContext) Constructor(java.lang.reflect.Constructor) Function(java.util.function.Function) DynamicTestInvocationContext(org.junit.jupiter.api.extension.DynamicTestInvocationContext) Extension(org.junit.jupiter.api.extension.Extension) GroupPrincipal(pro.taskana.common.api.security.GroupPrincipal) Map(java.util.Map) CheckedFunction.wrapExceptFor(pro.taskana.common.internal.util.CheckedFunction.wrapExceptFor) StreamSupport(java.util.stream.StreamSupport) TestTemplateInvocationContextProvider(org.junit.jupiter.api.extension.TestTemplateInvocationContextProvider) Method(java.lang.reflect.Method) Namespace(org.junit.jupiter.api.extension.ExtensionContext.Namespace) SystemException(pro.taskana.common.api.exceptions.SystemException) Iterator(java.util.Iterator) InvocationInterceptor(org.junit.jupiter.api.extension.InvocationInterceptor) JUnitException(org.junit.platform.commons.JUnitException) TestAbortedException(org.opentest4j.TestAbortedException) WithAccessIds(pro.taskana.testapi.security.WithAccessId.WithAccessIds) PrivilegedAction(java.security.PrivilegedAction) Store(org.junit.jupiter.api.extension.ExtensionContext.Store) Collectors(java.util.stream.Collectors) Subject(javax.security.auth.Subject) ReflectiveInvocationContext(org.junit.jupiter.api.extension.ReflectiveInvocationContext) ParameterContext(org.junit.jupiter.api.extension.ParameterContext) List(java.util.List) AnnotationSupport(org.junit.platform.commons.support.AnnotationSupport) Principal(java.security.Principal) Stream(java.util.stream.Stream) TestTemplateInvocationContext(org.junit.jupiter.api.extension.TestTemplateInvocationContext) Optional(java.util.Optional) Collections(java.util.Collections) ParameterResolver(org.junit.jupiter.api.extension.ParameterResolver) AnnotatedElement(java.lang.reflect.AnnotatedElement) HashMap(java.util.HashMap) Store(org.junit.jupiter.api.extension.ExtensionContext.Store) DynamicContainer(org.junit.jupiter.api.DynamicContainer) SystemException(pro.taskana.common.api.exceptions.SystemException) WithAccessIds(pro.taskana.testapi.security.WithAccessId.WithAccessIds) Iterator(java.util.Iterator) DynamicNode(org.junit.jupiter.api.DynamicNode) Stream(java.util.stream.Stream) List(java.util.List)

Aggregations

AnnotatedElement (java.lang.reflect.AnnotatedElement)2 Constructor (java.lang.reflect.Constructor)2 Method (java.lang.reflect.Method)2 Principal (java.security.Principal)2 PrivilegedAction (java.security.PrivilegedAction)2 Arrays (java.util.Arrays)2 Collections (java.util.Collections)2 HashMap (java.util.HashMap)2 Iterator (java.util.Iterator)2 List (java.util.List)2 Map (java.util.Map)2 Optional (java.util.Optional)2 Function (java.util.function.Function)2 Collectors (java.util.stream.Collectors)2 Stream (java.util.stream.Stream)2 StreamSupport (java.util.stream.StreamSupport)2 Subject (javax.security.auth.Subject)2 DynamicContainer (org.junit.jupiter.api.DynamicContainer)2 DynamicNode (org.junit.jupiter.api.DynamicNode)2 DynamicTestInvocationContext (org.junit.jupiter.api.extension.DynamicTestInvocationContext)2