package org.apereo.cas.util.junit;

import lombok.SneakyThrows;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/**
 * This is {@link ConditionalSpringRunner}.
 *
 * @author Misagh Moayyed
 * @since 5.3.0
 */
public class ConditionalSpringRunner extends SpringJUnit4ClassRunner {
    /**
     * Construct a new {@code SpringJUnit4ClassRunner}.
     *
     * @param clazz the test class to be run
     * @see #createTestContextManager(Class)
     */
    public ConditionalSpringRunner(final Class<?> clazz) throws InitializationError {
        super(clazz);
    }

    @Override
    @SneakyThrows
    protected boolean isTestMethodIgnored(final FrameworkMethod frameworkMethod) {
        ConditionalIgnore ignore = frameworkMethod.getDeclaringClass().getAnnotation(ConditionalIgnore.class);
        if (ignore != null) {
            final IgnoreCondition condition = ignore.condition().getDeclaredConstructor().newInstance();
            return !condition.isSatisfied();
        }
        ignore = frameworkMethod.getAnnotation(ConditionalIgnore.class);
        if (ignore != null) {
            final IgnoreCondition condition = ignore.condition().getDeclaredConstructor().newInstance();
            return !condition.isSatisfied();
        }
        return super.isTestMethodIgnored(frameworkMethod);
    }

    @Override
    @SneakyThrows
    protected Statement withBeforeClasses(final Statement statement) {
        final ConditionalIgnore ignore = getTestClass().getJavaClass().getAnnotation(ConditionalIgnore.class);
        if (ignore != null) {
            final IgnoreCondition condition = ignore.condition().getDeclaredConstructor().newInstance();
            if (!condition.isSatisfied()) {
                return new ConditionalIgnoreRule.IgnoreStatement(condition);
            }
        }
        return super.withBeforeClasses(statement);
    }

    @Override
    @SneakyThrows
    protected Statement withAfterClasses(final Statement statement) {
        final ConditionalIgnore ignore = getTestClass().getJavaClass().getAnnotation(ConditionalIgnore.class);
        if (ignore != null) {
            final IgnoreCondition condition = ignore.condition().getDeclaredConstructor().newInstance();
            if (!condition.isSatisfied()) {
                return new ConditionalIgnoreRule.IgnoreStatement(condition);
            }
        }
        return super.withAfterClasses(statement);
    }
}

@@ -57,16 +57,56 @@
 Throws;%0A
+import org.apereo.cas.util.SocketUtils;%0A
 import o
@@ -145,16 +145,16 @@
 Method;%0A
-
 import o
@@ -1141,33 +1141,41 @@
     return !
-c
+isIgnoreC
 ondition
 .isSatisfied
@@ -1154,35 +1154,32 @@
 sIgnoreCondition
-.is
 Satisfied();%0A   
@@ -1164,32 +1164,49 @@
 ditionSatisfied(
+ignore, condition
 );%0A        %7D%0A   
@@ -1430,25 +1430,33 @@
 return !
-c
+isIgnoreC
 ondition
 .isSatis
@@ -1439,35 +1439,32 @@
 sIgnoreCondition
-.is
 Satisfied();%0A   
@@ -1457,16 +1457,33 @@
 tisfied(
+ignore, condition
 );%0A     
@@ -1915,33 +1915,41 @@
        if (!
-c
+isIgnoreC
 ondition
 .isSatisfied
@@ -1928,35 +1928,32 @@
 sIgnoreCondition
-.is
 Satisfied()) %7B%0A 
@@ -1938,32 +1938,49 @@
 ditionSatisfied(
+ignore, condition
 )) %7B%0A           
@@ -2492,25 +2492,33 @@
    if (!
-c
+isIgnoreC
 ondition
 .isSatis
@@ -2509,19 +2509,16 @@
 ondition
-.is
 Satisfie
@@ -2519,16 +2519,33 @@
 tisfied(
+ignore, condition
 )) %7B%0A   
@@ -2634,32 +2634,32 @@
     %7D%0A        %7D%0A
-
         return s
@@ -2697,11 +2697,347 @@
 );%0A    %7D
+%0A%0A    private boolean isIgnoreConditionSatisfied(final ConditionalIgnore ignore, final IgnoreCondition ignoreCondition) %7B%0A        boolean runTests = ignoreCondition.isSatisfied();%0A        if (runTests && ignore.port() %3E 0) %7B%0A            runTests = !SocketUtils.isTcpPortAvailable(ignore.port());%0A        %7D%0A        return runTests;%0A    %7D
 %0A%7D%0A

clean up conditional tests