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

com.zebrunner.agent.junit.IsIgnoreInterceptor Maven / Gradle / Ivy

package com.zebrunner.agent.junit;

import com.zebrunner.agent.core.listener.RerunListener;
import com.zebrunner.agent.core.registrar.domain.TestDTO;
import com.zebrunner.agent.junit.core.ArgumentsIndexResolver;
import com.zebrunner.agent.junit.core.RunContextService;
import com.zebrunner.agent.junit.core.TestCorrelationData;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.implementation.bind.annotation.Argument;
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
import net.bytebuddy.implementation.bind.annotation.SuperCall;
import net.bytebuddy.implementation.bind.annotation.This;
import org.junit.runner.Description;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;

@Slf4j
public class IsIgnoreInterceptor implements RerunListener {

    @Override
    public void onRerun(List tests) {
        for (TestDTO test : tests) {
            TestCorrelationData testCorrelationData = TestCorrelationData.fromJsonString(test.getCorrelationData());

            RunContextService.addTestCorrelationData(testCorrelationData, test.getId());
        }
    }

    // BlockJUnit4ClassRunner -> protected boolean isIgnored(FrameworkMethod child)
    @RuntimeType
    public static Boolean isIgnore(@This final BlockJUnit4ClassRunner runner,
                                   @SuperCall final Callable proxy,
                                   @Argument(0) FrameworkMethod child) throws Exception {
        boolean isIgnored = proxy.call();
        if (isIgnored) {
            return true;
        }

        // BlockJUnit4ClassRunner -> protected Description describeChild(FrameworkMethod method)
        Description testDescription = invokeMethod(runner, "describeChild", child);
        if (testDescription == null) {
            log.warn(
                    "Unable to build test description from method: {}.\n" +
                    "Check that provided version of JUnit is compatible with Zebrunner agent.\n" +
                    "Test will be automatically ignored for rerun.",
                    child
            );
            return true;
        }

        int argumentsIndex = ArgumentsIndexResolver.resolve(testDescription);
        return !RunContextService.isEligibleForRerun(child, argumentsIndex);
    }

    /**
     * Invoked method by name from class or superclass hierarchy (if method is not exists).
     */
    private static  R invokeMethod(Object fromInstance, String methodName, Object... parameters) {
        R result = null;
        Method method = findMethodByName(fromInstance.getClass(), methodName, parameters);
        if (method != null) {
            result = invokeMethod(fromInstance, method, parameters);
        }
        return result;
    }

    private static  R invokeMethod(Object target, Method method, Object... parameters) {
        R result = null;
        try {
            method.setAccessible(true);
            result = (R) method.invoke(target, parameters);
        } catch (IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * find declared method by name in class and superclasses.
     */
    private static Method findMethodByName(Class klass, String methodName, Object... parameterTypes) {
        Class[] parameterTypeClasses = Arrays.stream(parameterTypes)
                                                .map(Object::getClass)
                                                .toArray(Class[]::new);
        Method method;
        method = findDeclaredMethod(klass, methodName, parameterTypeClasses);
        while (method == null && klass.getSuperclass() != null) {
            klass = klass.getSuperclass();
            method = findDeclaredMethod(klass, methodName, parameterTypeClasses);
        }
        return method;
    }

    /**
     * Find declared method by name in class.
     */
    private static Method findDeclaredMethod(Class klass, String methodName, Class... parameterTypes) {
        Method[] methods = klass.getDeclaredMethods();
        return Arrays.stream(methods)
                     .filter(m -> m.getName().equals(methodName) && parametersFromTypes(m, parameterTypes))
                     .findFirst()
                     .orElse(null);
    }

    private static boolean parametersFromTypes(Method methodWithParameters, Class... parametersToCompare) {
        for (int i = 0; i < methodWithParameters.getParameters().length; i++) {
            Class parameterType = methodWithParameters.getParameters()[i].getType();
            if (!parameterType.isAssignableFrom(parametersToCompare[i])) {
                return false;
            }
        }
        return true;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy