org.testng.internal.MethodInvocationHelper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of testng Show documentation
Show all versions of testng Show documentation
Testing framework for Java
package org.testng.internal; import org.testng.IConfigurable; import org.testng.IConfigureCallBack; import org.testng.IHookCallBack; import org.testng.IHookable; import org.testng.ITestContext; import org.testng.ITestNGMethod; import org.testng.ITestResult; import org.testng.TestNGException; import org.testng.annotations.DataProvider; import org.testng.collections.Lists; import org.testng.internal.annotations.IAnnotationFinder; import org.testng.internal.collections.Pair; import org.testng.internal.thread.IExecutor; import org.testng.internal.thread.IFutureResult; import org.testng.internal.thread.ThreadExecutionException; import org.testng.internal.thread.ThreadTimeoutException; import org.testng.internal.thread.ThreadUtil; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; /** * Collections of helper methods to help deal with invocation of TestNG methods * * @author Cedric Beust
results in an exception */ protected static void invokeHookable(final Object testInstance, final Object[] parameters, final IHookable hookable, final Method thisMethod, final TestResult testResult) throws Throwable { final Throwable[] error = new Throwable[1]; IHookCallBack callback = new IHookCallBack() { @Override public void runTestMethod(ITestResult tr) { try { invokeMethod(thisMethod, testInstance, parameters); } catch (Throwable t) { error[0] = t; tr.setThrowable(t); // make Throwable available to IHookable } } @Override public Object[] getParameters() { return parameters; } }; hookable.run(callback, testResult); if (error[0] != null) { throw error[0]; } } /** * Invokes a method on a separate thread in order to allow us to timeout the * invocation. It uses as implementation an* @author nullin * */ public class MethodInvocationHelper { protected static Object invokeMethod(Method thisMethod, Object instance, Object[] parameters) throws InvocationTargetException, IllegalAccessException { Utils.checkInstanceOrStatic(instance, thisMethod); // TESTNG-326, allow IObjectFactory to load from non-standard classloader // If the instance has a different classloader, its class won't match the // method's class if (instance == null || !thisMethod.getDeclaringClass().isAssignableFrom(instance.getClass())) { // for some reason, we can't call this method on this class // is it static? boolean isStatic = Modifier.isStatic(thisMethod.getModifiers()); if (!isStatic) { // not static, so grab a method with the same name and signature in this case Class> clazz = instance.getClass(); try { thisMethod = clazz.getMethod(thisMethod.getName(), thisMethod.getParameterTypes()); } catch (Exception e) { // ignore, the method may be private boolean found = false; for (; clazz != null; clazz = clazz.getSuperclass()) { try { thisMethod = clazz.getDeclaredMethod(thisMethod.getName(), thisMethod.getParameterTypes()); found = true; break; } catch (Exception e2) { } } if (!found) { // should we assert here? Or just allow it to fail on invocation? if (thisMethod.getDeclaringClass().getName().equals(instance.getClass().getName())) { throw new RuntimeException("Can't invoke method " + thisMethod + ", probably due to classloader mismatch"); } throw new RuntimeException("Can't invoke method " + thisMethod + " on this instance of " + instance.getClass() + " due to class mismatch"); } } } } synchronized(thisMethod) { if (! Modifier.isPublic(thisMethod.getModifiers())) { thisMethod.setAccessible(true); } } return thisMethod.invoke(instance, parameters); } protected static Iterator Executor
and a *CountDownLatch
. */ protected static void invokeWithTimeout(ITestNGMethod tm, Object instance, Object[] parameterValues, ITestResult testResult) throws InterruptedException, ThreadExecutionException { if (ThreadUtil.isTestNGThread()) { // We are already running in our own executor, don't create another one (or we will // lose the time out of the enclosing executor). invokeWithTimeoutWithNoExecutor(tm, instance, parameterValues, testResult); } else { invokeWithTimeoutWithNewExecutor(tm, instance, parameterValues, testResult); } } private static void invokeWithTimeoutWithNoExecutor(ITestNGMethod tm, Object instance, Object[] parameterValues, ITestResult testResult) { InvokeMethodRunnable imr = new InvokeMethodRunnable(tm, instance, parameterValues); try { imr.run(); testResult.setStatus(ITestResult.SUCCESS); } catch (Exception ex) { testResult.setThrowable(ex.getCause()); testResult.setStatus(ITestResult.FAILURE); } } private static void invokeWithTimeoutWithNewExecutor(ITestNGMethod tm, Object instance, Object[] parameterValues, ITestResult testResult) throws InterruptedException, ThreadExecutionException { IExecutor exec = ThreadUtil.createExecutor(1, tm.getMethodName()); InvokeMethodRunnable imr = new InvokeMethodRunnable(tm, instance, parameterValues); IFutureResult future = exec.submitRunnable(imr); exec.shutdown(); long realTimeOut = MethodHelper.calculateTimeOut(tm); boolean finished = exec.awaitTermination(realTimeOut); if (!finished) { exec.stopNow(); ThreadTimeoutException exception = new ThreadTimeoutException("Method " + tm.getClass().getName() + "." + tm.getMethodName() + "()" + " didn't finish within the time-out " + realTimeOut); exception.setStackTrace(exec.getStackTraces()[0]); testResult.setThrowable(exception); testResult.setStatus(ITestResult.FAILURE); } else { Utils.log("Invoker " + Thread.currentThread().hashCode(), 3, "Method " + tm.getMethodName() + " completed within the time-out " + tm.getTimeOut()); // We don't need the result from the future but invoking get() on it // will trigger the exception that was thrown, if any future.get(); // done.await(); testResult.setStatus(ITestResult.SUCCESS); // if no exception till here // than SUCCESS } } protected static void invokeConfigurable(final Object instance, final Object[] parameters, final IConfigurable configurableInstance, final Method thisMethod, final ITestResult testResult) throws Throwable { final Throwable[] error = new Throwable[1]; IConfigureCallBack callback = new IConfigureCallBack() { @Override public void runConfigurationMethod(ITestResult tr) { try { invokeMethod(thisMethod, instance, parameters); } catch (Throwable t) { error[0] = t; tr.setThrowable(t); // make Throwable available to IConfigurable } } @Override public Object[] getParameters() { return parameters; } }; configurableInstance.run(callback, testResult); if (error[0] != null) { throw error[0]; } } }