1b1c182d51b05a40ac5350e562503a94d024a7c80nullinpackage org.testng.internal; 2b1c182d51b05a40ac5350e562503a94d024a7c80nullin 324e36c535b7d2b03c32562162d8b7d8e4fe5f354Vladislav Rassokhinimport org.testng.IConfigurable; 4b1c182d51b05a40ac5350e562503a94d024a7c80nullinimport org.testng.IConfigureCallBack; 5b1c182d51b05a40ac5350e562503a94d024a7c80nullinimport org.testng.IHookCallBack; 624e36c535b7d2b03c32562162d8b7d8e4fe5f354Vladislav Rassokhinimport org.testng.IHookable; 7b1c182d51b05a40ac5350e562503a94d024a7c80nullinimport org.testng.ITestContext; 8b1c182d51b05a40ac5350e562503a94d024a7c80nullinimport org.testng.ITestNGMethod; 9b1c182d51b05a40ac5350e562503a94d024a7c80nullinimport org.testng.ITestResult; 10b1c182d51b05a40ac5350e562503a94d024a7c80nullinimport org.testng.TestNGException; 11ed9cafaaad9cf9da7940ad1da9437f27cb85438dCédric Beustimport org.testng.annotations.DataProvider; 12b1c182d51b05a40ac5350e562503a94d024a7c80nullinimport org.testng.collections.Lists; 13b1c182d51b05a40ac5350e562503a94d024a7c80nullinimport org.testng.internal.annotations.IAnnotationFinder; 142a4d14e870d4cf6b6e4800ffd72c7d46deefc473Vladislav Rassokhinimport org.testng.internal.collections.Pair; 15b1c182d51b05a40ac5350e562503a94d024a7c80nullinimport org.testng.internal.thread.IExecutor; 16b1c182d51b05a40ac5350e562503a94d024a7c80nullinimport org.testng.internal.thread.IFutureResult; 17b1c182d51b05a40ac5350e562503a94d024a7c80nullinimport org.testng.internal.thread.ThreadExecutionException; 18b1c182d51b05a40ac5350e562503a94d024a7c80nullinimport org.testng.internal.thread.ThreadTimeoutException; 19b1c182d51b05a40ac5350e562503a94d024a7c80nullinimport org.testng.internal.thread.ThreadUtil; 202c23fd8d5624a9c06eee5e06721b79d96c421fe5Julien Herrimport org.testng.xml.XmlSuite; 21b1c182d51b05a40ac5350e562503a94d024a7c80nullin 222a4d14e870d4cf6b6e4800ffd72c7d46deefc473Vladislav Rassokhinimport java.lang.reflect.Constructor; 23b1c182d51b05a40ac5350e562503a94d024a7c80nullinimport java.lang.reflect.InvocationTargetException; 24b1c182d51b05a40ac5350e562503a94d024a7c80nullinimport java.lang.reflect.Method; 25b1c182d51b05a40ac5350e562503a94d024a7c80nullinimport java.lang.reflect.Modifier; 262a4d14e870d4cf6b6e4800ffd72c7d46deefc473Vladislav Rassokhinimport java.util.ArrayList; 272a4d14e870d4cf6b6e4800ffd72c7d46deefc473Vladislav Rassokhinimport java.util.Collection; 28b1c182d51b05a40ac5350e562503a94d024a7c80nullinimport java.util.Iterator; 29b1c182d51b05a40ac5350e562503a94d024a7c80nullinimport java.util.List; 30b1c182d51b05a40ac5350e562503a94d024a7c80nullin 31b1c182d51b05a40ac5350e562503a94d024a7c80nullin/** 32b1c182d51b05a40ac5350e562503a94d024a7c80nullin * Collections of helper methods to help deal with invocation of TestNG methods 330f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin * 340f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin * @author Cedric Beust <cedric@beust.com> 350f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin * @author nullin <nalin.makar * gmail.com> 36b1c182d51b05a40ac5350e562503a94d024a7c80nullin * 37b1c182d51b05a40ac5350e562503a94d024a7c80nullin */ 38b1c182d51b05a40ac5350e562503a94d024a7c80nullinpublic class MethodInvocationHelper { 39b1c182d51b05a40ac5350e562503a94d024a7c80nullin 40b1c182d51b05a40ac5350e562503a94d024a7c80nullin protected static Object invokeMethod(Method thisMethod, Object instance, Object[] parameters) 4130b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust throws InvocationTargetException, IllegalAccessException { 424438e4fa82ea3d7d8623d11156657d119cddaa14Cédric Beust Utils.checkInstanceOrStatic(instance, thisMethod); 434438e4fa82ea3d7d8623d11156657d119cddaa14Cédric Beust 44b1c182d51b05a40ac5350e562503a94d024a7c80nullin // TESTNG-326, allow IObjectFactory to load from non-standard classloader 4530b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust // If the instance has a different classloader, its class won't match the 4630b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust // method's class 474438e4fa82ea3d7d8623d11156657d119cddaa14Cédric Beust if (instance == null || !thisMethod.getDeclaringClass().isAssignableFrom(instance.getClass())) { 48b1c182d51b05a40ac5350e562503a94d024a7c80nullin // for some reason, we can't call this method on this class 49b1c182d51b05a40ac5350e562503a94d024a7c80nullin // is it static? 50b1c182d51b05a40ac5350e562503a94d024a7c80nullin boolean isStatic = Modifier.isStatic(thisMethod.getModifiers()); 51b1c182d51b05a40ac5350e562503a94d024a7c80nullin if (!isStatic) { 52b1c182d51b05a40ac5350e562503a94d024a7c80nullin // not static, so grab a method with the same name and signature in this case 53b1c182d51b05a40ac5350e562503a94d024a7c80nullin Class<?> clazz = instance.getClass(); 54b1c182d51b05a40ac5350e562503a94d024a7c80nullin try { 55b1c182d51b05a40ac5350e562503a94d024a7c80nullin thisMethod = clazz.getMethod(thisMethod.getName(), thisMethod.getParameterTypes()); 56b1c182d51b05a40ac5350e562503a94d024a7c80nullin } catch (Exception e) { 57b1c182d51b05a40ac5350e562503a94d024a7c80nullin // ignore, the method may be private 58b1c182d51b05a40ac5350e562503a94d024a7c80nullin boolean found = false; 59b1c182d51b05a40ac5350e562503a94d024a7c80nullin for (; clazz != null; clazz = clazz.getSuperclass()) { 60b1c182d51b05a40ac5350e562503a94d024a7c80nullin try { 6130b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust thisMethod = clazz.getDeclaredMethod(thisMethod.getName(), 6230b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust thisMethod.getParameterTypes()); 63b1c182d51b05a40ac5350e562503a94d024a7c80nullin found = true; 64b1c182d51b05a40ac5350e562503a94d024a7c80nullin break; 6530b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust } catch (Exception e2) { 6630b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust } 67b1c182d51b05a40ac5350e562503a94d024a7c80nullin } 68b1c182d51b05a40ac5350e562503a94d024a7c80nullin if (!found) { 6930b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust // should we assert here? Or just allow it to fail on invocation? 70b1c182d51b05a40ac5350e562503a94d024a7c80nullin if (thisMethod.getDeclaringClass().getName().equals(instance.getClass().getName())) { 7130b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust throw new RuntimeException("Can't invoke method " + thisMethod 7230b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust + ", probably due to classloader mismatch"); 73b1c182d51b05a40ac5350e562503a94d024a7c80nullin } 7430b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust throw new RuntimeException("Can't invoke method " + thisMethod 7530b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust + " on this instance of " + instance.getClass() + " due to class mismatch"); 76b1c182d51b05a40ac5350e562503a94d024a7c80nullin } 77b1c182d51b05a40ac5350e562503a94d024a7c80nullin } 78b1c182d51b05a40ac5350e562503a94d024a7c80nullin } 79b1c182d51b05a40ac5350e562503a94d024a7c80nullin } 800f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin 8161a0a8a2e056dd41e02efdef372de49d2996b67aCédric Beust synchronized(thisMethod) { 8261a0a8a2e056dd41e02efdef372de49d2996b67aCédric Beust if (! Modifier.isPublic(thisMethod.getModifiers())) { 83b1c182d51b05a40ac5350e562503a94d024a7c80nullin thisMethod.setAccessible(true); 84b1c182d51b05a40ac5350e562503a94d024a7c80nullin } 85b1c182d51b05a40ac5350e562503a94d024a7c80nullin } 8661a0a8a2e056dd41e02efdef372de49d2996b67aCédric Beust return thisMethod.invoke(instance, parameters); 87b1c182d51b05a40ac5350e562503a94d024a7c80nullin } 88b1c182d51b05a40ac5350e562503a94d024a7c80nullin 8930b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust protected static Iterator<Object[]> invokeDataProvider(Object instance, Method dataProvider, 9030b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust ITestNGMethod method, ITestContext testContext, Object fedInstance, 9130b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust IAnnotationFinder annotationFinder) { 9224e36c535b7d2b03c32562162d8b7d8e4fe5f354Vladislav Rassokhin Iterator<Object[]> result; 932a4d14e870d4cf6b6e4800ffd72c7d46deefc473Vladislav Rassokhin final ConstructorOrMethod com = method.getConstructorOrMethod(); 940f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin 95b1c182d51b05a40ac5350e562503a94d024a7c80nullin // If it returns an Object[][], convert it to an Iterable<Object[]> 96b1c182d51b05a40ac5350e562503a94d024a7c80nullin try { 97b1c182d51b05a40ac5350e562503a94d024a7c80nullin List<Object> lParameters = Lists.newArrayList(); 980f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin 99b1c182d51b05a40ac5350e562503a94d024a7c80nullin // Go through all the parameters declared on this Data Provider and 100b1c182d51b05a40ac5350e562503a94d024a7c80nullin // make sure we have at most one Method and one ITestContext. 101b1c182d51b05a40ac5350e562503a94d024a7c80nullin // Anything else is an error 102b1c182d51b05a40ac5350e562503a94d024a7c80nullin Class<?>[] parameterTypes = dataProvider.getParameterTypes(); 1030f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin 10410c223b7aa6bf34778079bb5ee1a494c83cd1239Ryan Schmitt final Collection<Pair<Integer, Class<?>>> unresolved = new ArrayList<>(parameterTypes.length); 105b1c182d51b05a40ac5350e562503a94d024a7c80nullin int i = 0; 106b1c182d51b05a40ac5350e562503a94d024a7c80nullin for (Class<?> cls : parameterTypes) { 107b1c182d51b05a40ac5350e562503a94d024a7c80nullin boolean isTestInstance = annotationFinder.hasTestInstance(dataProvider, i++); 108b1c182d51b05a40ac5350e562503a94d024a7c80nullin if (cls.equals(Method.class)) { 1092a4d14e870d4cf6b6e4800ffd72c7d46deefc473Vladislav Rassokhin lParameters.add(com.getMethod()); 1102a4d14e870d4cf6b6e4800ffd72c7d46deefc473Vladislav Rassokhin } else if (cls.equals(Constructor.class)) { 1112a4d14e870d4cf6b6e4800ffd72c7d46deefc473Vladislav Rassokhin lParameters.add(com.getConstructor()); 1122a4d14e870d4cf6b6e4800ffd72c7d46deefc473Vladislav Rassokhin } else if (cls.equals(ConstructorOrMethod.class)) { 1132a4d14e870d4cf6b6e4800ffd72c7d46deefc473Vladislav Rassokhin lParameters.add(com); 1142a4d14e870d4cf6b6e4800ffd72c7d46deefc473Vladislav Rassokhin } else if (cls.equals(ITestNGMethod.class)) { 1152a4d14e870d4cf6b6e4800ffd72c7d46deefc473Vladislav Rassokhin lParameters.add(method); 11630b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust } else if (cls.equals(ITestContext.class)) { 117b1c182d51b05a40ac5350e562503a94d024a7c80nullin lParameters.add(testContext); 11830b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust } else if (isTestInstance) { 119b1c182d51b05a40ac5350e562503a94d024a7c80nullin lParameters.add(fedInstance); 1202a4d14e870d4cf6b6e4800ffd72c7d46deefc473Vladislav Rassokhin } else { 1212a4d14e870d4cf6b6e4800ffd72c7d46deefc473Vladislav Rassokhin unresolved.add(new Pair<Integer, Class<?>>(i, cls)); 1222a4d14e870d4cf6b6e4800ffd72c7d46deefc473Vladislav Rassokhin } 1232a4d14e870d4cf6b6e4800ffd72c7d46deefc473Vladislav Rassokhin } 1242a4d14e870d4cf6b6e4800ffd72c7d46deefc473Vladislav Rassokhin if (!unresolved.isEmpty()) { 1252a4d14e870d4cf6b6e4800ffd72c7d46deefc473Vladislav Rassokhin final StringBuilder sb = new StringBuilder(); 1262a4d14e870d4cf6b6e4800ffd72c7d46deefc473Vladislav Rassokhin sb.append("Some DataProvider ").append(dataProvider).append(" parameters unresolved: "); 1272a4d14e870d4cf6b6e4800ffd72c7d46deefc473Vladislav Rassokhin for (Pair<Integer, Class<?>> pair : unresolved) { 1282a4d14e870d4cf6b6e4800ffd72c7d46deefc473Vladislav Rassokhin sb.append(" at ").append(pair.first()).append(" type ").append(pair.second()).append("\n"); 129b1c182d51b05a40ac5350e562503a94d024a7c80nullin } 1302a4d14e870d4cf6b6e4800ffd72c7d46deefc473Vladislav Rassokhin throw new TestNGException(sb.toString()); 131b1c182d51b05a40ac5350e562503a94d024a7c80nullin } 1322a4d14e870d4cf6b6e4800ffd72c7d46deefc473Vladislav Rassokhin 133b1c182d51b05a40ac5350e562503a94d024a7c80nullin Object[] parameters = lParameters.toArray(new Object[lParameters.size()]); 1340f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin 13530b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust Class<?> returnType = dataProvider.getReturnType(); 136b1c182d51b05a40ac5350e562503a94d024a7c80nullin if (Object[][].class.isAssignableFrom(returnType)) { 137ed9cafaaad9cf9da7940ad1da9437f27cb85438dCédric Beust Object[][] originalResult = (Object[][]) invokeMethod(dataProvider, instance, parameters); 138ed9cafaaad9cf9da7940ad1da9437f27cb85438dCédric Beust 139ed9cafaaad9cf9da7940ad1da9437f27cb85438dCédric Beust // If the data provider is restricting the indices to return, filter them out 140ed9cafaaad9cf9da7940ad1da9437f27cb85438dCédric Beust int[] indices = dataProvider.getAnnotation(DataProvider.class).indices(); 141ed9cafaaad9cf9da7940ad1da9437f27cb85438dCédric Beust Object[][] oResult; 142ed9cafaaad9cf9da7940ad1da9437f27cb85438dCédric Beust if (indices.length > 0) { 143ed9cafaaad9cf9da7940ad1da9437f27cb85438dCédric Beust oResult = new Object[indices.length][]; 144ed9cafaaad9cf9da7940ad1da9437f27cb85438dCédric Beust for (int j = 0; j < indices.length; j++) { 145ed9cafaaad9cf9da7940ad1da9437f27cb85438dCédric Beust oResult[j] = originalResult[indices[j]]; 146ed9cafaaad9cf9da7940ad1da9437f27cb85438dCédric Beust } 147ed9cafaaad9cf9da7940ad1da9437f27cb85438dCédric Beust } else { 148ed9cafaaad9cf9da7940ad1da9437f27cb85438dCédric Beust oResult = originalResult; 149ed9cafaaad9cf9da7940ad1da9437f27cb85438dCédric Beust } 150ed9cafaaad9cf9da7940ad1da9437f27cb85438dCédric Beust 151b1c182d51b05a40ac5350e562503a94d024a7c80nullin method.setParameterInvocationCount(oResult.length); 152b1c182d51b05a40ac5350e562503a94d024a7c80nullin result = MethodHelper.createArrayIterator(oResult); 15330b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust } else if (Iterator.class.isAssignableFrom(returnType)) { 15424e36c535b7d2b03c32562162d8b7d8e4fe5f354Vladislav Rassokhin // Already an Iterator<Object[]>, assign it directly 15530b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust result = (Iterator<Object[]>) invokeMethod(dataProvider, instance, parameters); 15630b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust } else { 15730b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust throw new TestNGException("Data Provider " + dataProvider + " must return" 15830b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust + " either Object[][] or Iterator<Object>[], not " + returnType); 159b1c182d51b05a40ac5350e562503a94d024a7c80nullin } 160a3f78c5debcd03e7755f5ff2956a6f325e41d0b7Ryan Schmitt } catch (InvocationTargetException | IllegalAccessException e) { 16130b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust // Don't throw TestNGException here or this test won't be reported as a 16230b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust // skip or failure 163f5fc1732fe39aae26224f00a23273fe3e9929398Cédric Beust throw new RuntimeException(e.getCause()); 164b1c182d51b05a40ac5350e562503a94d024a7c80nullin } 1650f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin 166b1c182d51b05a40ac5350e562503a94d024a7c80nullin return result; 167b1c182d51b05a40ac5350e562503a94d024a7c80nullin } 168b1c182d51b05a40ac5350e562503a94d024a7c80nullin 169b1c182d51b05a40ac5350e562503a94d024a7c80nullin /** 170b1c182d51b05a40ac5350e562503a94d024a7c80nullin * Invokes the <code>run</code> method of the <code>IHookable</code>. 171b1c182d51b05a40ac5350e562503a94d024a7c80nullin * 17230b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust * @param testInstance 17330b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust * the instance to invoke the method in 17430b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust * @param parameters 17530b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust * the parameters to be passed to <code>IHookCallBack</code> 17630b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust * @param thisMethod 17730b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust * the method to be invoked through the <code>IHookCallBack</code> 17830b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust * @param testResult 17930b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust * the current <code>ITestResult</code> passed to 18030b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust * <code>IHookable.run</code> 181b1c182d51b05a40ac5350e562503a94d024a7c80nullin * @throws NoSuchMethodException 182b1c182d51b05a40ac5350e562503a94d024a7c80nullin * @throws IllegalAccessException 183b1c182d51b05a40ac5350e562503a94d024a7c80nullin * @throws InvocationTargetException 18430b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust * @throws Throwable 18530b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust * thrown if the reflective call to 18630b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust * <tt>thisMethod</code> results in an exception 187b1c182d51b05a40ac5350e562503a94d024a7c80nullin */ 18830b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust protected static void invokeHookable(final Object testInstance, final Object[] parameters, 18924e36c535b7d2b03c32562162d8b7d8e4fe5f354Vladislav Rassokhin final IHookable hookable, final Method thisMethod, 1908e84be5f48c104aa57cd9de8db3dd4d7a676040cJulien Herr final ITestResult testResult) throws Throwable { 191b1c182d51b05a40ac5350e562503a94d024a7c80nullin final Throwable[] error = new Throwable[1]; 1920f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin 193b1c182d51b05a40ac5350e562503a94d024a7c80nullin IHookCallBack callback = new IHookCallBack() { 194b1c182d51b05a40ac5350e562503a94d024a7c80nullin @Override 195b1c182d51b05a40ac5350e562503a94d024a7c80nullin public void runTestMethod(ITestResult tr) { 196b1c182d51b05a40ac5350e562503a94d024a7c80nullin try { 197b1c182d51b05a40ac5350e562503a94d024a7c80nullin invokeMethod(thisMethod, testInstance, parameters); 19830b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust } catch (Throwable t) { 19930b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust error[0] = t; 20030b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust tr.setThrowable(t); // make Throwable available to IHookable 20130b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust } 20230b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust } 2030f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin 204b1c182d51b05a40ac5350e562503a94d024a7c80nullin @Override 205b1c182d51b05a40ac5350e562503a94d024a7c80nullin public Object[] getParameters() { 206b1c182d51b05a40ac5350e562503a94d024a7c80nullin return parameters; 207b1c182d51b05a40ac5350e562503a94d024a7c80nullin } 208b1c182d51b05a40ac5350e562503a94d024a7c80nullin }; 20924e36c535b7d2b03c32562162d8b7d8e4fe5f354Vladislav Rassokhin hookable.run(callback, testResult); 210b1c182d51b05a40ac5350e562503a94d024a7c80nullin if (error[0] != null) { 211b1c182d51b05a40ac5350e562503a94d024a7c80nullin throw error[0]; 212b1c182d51b05a40ac5350e562503a94d024a7c80nullin } 213b1c182d51b05a40ac5350e562503a94d024a7c80nullin } 214b1c182d51b05a40ac5350e562503a94d024a7c80nullin 215b1c182d51b05a40ac5350e562503a94d024a7c80nullin /** 21630b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust * Invokes a method on a separate thread in order to allow us to timeout the 21730b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust * invocation. It uses as implementation an <code>Executor</code> and a 21830b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust * <code>CountDownLatch</code>. 21930b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust */ 22030b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust protected static void invokeWithTimeout(ITestNGMethod tm, Object instance, 22130b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust Object[] parameterValues, ITestResult testResult) 22230b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust throws InterruptedException, ThreadExecutionException { 2238e84be5f48c104aa57cd9de8db3dd4d7a676040cJulien Herr invokeWithTimeout(tm, instance, parameterValues, testResult, null); 2248e84be5f48c104aa57cd9de8db3dd4d7a676040cJulien Herr } 2258e84be5f48c104aa57cd9de8db3dd4d7a676040cJulien Herr 2268e84be5f48c104aa57cd9de8db3dd4d7a676040cJulien Herr protected static void invokeWithTimeout(ITestNGMethod tm, Object instance, 2278e84be5f48c104aa57cd9de8db3dd4d7a676040cJulien Herr Object[] parameterValues, ITestResult testResult, IHookable hookable) 2288e84be5f48c104aa57cd9de8db3dd4d7a676040cJulien Herr throws InterruptedException, ThreadExecutionException { 2292c23fd8d5624a9c06eee5e06721b79d96c421fe5Julien Herr if (ThreadUtil.isTestNGThread() && testResult.getTestContext().getCurrentXmlTest().getParallel() != XmlSuite.ParallelMode.TESTS) { 23030b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust // We are already running in our own executor, don't create another one (or we will 23130b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust // lose the time out of the enclosing executor). 2328e84be5f48c104aa57cd9de8db3dd4d7a676040cJulien Herr invokeWithTimeoutWithNoExecutor(tm, instance, parameterValues, testResult, hookable); 23330b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust } else { 2348e84be5f48c104aa57cd9de8db3dd4d7a676040cJulien Herr invokeWithTimeoutWithNewExecutor(tm, instance, parameterValues, testResult, hookable); 235349a0501482e3fada78e74a70eea8b8585bca308Cédric Beust } 23630b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust } 2370f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin 23830b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust private static void invokeWithTimeoutWithNoExecutor(ITestNGMethod tm, Object instance, 2398e84be5f48c104aa57cd9de8db3dd4d7a676040cJulien Herr Object[] parameterValues, ITestResult testResult, IHookable hookable) { 2400f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin 2418e84be5f48c104aa57cd9de8db3dd4d7a676040cJulien Herr InvokeMethodRunnable imr = new InvokeMethodRunnable(tm, instance, parameterValues, hookable, testResult); 242349a0501482e3fada78e74a70eea8b8585bca308Cédric Beust try { 243349a0501482e3fada78e74a70eea8b8585bca308Cédric Beust imr.run(); 244349a0501482e3fada78e74a70eea8b8585bca308Cédric Beust testResult.setStatus(ITestResult.SUCCESS); 24530b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust } catch (Exception ex) { 246349a0501482e3fada78e74a70eea8b8585bca308Cédric Beust testResult.setThrowable(ex.getCause()); 247349a0501482e3fada78e74a70eea8b8585bca308Cédric Beust testResult.setStatus(ITestResult.FAILURE); 248349a0501482e3fada78e74a70eea8b8585bca308Cédric Beust } 249349a0501482e3fada78e74a70eea8b8585bca308Cédric Beust } 250349a0501482e3fada78e74a70eea8b8585bca308Cédric Beust 25130b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust private static void invokeWithTimeoutWithNewExecutor(ITestNGMethod tm, Object instance, 2528e84be5f48c104aa57cd9de8db3dd4d7a676040cJulien Herr Object[] parameterValues, ITestResult testResult, IHookable hookable) 253349a0501482e3fada78e74a70eea8b8585bca308Cédric Beust throws InterruptedException, ThreadExecutionException { 25424e36c535b7d2b03c32562162d8b7d8e4fe5f354Vladislav Rassokhin IExecutor exec = ThreadUtil.createExecutor(1, tm.getMethodName()); 255349a0501482e3fada78e74a70eea8b8585bca308Cédric Beust 2568e84be5f48c104aa57cd9de8db3dd4d7a676040cJulien Herr InvokeMethodRunnable imr = new InvokeMethodRunnable(tm, instance, parameterValues, hookable, testResult); 257349a0501482e3fada78e74a70eea8b8585bca308Cédric Beust IFutureResult future = exec.submitRunnable(imr); 258349a0501482e3fada78e74a70eea8b8585bca308Cédric Beust exec.shutdown(); 259349a0501482e3fada78e74a70eea8b8585bca308Cédric Beust long realTimeOut = MethodHelper.calculateTimeOut(tm); 260349a0501482e3fada78e74a70eea8b8585bca308Cédric Beust boolean finished = exec.awaitTermination(realTimeOut); 261349a0501482e3fada78e74a70eea8b8585bca308Cédric Beust 26230b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust if (!finished) { 263349a0501482e3fada78e74a70eea8b8585bca308Cédric Beust exec.stopNow(); 264349a0501482e3fada78e74a70eea8b8585bca308Cédric Beust ThreadTimeoutException exception = new ThreadTimeoutException("Method " 26530b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust + tm.getClass().getName() + "." + tm.getMethodName() + "()" 26630b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust + " didn't finish within the time-out " + realTimeOut); 267349a0501482e3fada78e74a70eea8b8585bca308Cédric Beust exception.setStackTrace(exec.getStackTraces()[0]); 268349a0501482e3fada78e74a70eea8b8585bca308Cédric Beust testResult.setThrowable(exception); 269349a0501482e3fada78e74a70eea8b8585bca308Cédric Beust testResult.setStatus(ITestResult.FAILURE); 27030b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust } else { 27124e36c535b7d2b03c32562162d8b7d8e4fe5f354Vladislav Rassokhin Utils.log("Invoker " + Thread.currentThread().hashCode(), 3, "Method " + tm.getMethodName() 27230b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust + " completed within the time-out " + tm.getTimeOut()); 273349a0501482e3fada78e74a70eea8b8585bca308Cédric Beust 274349a0501482e3fada78e74a70eea8b8585bca308Cédric Beust // We don't need the result from the future but invoking get() on it 275349a0501482e3fada78e74a70eea8b8585bca308Cédric Beust // will trigger the exception that was thrown, if any 276349a0501482e3fada78e74a70eea8b8585bca308Cédric Beust future.get(); 27730b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust // done.await(); 278349a0501482e3fada78e74a70eea8b8585bca308Cédric Beust 27930b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust testResult.setStatus(ITestResult.SUCCESS); // if no exception till here 28030b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust // than SUCCESS 281349a0501482e3fada78e74a70eea8b8585bca308Cédric Beust } 282349a0501482e3fada78e74a70eea8b8585bca308Cédric Beust } 283b1c182d51b05a40ac5350e562503a94d024a7c80nullin 28430b5dbacace7283ae6ee0bc2af4ecd647eca75f7Cédric Beust protected static void invokeConfigurable(final Object instance, final Object[] parameters, 28524e36c535b7d2b03c32562162d8b7d8e4fe5f354Vladislav Rassokhin final IConfigurable configurableInstance, final Method thisMethod, 28624e36c535b7d2b03c32562162d8b7d8e4fe5f354Vladislav Rassokhin final ITestResult testResult) throws Throwable { 287b1c182d51b05a40ac5350e562503a94d024a7c80nullin final Throwable[] error = new Throwable[1]; 2880f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin 289b1c182d51b05a40ac5350e562503a94d024a7c80nullin IConfigureCallBack callback = new IConfigureCallBack() { 290b1c182d51b05a40ac5350e562503a94d024a7c80nullin @Override 291b1c182d51b05a40ac5350e562503a94d024a7c80nullin public void runConfigurationMethod(ITestResult tr) { 292b1c182d51b05a40ac5350e562503a94d024a7c80nullin try { 293b1c182d51b05a40ac5350e562503a94d024a7c80nullin invokeMethod(thisMethod, instance, parameters); 294b1c182d51b05a40ac5350e562503a94d024a7c80nullin } catch (Throwable t) { 295b1c182d51b05a40ac5350e562503a94d024a7c80nullin error[0] = t; 296b1c182d51b05a40ac5350e562503a94d024a7c80nullin tr.setThrowable(t); // make Throwable available to IConfigurable 297b1c182d51b05a40ac5350e562503a94d024a7c80nullin } 298b1c182d51b05a40ac5350e562503a94d024a7c80nullin } 2990f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin 300b1c182d51b05a40ac5350e562503a94d024a7c80nullin @Override 301b1c182d51b05a40ac5350e562503a94d024a7c80nullin public Object[] getParameters() { 302b1c182d51b05a40ac5350e562503a94d024a7c80nullin return parameters; 303b1c182d51b05a40ac5350e562503a94d024a7c80nullin } 304b1c182d51b05a40ac5350e562503a94d024a7c80nullin }; 30524e36c535b7d2b03c32562162d8b7d8e4fe5f354Vladislav Rassokhin configurableInstance.run(callback, testResult); 306b1c182d51b05a40ac5350e562503a94d024a7c80nullin if (error[0] != null) { 307b1c182d51b05a40ac5350e562503a94d024a7c80nullin throw error[0]; 308b1c182d51b05a40ac5350e562503a94d024a7c80nullin } 309b1c182d51b05a40ac5350e562503a94d024a7c80nullin } 310b1c182d51b05a40ac5350e562503a94d024a7c80nullin 31124e36c535b7d2b03c32562162d8b7d8e4fe5f354Vladislav Rassokhin} 312