Invoker.java revision 28e899a6c1620c8d07cb04a92f96658550e4af16
1f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustpackage org.testng.internal;
2f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
3f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
4f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.IClass;
50bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beustimport org.testng.IConfigurable;
6f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.IHookable;
7398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beustimport org.testng.IInvokedMethod;
838ef90d96ee65073c1090455e7caff2a85d654e2Cédric Beustimport org.testng.IInvokedMethodListener;
968f450416a61dbdd31ba55933fe10d2b022c3908Cédric Beustimport org.testng.IInvokedMethodListener2;
10f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.IRetryAnalyzer;
11f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.ITestClass;
12f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.ITestContext;
13f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.ITestListener;
14f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.ITestNGMethod;
15f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.ITestResult;
16f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.Reporter;
17f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.SkipException;
18f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.SuiteRunState;
19f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.TestException;
20f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.TestNGException;
212d568355761a9632bf24a87984e241f8a079d724Cédric Beustimport org.testng.annotations.IConfigurationAnnotation;
22aba3ac2f9fc3e370339b911598f62c7ffb6752aaCédric Beustimport org.testng.annotations.NoInjection;
23ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beustimport org.testng.collections.Lists;
240f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beustimport org.testng.collections.Maps;
25f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.internal.InvokeMethodRunnable.TestNGRuntimeException;
26f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.internal.annotations.AnnotationHelper;
27f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.internal.annotations.IAnnotationFinder;
28f035a01bd8ac47425984d6b9e07a733f3abb3c37nullinimport org.testng.internal.annotations.Sets;
29f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.internal.thread.ThreadExecutionException;
30f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.internal.thread.ThreadUtil;
31f035a01bd8ac47425984d6b9e07a733f3abb3c37nullinimport org.testng.internal.thread.graph.IWorker;
32f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.xml.XmlClass;
33f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.xml.XmlSuite;
34f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.xml.XmlTest;
35f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
36423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beustimport java.lang.annotation.Annotation;
37423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beustimport java.lang.reflect.InvocationTargetException;
38423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beustimport java.lang.reflect.Method;
39423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beustimport java.util.Iterator;
40423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beustimport java.util.List;
41423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beustimport java.util.Map;
42423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beustimport java.util.Set;
43423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beustimport java.util.regex.Pattern;
44423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust
45f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust/**
46f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust * This class is responsible for invoking methods:
47f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust * - test methods
48f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust * - configuration methods
49f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust * - possibly in a separate thread
50f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust * and then for notifying the result listeners.
51f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust *
52f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust * @author <a href="mailto:cedric@beust.com">Cedric Beust</a>
53f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust * @author <a href='mailto:the_mindstorm@evolva.ro'>Alexandru Popescu</a>
54f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust */
55f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustpublic class Invoker implements IInvoker {
5621dad3370294d6595fdddc3faf55792f60a913f1nullin  private final ITestContext m_testContext;
5721dad3370294d6595fdddc3faf55792f60a913f1nullin  private final ITestResultNotifier m_notifier;
5821dad3370294d6595fdddc3faf55792f60a913f1nullin  private final IAnnotationFinder m_annotationFinder;
5921dad3370294d6595fdddc3faf55792f60a913f1nullin  private final SuiteRunState m_suiteState;
606cf2e96a6b18fe7eecc44cac44bb0690a162f416Cédric Beust  private boolean m_skipFailedInvocationCounts;
6121dad3370294d6595fdddc3faf55792f60a913f1nullin  private final List<IInvokedMethodListener> m_invokedMethodListeners;
6262a82c6aa5725c9e9d600af5ee06a5852100208cnullin  private boolean m_continueOnFailedConfiguration;
6389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
6421dad3370294d6595fdddc3faf55792f60a913f1nullin  /** Group failures must be synced as the Invoker is accessed concurrently */
65423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust  private Map<String, Boolean> m_beforegroupsFailures = Maps.newHashtable();
6689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
6721dad3370294d6595fdddc3faf55792f60a913f1nullin  /** Class failures must be synced as the Invoker is accessed concurrently */
68f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin  private Map<Class<?>, Set<Object>> m_classInvocationResults = Maps.newHashtable();
6989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
7062a82c6aa5725c9e9d600af5ee06a5852100208cnullin  /** Test methods whose configuration methods have failed. */
71f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin  private Map<ITestNGMethod, Set<Object>> m_methodInvocationResults = Maps.newHashtable();
723297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust  private IConfiguration m_configuration;
7389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
74423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust  private void setClassInvocationFailure(Class<?> clazz, Object instance) {
75f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin    Set<Object> instances = m_classInvocationResults.get( clazz );
76423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust    if (instances == null) {
77f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin      instances = Sets.newHashSet();
78423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust      m_classInvocationResults.put(clazz, instances);
79423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust    }
80423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust    instances.add(instance);
8162a82c6aa5725c9e9d600af5ee06a5852100208cnullin  }
8289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
83423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust  private void setMethodInvocationFailure(ITestNGMethod method, Object instance) {
84f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin    Set<Object> instances = m_methodInvocationResults.get(method);
85423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust    if (instances == null) {
86f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin      instances = Sets.newHashSet();
87423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust      m_methodInvocationResults.put(method, instances);
88423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust    }
89423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust    instances.add(instance);
9062a82c6aa5725c9e9d600af5ee06a5852100208cnullin  }
91f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
923297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust  public Invoker(IConfiguration configuration,
933297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust                 ITestContext testContext,
94f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                 ITestResultNotifier notifier,
95f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                 SuiteRunState state,
9638ef90d96ee65073c1090455e7caff2a85d654e2Cédric Beust                 boolean skipFailedInvocationCounts,
97398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust                 List<IInvokedMethodListener> invokedMethodListeners) {
983297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust    m_configuration = configuration;
99f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    m_testContext= testContext;
100f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    m_suiteState= state;
101f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    m_notifier= notifier;
1023297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust    m_annotationFinder= configuration.getAnnotationFinder();
1036cf2e96a6b18fe7eecc44cac44bb0690a162f416Cédric Beust    m_skipFailedInvocationCounts = skipFailedInvocationCounts;
104398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust    m_invokedMethodListeners = invokedMethodListeners;
10562a82c6aa5725c9e9d600af5ee06a5852100208cnullin    m_continueOnFailedConfiguration = XmlSuite.CONTINUE.equals(testContext.getSuite().getXmlSuite().getConfigFailurePolicy());
106f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
107f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
108f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
109f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * Invoke configuration methods if they belong to the same TestClass passed
110f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * in parameter.. <p/>TODO: Calculate ahead of time which methods should be
111f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * invoked for each class. Might speed things up for users who invoke the
112f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * same test class with different parameters in the same suite run.
113f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   *
114f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * If instance is non-null, the configuration will be run on it.  If it is null,
115f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * the configuration methods will be run on all the instances retrieved
116f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * from the ITestClass.
117f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
118423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust  @Override
119f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  public void invokeConfigurations(IClass testClass,
120f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   ITestNGMethod[] allMethods,
121f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   XmlSuite suite,
122f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   Map<String, String> params,
123facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust                                   Object[] parameterValues,
124f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   Object instance)
125f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
126da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust    invokeConfigurations(testClass, null, allMethods, suite, params, parameterValues, instance,
127da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust        null);
128f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
129f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
130f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private void invokeConfigurations(IClass testClass,
131f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   ITestNGMethod currentTestMethod,
132f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   ITestNGMethod[] allMethods,
133f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   XmlSuite suite,
134f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   Map<String, String> params,
135facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust                                   Object[] parameterValues,
136da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust                                   Object instance,
137da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust                                   ITestResult testMethodResult)
138f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
139f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if(null == allMethods) {
140f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      log(5, "No @Configuration methods found");
141f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
142f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      return;
143f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
144f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
145f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    ITestNGMethod[] methods= filterMethodsUnique(testClass, allMethods);
146f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
147f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for(ITestNGMethod tm : methods) {
148f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if(null == testClass) {
149f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        testClass= tm.getTestClass();
150f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
151f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
15289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      ITestResult testResult= new TestResult(testClass,
153f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             instance,
154f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             tm,
155f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             null,
156f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             System.currentTimeMillis(),
157f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             System.currentTimeMillis());
158f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1592d568355761a9632bf24a87984e241f8a079d724Cédric Beust      IConfigurationAnnotation configurationAnnotation= null;
160f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      try {
161f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        Object[] instances= tm.getInstances();
1620f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        if (instances == null || instances.length == 0) {
1630f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin          instances = new Object[] { instance };
1640f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        }
165f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        Class<?> objectClass= instances[0].getClass();
166f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        Method method= tm.getMethod();
167f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
168f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // Only run the configuration if
169f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // - the test is enabled and
170f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // - the Configuration method belongs to the same class or a parent
171f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if(MethodHelper.isEnabled(objectClass, m_annotationFinder)) {
172423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust          configurationAnnotation = AnnotationHelper.findConfiguration(m_annotationFinder, method);
173f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
174e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust          if (MethodHelper.isEnabled(configurationAnnotation)) {
1750501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust            boolean isClassConfiguration = isClassConfiguration(configurationAnnotation);
17689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin            boolean isSuiteConfiguration = isSuiteConfiguration(configurationAnnotation);
177e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            boolean alwaysRun= isAlwaysRun(configurationAnnotation);
17889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
179423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust            if (!confInvocationPassed(tm, currentTestMethod, testClass, instance) && !alwaysRun) {
180423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust              handleConfigurationSkip(tm, testResult, configurationAnnotation, currentTestMethod, instance, suite);
181e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust              continue;
182e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            }
18389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
184e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            log(3, "Invoking " + Utils.detailedMethodName(tm, true));
18589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
186facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust            Object[] parameters = Parameters.createConfigurationParameters(tm.getMethod(),
187facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust                params,
188facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust                parameterValues,
189facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust                currentTestMethod,
190facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust                m_annotationFinder,
191facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust                suite,
192da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust                m_testContext,
193da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust                testMethodResult);
194e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            testResult.setParameters(parameters);
19589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
196e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            Object[] newInstances= (null != instance) ? new Object[] { instance } : instances;
19789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
198e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            invokeConfigurationMethod(newInstances, tm,
1990501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust              parameters, isClassConfiguration, isSuiteConfiguration, testResult);
20089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
201e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            // TODO: probably we should trigger the event for each instance???
202e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            testResult.setEndMillis(System.currentTimeMillis());
203e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            runConfigurationListeners(testResult);
204e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust          }
205e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust          else {
206e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            log(3,
207e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust                "Skipping "
208e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust                + Utils.detailedMethodName(tm, true)
209e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust                + " because it is not enabled");
210f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
211f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        } // if is enabled
212f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        else {
213f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          log(3,
214f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              "Skipping "
215f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              + Utils.detailedMethodName(tm, true)
216f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              + " because "
217f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              + objectClass.getName()
218f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              + " is not enabled");
219f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
220f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
221f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      catch(InvocationTargetException ex) {
222423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust        handleConfigurationFailure(ex, tm, testResult, configurationAnnotation, currentTestMethod, instance, suite);
223f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
224f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      catch(TestNGException ex) {
225f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // Don't wrap TestNGExceptions, it could be a missing parameter on a
226f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // @Configuration method
227423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust        handleConfigurationFailure(ex, tm, testResult, configurationAnnotation, currentTestMethod, instance, suite);
228f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
229f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      catch(Throwable ex) { // covers the non-wrapper exceptions
230423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust        handleConfigurationFailure(ex, tm, testResult, configurationAnnotation, currentTestMethod, instance, suite);
231f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
232f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    } // for methods
233f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
23489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
235f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
23662a82c6aa5725c9e9d600af5ee06a5852100208cnullin   * Marks the current <code>TestResult</code> as skipped and invokes the listeners.
237f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
23889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin  private void handleConfigurationSkip(ITestNGMethod tm,
23989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                       ITestResult testResult,
24089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                       IConfigurationAnnotation annotation,
24189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                       ITestNGMethod currentTestMethod,
242423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust                                       Object instance,
24362a82c6aa5725c9e9d600af5ee06a5852100208cnullin                                       XmlSuite suite) {
244423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust    recordConfigurationInvocationFailed(tm, testResult.getTestClass(), annotation, currentTestMethod, instance, suite);
245f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    testResult.setStatus(ITestResult.SKIP);
246f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    runConfigurationListeners(testResult);
247f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
24889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
249f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
250f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * Is the current <code>IConfiguration</code> a class-level method.
251f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
2522d568355761a9632bf24a87984e241f8a079d724Cédric Beust  private  boolean isClassConfiguration(IConfigurationAnnotation configurationAnnotation) {
2530b2ac5eab08098da2c2b63d4a3f87ba72ad5d6a1nullin    if (null == configurationAnnotation) {
254f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      return false;
255f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
256f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
2570b2ac5eab08098da2c2b63d4a3f87ba72ad5d6a1nullin    boolean before = configurationAnnotation.getBeforeTestClass();
2580b2ac5eab08098da2c2b63d4a3f87ba72ad5d6a1nullin    boolean after = configurationAnnotation.getAfterTestClass();
259f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
2600b2ac5eab08098da2c2b63d4a3f87ba72ad5d6a1nullin    return before || after;
261f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
262f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
263f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
2640501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust   * Is the current <code>IConfiguration</code> a suite level method.
2650501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust   */
2660501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust  private  boolean isSuiteConfiguration(IConfigurationAnnotation configurationAnnotation) {
2670b2ac5eab08098da2c2b63d4a3f87ba72ad5d6a1nullin    if (null == configurationAnnotation) {
2680501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust      return false;
2690501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust    }
2700501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust
2710b2ac5eab08098da2c2b63d4a3f87ba72ad5d6a1nullin    boolean before = configurationAnnotation.getBeforeSuite();
2720b2ac5eab08098da2c2b63d4a3f87ba72ad5d6a1nullin    boolean after = configurationAnnotation.getAfterSuite();
2730501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust
2740b2ac5eab08098da2c2b63d4a3f87ba72ad5d6a1nullin    return before || after;
2750501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust  }
2760501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust
2770501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust  /**
278f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * Is the <code>IConfiguration</code> marked as alwaysRun.
279f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
2802d568355761a9632bf24a87984e241f8a079d724Cédric Beust  private boolean isAlwaysRun(IConfigurationAnnotation configurationAnnotation) {
281f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if(null == configurationAnnotation) {
282f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      return false;
283f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
28489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
285f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    boolean alwaysRun= false;
286f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if ((configurationAnnotation.getAfterSuite()
287f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        || configurationAnnotation.getAfterTest()
288f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        || configurationAnnotation.getAfterTestClass()
289f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        || configurationAnnotation.getAfterTestMethod())
290f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        && configurationAnnotation.getAlwaysRun())
291f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    {
292f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        alwaysRun= true;
293f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
29489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
295f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return alwaysRun;
296f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
29789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
298f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private void handleConfigurationFailure(Throwable ite,
299f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                          ITestNGMethod tm,
300f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                          ITestResult testResult,
3012d568355761a9632bf24a87984e241f8a079d724Cédric Beust                                          IConfigurationAnnotation annotation,
30262a82c6aa5725c9e9d600af5ee06a5852100208cnullin                                          ITestNGMethod currentTestMethod,
303423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust                                          Object instance,
30489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                          XmlSuite suite)
305f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
306f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    Throwable cause= ite.getCause() != null ? ite.getCause() : ite;
30789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
308f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if(SkipException.class.isAssignableFrom(cause.getClass())) {
309f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      SkipException skipEx= (SkipException) cause;
3100c3edfde6ca92fb2cfeb3072fa1c7cb08c1706c3DanFabulich      if(skipEx.isSkip()) {
311f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        testResult.setThrowable(skipEx);
312423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust        handleConfigurationSkip(tm, testResult, annotation, currentTestMethod, instance, suite);
313f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        return;
314f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
315f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
31689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin    Utils.log("", 3, "Failed to invoke @Configuration method "
317f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        + tm.getRealClass().getName() + "." + tm.getMethodName() + ":" + cause.getMessage());
318f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    handleException(cause, tm, testResult, 1);
319f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    runConfigurationListeners(testResult);
320f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
32189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin    //
322f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // If in TestNG mode, need to take a look at the annotation to figure out
323f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // what kind of @Configuration method we're dealing with
324f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
325f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if (null != annotation) {
326423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust      recordConfigurationInvocationFailed(tm, testResult.getTestClass(), annotation, currentTestMethod, instance, suite);
327f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
328f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
329f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
330f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
331f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return All the classes that belong to the same <test> tag as @param cls
332f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
333f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private XmlClass[] findClassesInSameTest(Class<?> cls, XmlSuite suite) {
3340f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beust    Map<String, XmlClass> vResult= Maps.newHashMap();
335f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    String className= cls.getName();
336f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for(XmlTest test : suite.getTests()) {
337f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for(XmlClass testClass : test.getXmlClasses()) {
338f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if(testClass.getName().equals(className)) {
339f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
340f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          // Found it, add all the classes in this test in the result
341f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          for(XmlClass thisClass : test.getXmlClasses()) {
342f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            vResult.put(thisClass.getName(), thisClass);
343f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
344f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          // Note:  we need to iterate through the entire suite since the same
345f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          // class might appear in several <test> tags
346f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
347f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
348f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
349f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
350f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    XmlClass[] result= vResult.values().toArray(new XmlClass[vResult.size()]);
351f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
352f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return result;
353f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
354f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
355f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
356f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * Record internally the failure of a Configuration, so that we can determine
357f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * later if @Test should be skipped.
358f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
35989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin  private void recordConfigurationInvocationFailed(ITestNGMethod tm,
36089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                   IClass testClass,
36189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                   IConfigurationAnnotation annotation,
36289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                   ITestNGMethod currentTestMethod,
363423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust                                                   Object instance,
36462a82c6aa5725c9e9d600af5ee06a5852100208cnullin                                                   XmlSuite suite) {
36562a82c6aa5725c9e9d600af5ee06a5852100208cnullin    // If beforeTestClass or afterTestClass failed, mark either the config method's
36662a82c6aa5725c9e9d600af5ee06a5852100208cnullin    // entire class as failed, or the class under tests as failed, depending on
36762a82c6aa5725c9e9d600af5ee06a5852100208cnullin    // the configuration failure policy
36862a82c6aa5725c9e9d600af5ee06a5852100208cnullin    if (annotation.getBeforeTestClass() || annotation.getAfterTestClass()) {
36962a82c6aa5725c9e9d600af5ee06a5852100208cnullin      // tm is the configuration method, and currentTestMethod is null for BeforeClass
37062a82c6aa5725c9e9d600af5ee06a5852100208cnullin      // methods, so we need testClass
37162a82c6aa5725c9e9d600af5ee06a5852100208cnullin      if (m_continueOnFailedConfiguration) {
372423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust        setClassInvocationFailure(testClass.getRealClass(), instance);
37362a82c6aa5725c9e9d600af5ee06a5852100208cnullin      } else {
374423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust        setClassInvocationFailure(tm.getRealClass(), instance);
37562a82c6aa5725c9e9d600af5ee06a5852100208cnullin      }
37662a82c6aa5725c9e9d600af5ee06a5852100208cnullin    }
37789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
37862a82c6aa5725c9e9d600af5ee06a5852100208cnullin    // If before/afterTestMethod failed, mark either the config method's entire
37962a82c6aa5725c9e9d600af5ee06a5852100208cnullin    // class as failed, or just the current test method as failed, depending on
38062a82c6aa5725c9e9d600af5ee06a5852100208cnullin    // the configuration failure policy
38162a82c6aa5725c9e9d600af5ee06a5852100208cnullin    else if (annotation.getBeforeTestMethod() || annotation.getAfterTestMethod()) {
38262a82c6aa5725c9e9d600af5ee06a5852100208cnullin      if (m_continueOnFailedConfiguration) {
383423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust        setMethodInvocationFailure(currentTestMethod, instance);
38462a82c6aa5725c9e9d600af5ee06a5852100208cnullin      } else {
385423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust        setClassInvocationFailure(tm.getRealClass(), instance);
38662a82c6aa5725c9e9d600af5ee06a5852100208cnullin      }
387f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
388f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
389f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // If beforeSuite or afterSuite failed, mark *all* the classes as failed
390f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // for configurations.  At this point, the entire Suite is screwed
391f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    else if (annotation.getBeforeSuite() || annotation.getAfterSuite()) {
392f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      m_suiteState.failed();
393f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
394f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
395f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // beforeTest or afterTest:  mark all the classes in the same
396f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // <test> stanza as failed for configuration
397f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    else if (annotation.getBeforeTest() || annotation.getAfterTest()) {
398423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust      setClassInvocationFailure(tm.getRealClass(), instance);
399f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      XmlClass[] classes= findClassesInSameTest(tm.getRealClass(), suite);
400f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for(XmlClass xmlClass : classes) {
401423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust        setClassInvocationFailure(xmlClass.getSupportClass(), instance);
402f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
403f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
404f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    String[] beforeGroups= annotation.getBeforeGroups();
405f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if(null != beforeGroups && beforeGroups.length > 0) {
406f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for(String group: beforeGroups) {
407f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        m_beforegroupsFailures.put(group, Boolean.FALSE);
408f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
409f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
410f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
41189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
412f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
413f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return true if this class has successfully run all its @Configuration
414f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * method or false if at least one of these methods failed.
415f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
416423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust  private boolean confInvocationPassed(ITestNGMethod method, ITestNGMethod currentTestMethod, IClass testClass, Object instance) {
417f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    boolean result= true;
418f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
41962a82c6aa5725c9e9d600af5ee06a5852100208cnullin    // If continuing on config failure, check invocation results for the class
42062a82c6aa5725c9e9d600af5ee06a5852100208cnullin    // under test, otherwise use the method's declaring class
42189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin    Class<?> cls = m_continueOnFailedConfiguration ?
42262a82c6aa5725c9e9d600af5ee06a5852100208cnullin            testClass.getRealClass() : method.getMethod().getDeclaringClass();
42362a82c6aa5725c9e9d600af5ee06a5852100208cnullin
424f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if(m_suiteState.isFailed()) {
425f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      result= false;
426f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
427f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    else {
428423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust      if (m_classInvocationResults.containsKey(cls)) {
4290f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        if (! m_continueOnFailedConfiguration) {
4300f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin          result = !m_classInvocationResults.containsKey(cls);
4310f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        } else {
4320f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin          result = !m_classInvocationResults.get(cls).contains(instance);
4330f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        }
434f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
43562a82c6aa5725c9e9d600af5ee06a5852100208cnullin      // if method is BeforeClass, currentTestMethod will be null
43689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      else if (m_continueOnFailedConfiguration &&
43789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin              currentTestMethod != null &&
43862a82c6aa5725c9e9d600af5ee06a5852100208cnullin              m_methodInvocationResults.containsKey(currentTestMethod)) {
439423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust        result = !m_methodInvocationResults.get(currentTestMethod).contains(instance);
44062a82c6aa5725c9e9d600af5ee06a5852100208cnullin      }
441423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust      else if (! m_continueOnFailedConfiguration) {
442f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        for(Class<?> clazz: m_classInvocationResults.keySet()) {
4431e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust//          if (clazz == cls) {
444f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          if(clazz.isAssignableFrom(cls)) {
445f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            result= false;
446f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            break;
447f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
448f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
449f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
450f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
451f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
452f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // check if there are failed @BeforeGroups
453f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    String[] groups= method.getGroups();
454f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if(null != groups && groups.length > 0) {
455f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for(String group: groups) {
456f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if(m_beforegroupsFailures.containsKey(group)) {
457f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          result= false;
458f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          break;
459f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
460f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
461f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
462f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return result;
463f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
464f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
465f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
466f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * Effectively invokes a configuration method on all passed in instances.
467d3c04c36b8f179fd5aa1b53711a5b909cde06d09nalin.makar@gmail.com   * TODO: Should change this method to be more like invokeMethod() so that we can
468d3c04c36b8f179fd5aa1b53711a5b909cde06d09nalin.makar@gmail.com   * handle calls to {@code IInvokedMethodListener} better.
46989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin   *
470f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param instances the instances to invoke the configuration method on
471f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param tm the configuration method
472f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param params the parameters needed for method invocation
473f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param isClass flag if the configuration method is a class level method // FIXME: this looks like a missusage
474f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param testResult
475f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @throws InvocationTargetException
476f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @throws IllegalAccessException
477f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
478f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private void invokeConfigurationMethod(Object[] instances,
479f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                         ITestNGMethod tm,
480f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                         Object[] params,
481f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                         boolean isClass,
4820501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust                                         boolean isSuite,
483f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                         ITestResult testResult)
48489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin    throws InvocationTargetException, IllegalAccessException
485f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
486f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Mark this method with the current thread id
487f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    tm.setId(ThreadUtil.currentThreadInfo());
488f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
489f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for(Object targetInstance : instances) {
490f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      InvokedMethod im= new InvokedMethod(targetInstance,
491f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                          tm,
492f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                          params,
493f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                          false, /* isTest */
494f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                          isClass, /* ??? */
495f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                          System.currentTimeMillis());
496f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
497398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust      runInvokedMethodListeners(true /* before */, im, testResult);
498f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      m_notifier.addInvokedMethod(im);
499f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      try {
500f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        Reporter.setCurrentTestResult(testResult);
5010bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust        Method method = tm.getMethod();
502e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust
503e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust        //
504e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust        // If this method is a IHookable, invoke its run() method
505e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust        //
506e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust        IConfigurable configurableInstance =
507e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust          IConfigurable.class.isAssignableFrom(tm.getMethod().getDeclaringClass()) ?
508e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust          (IConfigurable) targetInstance : m_configuration.getConfigurable();
509e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust        if (configurableInstance != null) {
5100bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust          //
5110bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust          // If this method is a IConfigurable, invoke its run() method
5120bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust          //
513b1c182d51b05a40ac5350e562503a94d024a7c80nullin          MethodInvocationHelper.invokeConfigurable(targetInstance, params, configurableInstance, method,
514e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust              testResult);
5150bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust        }
5160bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust        else {
5170bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust          //
518830ff4bf3fbfae0d63cb762b9c0d9a184feb58a3Cédric Beust          // Not a IConfigurable, invoke directly
5190bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust          //
520830ff4bf3fbfae0d63cb762b9c0d9a184feb58a3Cédric Beust          if (MethodHelper.calculateTimeOut(tm) <= 0) {
521b1c182d51b05a40ac5350e562503a94d024a7c80nullin            MethodInvocationHelper.invokeMethod(method, targetInstance, params);
522830ff4bf3fbfae0d63cb762b9c0d9a184feb58a3Cédric Beust          }
523830ff4bf3fbfae0d63cb762b9c0d9a184feb58a3Cédric Beust          else {
524b1c182d51b05a40ac5350e562503a94d024a7c80nullin            MethodInvocationHelper.invokeWithTimeout(tm, targetInstance, params, testResult);
525830ff4bf3fbfae0d63cb762b9c0d9a184feb58a3Cédric Beust            if (!testResult.isSuccess()) {
526830ff4bf3fbfae0d63cb762b9c0d9a184feb58a3Cédric Beust              // A time out happened
527830ff4bf3fbfae0d63cb762b9c0d9a184feb58a3Cédric Beust              throwConfigurationFailure(testResult, testResult.getThrowable());
528830ff4bf3fbfae0d63cb762b9c0d9a184feb58a3Cédric Beust              throw testResult.getThrowable();
529830ff4bf3fbfae0d63cb762b9c0d9a184feb58a3Cédric Beust            }
530830ff4bf3fbfae0d63cb762b9c0d9a184feb58a3Cédric Beust          }
5310bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust        }
5320501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust        // Only run the method once if it's @BeforeSuite or @AfterSuite
5330f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        if (isSuite) {
5340f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin          break;
5350f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        }
536db66a3de4428040dd9f7e377a3b6835965c8b0cdCédric Beust      }
537d3c04c36b8f179fd5aa1b53711a5b909cde06d09nalin.makar@gmail.com      catch (InvocationTargetException ex) {
5380bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust       throwConfigurationFailure(testResult, ex);
5390bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust       throw ex;
540d3c04c36b8f179fd5aa1b53711a5b909cde06d09nalin.makar@gmail.com      }
541d3c04c36b8f179fd5aa1b53711a5b909cde06d09nalin.makar@gmail.com      catch (IllegalAccessException ex) {
5420bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust        throwConfigurationFailure(testResult, ex);
5430bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust        throw ex;
5440bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust      }
5450bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust      catch (NoSuchMethodException ex) {
5460bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust        throwConfigurationFailure(testResult, ex);
5470bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust        throw new TestNGException(ex);
5480bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust      }
5490bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust      catch (Throwable ex) {
5500bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust        throwConfigurationFailure(testResult, ex);
5510bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust        throw new TestNGException(ex);
5520bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust      }
5530bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust      finally {
554f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        Reporter.setCurrentTestResult(testResult);
555398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust        runInvokedMethodListeners(false /* after */, im, testResult);
55689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      }
557f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
558f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
559f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
5600bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust  private void throwConfigurationFailure(ITestResult testResult, Throwable ex)
5610bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust  {
5620bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust    testResult.setStatus(ITestResult.FAILURE);;
5630bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust    testResult.setThrowable(ex.getCause() == null ? ex : ex.getCause());
5640bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust  }
5650bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust
56689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin  private void runInvokedMethodListeners(boolean before, IInvokedMethod method,
567398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust      ITestResult testResult)
568398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust  {
569398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust    if (m_invokedMethodListeners != null) {
570398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust      if (before) {
571398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust        for (IInvokedMethodListener l : m_invokedMethodListeners) {
57268f450416a61dbdd31ba55933fe10d2b022c3908Cédric Beust          if (l instanceof IInvokedMethodListener2) {
57368f450416a61dbdd31ba55933fe10d2b022c3908Cédric Beust            IInvokedMethodListener2 l2 = (IInvokedMethodListener2) l;
57468f450416a61dbdd31ba55933fe10d2b022c3908Cédric Beust            l2.beforeInvocation(method, testResult, m_testContext);
57568f450416a61dbdd31ba55933fe10d2b022c3908Cédric Beust          } else {
57668f450416a61dbdd31ba55933fe10d2b022c3908Cédric Beust            l.beforeInvocation(method, testResult);
57768f450416a61dbdd31ba55933fe10d2b022c3908Cédric Beust          }
578398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust        }
579398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust      }
580398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust      else {
581398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust        for (IInvokedMethodListener l : m_invokedMethodListeners) {
58268f450416a61dbdd31ba55933fe10d2b022c3908Cédric Beust          if (l instanceof IInvokedMethodListener2) {
58368f450416a61dbdd31ba55933fe10d2b022c3908Cédric Beust            IInvokedMethodListener2 l2 = (IInvokedMethodListener2) l;
58468f450416a61dbdd31ba55933fe10d2b022c3908Cédric Beust            l2.afterInvocation(method, testResult, m_testContext);
58568f450416a61dbdd31ba55933fe10d2b022c3908Cédric Beust          } else {
58668f450416a61dbdd31ba55933fe10d2b022c3908Cédric Beust            l.afterInvocation(method, testResult);
58768f450416a61dbdd31ba55933fe10d2b022c3908Cédric Beust          }
588398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust        }
589398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust      }
590398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust    }
591398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust  }
592398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust
593927a6d8a655520943e3a8a9ea9f09cbfe56f2ae6Cédric Beust  // pass both paramValues and paramIndex to be thread safe in case parallel=true + dataprovider.
594f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private ITestResult invokeMethod(Object[] instances,
595f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   int instanceIndex,
596f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   final ITestNGMethod tm,
597f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   Object[] parameterValues,
598927a6d8a655520943e3a8a9ea9f09cbfe56f2ae6Cédric Beust                                   int parametersIndex,
599f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   XmlSuite suite,
600f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   Map<String, String> params,
601f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   ITestClass testClass,
602f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   ITestNGMethod[] beforeMethods,
603f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   ITestNGMethod[] afterMethods,
604f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   ConfigurationGroupMethods groupMethods) {
60594efdf8e6ac7332eadf8bfe5d1fe699caee5d051Cédric Beust    TestResult testResult = new TestResult();
60694efdf8e6ac7332eadf8bfe5d1fe699caee5d051Cédric Beust
607f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
608f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Invoke beforeGroups configurations
609f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
6103297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust    Object instance = instances[instanceIndex];
611f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    invokeBeforeGroupsConfigurations(testClass, tm, groupMethods, suite, params,
6123297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust        instance);
613f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
614f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
61545a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust    // Invoke beforeMethods only if
61645a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust    // - firstTimeOnly is not set
61745a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust    // - firstTimeOnly is set, and we are reaching at the first invocationCount
618f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
61989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin    invokeConfigurations(testClass, tm,
62045a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      filterConfigurationMethods(tm, beforeMethods, true /* beforeMethods */),
621facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust      suite, params, parameterValues,
6223297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust      instance, testResult);
62389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
624f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
625f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Create the ExtraOutput for this method
626f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
62738ef90d96ee65073c1090455e7caff2a85d654e2Cédric Beust    InvokedMethod invokedMethod = null;
628f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    try {
6293297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust      testResult.init(testClass, instance,
630f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                 tm,
631f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                 null,
632f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                 System.currentTimeMillis(),
633f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                 0);
634f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      testResult.setParameters(parameterValues);
635f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      testResult.setHost(m_testContext.getHost());
636f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      testResult.setStatus(ITestResult.STARTED);
637f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      runTestListeners(testResult);
638f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
6393297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust      invokedMethod= new InvokedMethod(instance,
640f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          tm,
641f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          parameterValues,
642e934f66fb4fb247ebf5fec45770bc6820fbba29anullin          true /* isTest */,
643e934f66fb4fb247ebf5fec45770bc6820fbba29anullin          false /* isConfiguration */,
644f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          System.currentTimeMillis());
645f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
64628e899a6c1620c8d07cb04a92f96658550e4af16nullin      runInvokedMethodListeners(true /* before */, invokedMethod, testResult);
64738ef90d96ee65073c1090455e7caff2a85d654e2Cédric Beust
648f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      m_notifier.addInvokedMethod(invokedMethod);
64989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
650f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Method thisMethod= tm.getMethod();
65189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
6523297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust      if(confInvocationPassed(tm, tm, testClass, instance)) {
653f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        log(3, "Invoking " + thisMethod.getDeclaringClass().getName() + "." +
654f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            thisMethod.getName());
655f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
656f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // If no timeOut, just invoke the method
657331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust        if (MethodHelper.calculateTimeOut(tm) <= 0) {
658711b9b624165b9185efea58f010a40275e19c972mendelson.paul          try {
659711b9b624165b9185efea58f010a40275e19c972mendelson.paul            Reporter.setCurrentTestResult(testResult);
660711b9b624165b9185efea58f010a40275e19c972mendelson.paul            //
661711b9b624165b9185efea58f010a40275e19c972mendelson.paul            // If this method is a IHookable, invoke its run() method
662711b9b624165b9185efea58f010a40275e19c972mendelson.paul            //
663e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust            IHookable hookableInstance =
664e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust              IHookable.class.isAssignableFrom(thisMethod.getDeclaringClass()) ?
665e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust              (IHookable) instance : m_configuration.getHookable();
666e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust            if (hookableInstance != null) {
667b1c182d51b05a40ac5350e562503a94d024a7c80nullin              MethodInvocationHelper.invokeHookable(instance,
668e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust                  parameterValues, hookableInstance, thisMethod, testResult);
669711b9b624165b9185efea58f010a40275e19c972mendelson.paul            }
670711b9b624165b9185efea58f010a40275e19c972mendelson.paul            //
671711b9b624165b9185efea58f010a40275e19c972mendelson.paul            // Not a IHookable, invoke directly
672711b9b624165b9185efea58f010a40275e19c972mendelson.paul            //
673711b9b624165b9185efea58f010a40275e19c972mendelson.paul            else {
674b1c182d51b05a40ac5350e562503a94d024a7c80nullin              MethodInvocationHelper.invokeMethod(thisMethod, instance,
675f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                  parameterValues);
67689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin            }
677711b9b624165b9185efea58f010a40275e19c972mendelson.paul            testResult.setStatus(ITestResult.SUCCESS);
678711b9b624165b9185efea58f010a40275e19c972mendelson.paul          }
679711b9b624165b9185efea58f010a40275e19c972mendelson.paul          finally {
680711b9b624165b9185efea58f010a40275e19c972mendelson.paul            Reporter.setCurrentTestResult(null);
681f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
682f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
683f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        else {
684331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust          //
685331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust          // Method with a timeout
686331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust          //
687f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          try {
688f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            Reporter.setCurrentTestResult(testResult);
689b1c182d51b05a40ac5350e562503a94d024a7c80nullin            MethodInvocationHelper.invokeWithTimeout(tm, instance, parameterValues, testResult);
690f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
691f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          finally {
692f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            Reporter.setCurrentTestResult(null);
693f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
694f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
695f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
696f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      else {
697f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        testResult.setStatus(ITestResult.SKIP);
698f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
699f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
700f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    catch(InvocationTargetException ite) {
701f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      testResult.setThrowable(ite.getCause());
702d3c04c36b8f179fd5aa1b53711a5b909cde06d09nalin.makar@gmail.com      testResult.setStatus(ITestResult.FAILURE);
703f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
704f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    catch(ThreadExecutionException tee) { // wrapper for TestNGRuntimeException
705f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Throwable cause= tee.getCause();
706f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if(TestNGRuntimeException.class.equals(cause.getClass())) {
707f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        testResult.setThrowable(cause.getCause());
708f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
709f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      else {
710f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        testResult.setThrowable(cause);
711f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
712d3c04c36b8f179fd5aa1b53711a5b909cde06d09nalin.makar@gmail.com      testResult.setStatus(ITestResult.FAILURE);
713f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
714f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    catch(Throwable thr) { // covers the non-wrapper exceptions
715f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      testResult.setThrowable(thr);
716d3c04c36b8f179fd5aa1b53711a5b909cde06d09nalin.makar@gmail.com      testResult.setStatus(ITestResult.FAILURE);
717f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
718f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    finally {
719bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust      ExpectedExceptionsHolder expectedExceptionClasses
720318a4e47ce813109c76fc8281c9db5f04448f3f1Cédric Beust          = MethodHelper.findExpectedExceptions(m_annotationFinder, tm.getMethod());
721ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust      List<ITestResult> results = Lists.newArrayList();
722318a4e47ce813109c76fc8281c9db5f04448f3f1Cédric Beust      results.add(testResult);
7236216d78ae0757b7d57aa6e94cc041447d610724dCédric Beust      handleInvocationResults(tm, results, null, 0, expectedExceptionClasses, false,
7246216d78ae0757b7d57aa6e94cc041447d610724dCédric Beust          true /* collect results */);
72589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
726aacb207142f114ec6c99e8fab25c4836be70eb95nullin      //Run invokedMethodListeners after fixing the test results based on
727aacb207142f114ec6c99e8fab25c4836be70eb95nullin      //expectedExceptions, if any
72828e899a6c1620c8d07cb04a92f96658550e4af16nullin      runInvokedMethodListeners(false /* before */, invokedMethod, testResult);
72938ef90d96ee65073c1090455e7caff2a85d654e2Cédric Beust
730dd84c4f1673772d6b1febb72add6a2ae40f4e4ccCédric Beust      // If this method has a data provider and just failed, memorize the number
731dd84c4f1673772d6b1febb72add6a2ae40f4e4ccCédric Beust      // at which it failed.
7321ed096c7af783713cdeb4a3e9c0c4a02491d65fcCédric Beust      // Note: we're not exactly testing that this method has a data provider, just
7331ed096c7af783713cdeb4a3e9c0c4a02491d65fcCédric Beust      // that it has parameters, so might have to revisit this if bugs get reported
7341ed096c7af783713cdeb4a3e9c0c4a02491d65fcCédric Beust      // for the case where this method has parameters that don't come from a data
7351ed096c7af783713cdeb4a3e9c0c4a02491d65fcCédric Beust      // provider
736dd84c4f1673772d6b1febb72add6a2ae40f4e4ccCédric Beust      if (testResult.getThrowable() != null && parameterValues.length > 0) {
737927a6d8a655520943e3a8a9ea9f09cbfe56f2ae6Cédric Beust        tm.addFailedInvocationNumber(parametersIndex);
738dd84c4f1673772d6b1febb72add6a2ae40f4e4ccCédric Beust      }
739dd84c4f1673772d6b1febb72add6a2ae40f4e4ccCédric Beust
740f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
741f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // Increment the invocation count for this method
742f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
743f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      tm.incrementCurrentInvocationCount();
744f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
745f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if (testResult != null) {
746f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        testResult.setEndMillis(System.currentTimeMillis());
747f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
748bacea92cd4a97cc839df9533025400c343a4689fCédric Beust
7497e735d9079026e11bc7cd06dab2b99d9ff9cd6c3Cédric Beust//      if (testResult.getStatus() == ITestResult.SUCCESS) {
750bacea92cd4a97cc839df9533025400c343a4689fCédric Beust        runTestListeners(testResult);
7517e735d9079026e11bc7cd06dab2b99d9ff9cd6c3Cédric Beust//      }
752bacea92cd4a97cc839df9533025400c343a4689fCédric Beust
753f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
75445a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      // Invoke afterMethods only if
75545a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      // - lastTimeOnly is not set
75645a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      // - lastTimeOnly is set, and we are reaching the last invocationCount
757f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
75889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      invokeConfigurations(testClass, tm,
75945a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust          filterConfigurationMethods(tm, afterMethods, false /* beforeMethods */),
760facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust          suite, params, parameterValues,
7613297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust          instance,
762da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust          testResult);
76389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
764f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
76545a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      // Invoke afterGroups configurations
766f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
767f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      invokeAfterGroupsConfigurations(testClass, tm, groupMethods, suite,
7683297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust          params, instance);
769f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
77094efdf8e6ac7332eadf8bfe5d1fe699caee5d051Cédric Beust
771f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return testResult;
772f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
77389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
774f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
77545a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust   * The array of methods contains @BeforeMethods if isBefore if true, @AfterMethods
77645a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust   * otherwise.  This function removes all the methods that should not be run at this
77745a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust   * point because they are either firstTimeOnly or lastTimeOnly and we haven't reached
77845a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust   * the current invocationCount yet
77945a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust   */
78045a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust  private ITestNGMethod[] filterConfigurationMethods(ITestNGMethod tm,
78145a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      ITestNGMethod[] methods, boolean isBefore)
78245a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust  {
783ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust    List<ITestNGMethod> result = Lists.newArrayList();
78445a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust    for (ITestNGMethod m : methods) {
78545a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      ConfigurationMethod cm = (ConfigurationMethod) m;
78645a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      if (isBefore) {
78745a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust        if (! cm.isFirstTimeOnly() ||
78845a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust            (cm.isFirstTimeOnly() && tm.getCurrentInvocationCount() == 0))
78945a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust        {
79045a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust          result.add(m);
79145a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust        }
79245a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      }
79345a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      else {
794d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust        int current = tm.getCurrentInvocationCount();
795d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust        boolean isLast = false;
7962fc881781da9eb64b913650c8bb856d1f97c64cdCédric Beust        // If we have parameters, set the boolean if we are about to run
7972fc881781da9eb64b913650c8bb856d1f97c64cdCédric Beust        // the last invocation
798d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust        if (tm.getParameterInvocationCount() > 0) {
799d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust          isLast = current == tm.getParameterInvocationCount();
800d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust        }
8012fc881781da9eb64b913650c8bb856d1f97c64cdCédric Beust        // If we have invocationCount > 1, set the boolean if we are about to
8022fc881781da9eb64b913650c8bb856d1f97c64cdCédric Beust        // run the last invocation
803d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust        else if (tm.getInvocationCount() > 1) {
804d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust          isLast = current == tm.getInvocationCount();
805d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust        }
806d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust        if (! cm.isLastTimeOnly() || (cm.isLastTimeOnly() && isLast)) {
80745a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust          result.add(m);
80845a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust        }
80945a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      }
81045a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust    }
81145a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust
81245a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust    return result.toArray(new ITestNGMethod[result.size()]);
81345a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust  }
81445a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust
81545a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust  /**
81689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin   * {@link #invokeTestMethods()} eventually converge here to invoke a single @Test method.
817f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * <p/>
818f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * This method is responsible for actually invoking the method. It decides if the invocation
819f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * must be done:
820f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * <ul>
82189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin   * <li>through an <code>IHookable</code></li>
822f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * <li>directly (through reflection)</li>
823f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * <li>in a separate thread (in case it needs to timeout)
824f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * </ul>
82589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin   *
826f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * <p/>
827f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * This method is also reponsible for invoking @BeforeGroup, @BeforeMethod, @AfterMethod, @AfterGroup
828f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * if it is the case for the passed in @Test method.
829f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
83021dad3370294d6595fdddc3faf55792f60a913f1nullin  protected List<ITestResult> invokeTestMethod(Object[] instances,
831f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             final ITestNGMethod tm,
832f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             Object[] parameterValues,
833927a6d8a655520943e3a8a9ea9f09cbfe56f2ae6Cédric Beust                                             int parametersIndex,
834f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             XmlSuite suite,
835f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             Map<String, String> params,
836f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             ITestClass testClass,
837f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             ITestNGMethod[] beforeMethods,
838f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             ITestNGMethod[] afterMethods,
839f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             ConfigurationGroupMethods groupMethods)
840f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
841ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust    List<ITestResult> results = Lists.newArrayList();
842f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
843f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Mark this method with the current thread id
844f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    tm.setId(ThreadUtil.currentThreadInfo());
845f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
846f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for(int i= 0; i < instances.length; i++) {
847927a6d8a655520943e3a8a9ea9f09cbfe56f2ae6Cédric Beust      results.add(invokeMethod(instances, i, tm, parameterValues, parametersIndex, suite, params,
84894efdf8e6ac7332eadf8bfe5d1fe699caee5d051Cédric Beust          testClass, beforeMethods, afterMethods, groupMethods));
849f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
850f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
851f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return results;
852f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
853f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
854f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
855f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * Filter all the beforeGroups methods and invoke only those that apply
856f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * to the current test method
857f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
85889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin  private void invokeBeforeGroupsConfigurations(ITestClass testClass,
85989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                ITestNGMethod currentTestMethod,
86089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                ConfigurationGroupMethods groupMethods,
86189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                XmlSuite suite,
86289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                Map<String, String> params,
86389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                Object instance)
864f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
865f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    synchronized(groupMethods) {
866ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust      List<ITestNGMethod> filteredMethods = Lists.newArrayList();
867f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      String[] groups = currentTestMethod.getGroups();
868f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Map<String, List<ITestNGMethod>> beforeGroupMap = groupMethods.getBeforeGroupsMap();
86989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
870f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for (String group : groups) {
871f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        List<ITestNGMethod> methods = beforeGroupMap.get(group);
872f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if (methods != null) {
873f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          filteredMethods.addAll(methods);
874f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
875f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
87689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
877f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      ITestNGMethod[] beforeMethodsArray = filteredMethods.toArray(new ITestNGMethod[filteredMethods.size()]);
878f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
879f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // Invoke the right groups methods
880f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
881f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if(beforeMethodsArray.length > 0) {
882f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // don't pass the IClass or the instance as the method may be external
883f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // the invocation must be similar to @BeforeTest/@BeforeSuite
88489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin        invokeConfigurations(null, beforeMethodsArray, suite, params,
885facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust            null, /* no parameter values */
886facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust            null);
887f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
88889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
889f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
890f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // Remove them so they don't get run again
891f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
892f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      groupMethods.removeBeforeGroups(groups);
893f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
894f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
895f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
89689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin  private void invokeAfterGroupsConfigurations(ITestClass testClass,
897f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                               ITestNGMethod currentTestMethod,
898f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                               ConfigurationGroupMethods groupMethods,
89989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                               XmlSuite suite,
90089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                               Map<String, String> params,
90189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                               Object instance)
902f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
903f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Skip this if the current method doesn't belong to any group
904f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // (only a method that belongs to a group can trigger the invocation
905f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // of afterGroups methods)
9060f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin    if (currentTestMethod.getGroups().length == 0) {
9070f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      return;
9080f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin    }
90989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
910f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // See if the currentMethod is the last method in any of the groups
911f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // it belongs to
9120f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beust    Map<String, String> filteredGroups = Maps.newHashMap();
913f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    String[] groups = currentTestMethod.getGroups();
914f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    synchronized(groupMethods) {
915f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for (String group : groups) {
916f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if (groupMethods.isLastMethodForGroup(group, currentTestMethod)) {
917f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          filteredGroups.put(group, group);
918f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
919f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
92089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
9210f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      if(filteredGroups.isEmpty()) {
9220f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        return;
9230f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      }
92489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
925f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // The list of afterMethods to run
9260f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beust      Map<ITestNGMethod, ITestNGMethod> afterMethods = Maps.newHashMap();
92789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
928f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // Now filteredGroups contains all the groups for which we need to run the afterGroups
929f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // method.  Find all the methods that correspond to these groups and invoke them.
930f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Map<String, List<ITestNGMethod>> map = groupMethods.getAfterGroupsMap();
931f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for (String g : filteredGroups.values()) {
932f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        List<ITestNGMethod> methods = map.get(g);
933f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // Note:  should put them in a map if we want to make sure the same afterGroups
934f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // doesn't get run twice
935f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if (methods != null) {
936f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          for (ITestNGMethod m : methods) {
937f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            afterMethods.put(m, m);
938f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
939f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
940f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
94189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
942f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // Got our afterMethods, invoke them
943f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      ITestNGMethod[] afterMethodsArray = afterMethods.keySet().toArray(new ITestNGMethod[afterMethods.size()]);
944f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // don't pass the IClass or the instance as the method may be external
945f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // the invocation must be similar to @BeforeTest/@BeforeSuite
94689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      invokeConfigurations(null, afterMethodsArray, suite, params,
947facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust          null, /* no parameter values */
948facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust          null);
949f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
950f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // Remove the groups so they don't get run again
95189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      groupMethods.removeAfterGroups(filteredGroups.keySet());
952f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
953f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
954f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
955f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private Object[] getParametersFromIndex(Iterator<Object[]> parametersValues, int index) {
956f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    while (parametersValues.hasNext()) {
957f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Object[] parameters = parametersValues.next();
958f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
959f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if (index == 0) {
960f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        return parameters;
961f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
962f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      index--;
963f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
964f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return null;
965f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
96689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
967c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust  int retryFailed(Object[] instances,
968f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           int instanceIndex,
969f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           final ITestNGMethod tm,
970f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           XmlSuite suite,
971f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           ITestClass testClass,
972f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           ITestNGMethod[] beforeMethods,
973f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           ITestNGMethod[] afterMethods,
974f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           ConfigurationGroupMethods groupMethods,
975f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           List<ITestResult> result,
976f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           int failureCount,
977bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust                           ExpectedExceptionsHolder expectedExceptionHolder,
978f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           ITestContext testContext,
979f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           Map<String, String> parameters,
980f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           int parametersIndex) {
98192206009b23ecbbf29e5a0d20f6b095a552afcb8Cédric Beust    List<Object> failedInstances;
982f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
98392206009b23ecbbf29e5a0d20f6b095a552afcb8Cédric Beust    do {
984ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust      failedInstances = Lists.newArrayList();
9850f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beust      Map<String, String> allParameters = Maps.newHashMap();
986f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      /**
987f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust       * TODO: This recreates all the parameters every time when we only need
988f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust       * one specific set. Should optimize it by only recreating the set needed.
989f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust       */
990f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      ParameterBag bag = createParameters(testClass, tm, parameters,
991da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust          allParameters, null, suite, testContext, null /* fedInstance */, null /* testResult */);
992c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust      Object[] parameterValues =
993c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust          getParametersFromIndex(bag.parameterHolder.parameters, parametersIndex);
994f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
99589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      result.add(invokeMethod(instances, instanceIndex, tm, parameterValues,parametersIndex, suite,
99694efdf8e6ac7332eadf8bfe5d1fe699caee5d051Cédric Beust          allParameters, testClass, beforeMethods, afterMethods, groupMethods));
997f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      failureCount = handleInvocationResults(tm, result, failedInstances,
998bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust          failureCount, expectedExceptionHolder, true, true /* collect results */);
999f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1000f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    while (!failedInstances.isEmpty());
1001f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return failureCount;
1002f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
100389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1004f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private ParameterBag createParameters(ITestClass testClass,
1005f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                        ITestNGMethod testMethod,
1006f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                        Map<String, String> parameters,
1007f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                        Map<String, String> allParameterNames,
1008facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust                                        Object[] parameterValues,
1009f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                        XmlSuite suite,
10108b9443a6ada20a1e9f3852b715f3e789a0f8d490Cédric Beust                                        ITestContext testContext,
1011da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust                                        Object fedInstance,
1012da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust                                        ITestResult testResult)
10138778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust  {
10148778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust    Object instance;
10158778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust    if (fedInstance != null) {
10168778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust      instance = fedInstance;
10178778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust    }
10188778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust    else {
10198778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust      Object[] instances = testClass.getInstances(true);
10208778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust      instance = instances[0];
10218778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust    }
102289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
102389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin    ParameterBag bag= handleParameters(testMethod,
1024da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust        instance, allParameterNames, parameters, parameterValues, suite, testContext, fedInstance,
1025da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust        testResult);
1026f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1027f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return bag;
1028f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
102989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1030f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1031f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * Invoke all the test methods.  Note the plural:  the method passed in
1032f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * parameter might be invoked several times if the test class it belongs
1033f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * to has more than one instance (i.e., if an @Factory method has been
1034f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * declared somewhere that returns several instances of this TestClass).
1035f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * If no @Factory method was specified, testMethod will only be invoked
1036f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * once.
1037f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * <p/>
1038f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * Note that this method also takes care of invoking the beforeTestMethod
1039f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * and afterTestMethod, if any.
104089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin   *
104189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin   * Note (alex): this method can be refactored to use a SingleTestMethodWorker that
104289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin   * directly invokes
1043f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * {@link #invokeTestMethod(Object[], ITestNGMethod, Object[], XmlSuite, Map, ITestClass, ITestNGMethod[], ITestNGMethod[], ConfigurationGroupMethods)}
1044f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * and this would simplify the implementation (see how DataTestMethodWorker is used)
1045f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
1046423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust  @Override
1047f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  public List<ITestResult> invokeTestMethods(ITestNGMethod testMethod,
1048f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             ITestNGMethod[] allTestMethods,
1049f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             int testMethodIndex,
1050f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             XmlSuite suite,
1051f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             Map<String, String> parameters,
1052f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             ConfigurationGroupMethods groupMethods,
1053f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             Object[] instances,
1054f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             ITestContext testContext)
1055f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
1056f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Potential bug here if the test method was declared on a parent class
105789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin    assert null != testMethod.getTestClass()
1058f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    : "COULDN'T FIND TESTCLASS FOR " + testMethod.getMethod().getDeclaringClass();
105989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1060ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust    List<ITestResult> result = Lists.newArrayList();
106189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1062f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    ITestClass testClass= testMethod.getTestClass();
10630b2ac5eab08098da2c2b63d4a3f87ba72ad5d6a1nullin    long start = System.currentTimeMillis();
1064f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1065f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
1066f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // TODO:
1067f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // - [DONE] revisit invocationCount, threadPoolSize values
1068f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // - try to remove the isWithinThreadedMethod: still needed to determine the @BeforeMethod + @AfterMethod
1069f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // - [DONE] solve the results different approaches: assignment and addAll
1070f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
10716cf2e96a6b18fe7eecc44cac44bb0690a162f416Cédric Beust    // For invocationCount>1 and threadPoolSize>1 the method will be invoked on a thread pool
1072331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust    long timeOutInvocationCount = testMethod.getInvocationTimeOut();
1073331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust    boolean onlyOne = testMethod.getThreadPoolSize() > 1 ||
1074331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust      timeOutInvocationCount > 0;
107589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1076331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust    int invocationCount = onlyOne ? 1 : testMethod.getInvocationCount();
1077f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    int failureCount = 0;
1078f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
107989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin    ExpectedExceptionsHolder expectedExceptionHolder =
1080f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        MethodHelper.findExpectedExceptions(m_annotationFinder, testMethod.getMethod());
1081f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    while(invocationCount-- > 0) {
1082e934f66fb4fb247ebf5fec45770bc6820fbba29anullin      boolean okToProceed = checkDependencies(testMethod, allTestMethods);
1083f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1084f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if (okToProceed) {
1085f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        //
1086f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // Invoke the test method if it's enabled
1087f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        //
1088f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if (MethodHelper.isEnabled(testMethod.getMethod(), m_annotationFinder)) {
108962009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust          //
109062009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust          // If threadPoolSize specified, run this method in its own pool thread.
109162009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust          //
109262009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust          if (testMethod.getThreadPoolSize() > 1 && testMethod.getInvocationCount() > 1) {
109389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin              return invokePooledTestMethods(testMethod, allTestMethods, suite,
109462009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust                  parameters, groupMethods, testContext);
109562009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust          }
109689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
109762009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust          //
109862009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust          // No threads, regular invocation
109962009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust          //
110062009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust          else {
110162009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust            ITestNGMethod[] beforeMethods = filterMethods(testClass, testClass.getBeforeTestMethods());
110262009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust            ITestNGMethod[] afterMethods = filterMethods(testClass, testClass.getAfterTestMethods());
1103f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
11040f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beust            Map<String, String> allParameterNames = Maps.newHashMap();
110562009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust            ParameterBag bag = createParameters(testClass, testMethod,
1106da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust                parameters, allParameterNames, null, suite, testContext, instances[0],
1107da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust                null);
1108f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
110962009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust            if(bag.hasErrors()) {
111089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin              failureCount = handleInvocationResults(testMethod,
111162009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust                  bag.errorResults, null, failureCount, expectedExceptionHolder, true,
111262009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust                  true /* collect results */);
1113252c45802df7624a4fafbce810e05d22048f437bCédric Beust              registerSkippedTestResult(testMethod, instances[0], start);
111462009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust              continue;
111562009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust            }
111689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
111762009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust            Iterator<Object[]> allParameterValues= bag.parameterHolder.parameters;
111889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
111943f186d3baa643622b94876b945380a4b7e29d55Cédric Beust            int parametersIndex = 0;
112089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
112143f186d3baa643622b94876b945380a4b7e29d55Cédric Beust            try {
112201e59f7bdf6515f065bd697832db53253ca78b1aCédric Beust              List<TestMethodWithDataProviderMethodWorker> workers = Lists.newArrayList();
1123c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust
112443f186d3baa643622b94876b945380a4b7e29d55Cédric Beust              if (bag.parameterHolder.origin == ParameterHolder.ORIGIN_DATA_PROVIDER &&
112543f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                  bag.parameterHolder.dataProviderHolder.annotation.isParallel()) {
112643f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                while (allParameterValues.hasNext()) {
112728e899a6c1620c8d07cb04a92f96658550e4af16nullin                  Object[] parameterValues = injectParameters(allParameterValues.next(),
112828e899a6c1620c8d07cb04a92f96658550e4af16nullin                      testMethod.getMethod(), testContext, null /* test result */);
112943f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                  TestMethodWithDataProviderMethodWorker w =
113043f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    new TestMethodWithDataProviderMethodWorker(this,
113143f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                        testMethod, parametersIndex,
113243f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                        parameterValues, instances, suite, parameters, testClass,
113343f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                        beforeMethods, afterMethods, groupMethods,
113443f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                        expectedExceptionHolder, testContext, m_skipFailedInvocationCounts,
113543f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                        invocationCount, failureCount, m_notifier);
113643f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                  workers.add(w);
1137927a6d8a655520943e3a8a9ea9f09cbfe56f2ae6Cédric Beust                  // testng387: increment the param index in the bag.
1138927a6d8a655520943e3a8a9ea9f09cbfe56f2ae6Cédric Beust                  parametersIndex++;
113943f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                }
114043f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                PoolService ps = PoolService.getInstance();
114143f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                List<ITestResult> r = ps.submitTasksAndWait(testMethod, workers);
114243f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                result.addAll(r);
114343f186d3baa643622b94876b945380a4b7e29d55Cédric Beust
114443f186d3baa643622b94876b945380a4b7e29d55Cédric Beust              } else {
114543f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                while (allParameterValues.hasNext()) {
114628e899a6c1620c8d07cb04a92f96658550e4af16nullin                  Object[] parameterValues = injectParameters(allParameterValues.next(),
114728e899a6c1620c8d07cb04a92f96658550e4af16nullin                      testMethod.getMethod(), testContext, null /* test result */);
114843f186d3baa643622b94876b945380a4b7e29d55Cédric Beust
1149ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust                  List<ITestResult> tmpResults = Lists.newArrayList();
115043f186d3baa643622b94876b945380a4b7e29d55Cédric Beust
115143f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                  try {
115243f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    tmpResults.addAll(invokeTestMethod(instances,
115343f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                                                       testMethod,
115443f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                                                       parameterValues,
1155927a6d8a655520943e3a8a9ea9f09cbfe56f2ae6Cédric Beust                                                       parametersIndex,
115643f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                                                       suite,
115743f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                                                       parameters,
115843f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                                                       testClass,
115943f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                                                       beforeMethods,
116043f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                                                       afterMethods,
116143f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                                                       groupMethods));
1162f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                  }
116343f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                  finally {
1164ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust                    List<Object> failedInstances = Lists.newArrayList();
116543f186d3baa643622b94876b945380a4b7e29d55Cédric Beust
116643f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    failureCount = handleInvocationResults(testMethod, tmpResults,
116743f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                        failedInstances, failureCount, expectedExceptionHolder, true,
116843f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                        false /* don't collect results */);
116943f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    if (failedInstances.isEmpty()) {
117043f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                      result.addAll(tmpResults);
117143f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    } else {
117243f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                      for (int i = 0; i < failedInstances.size(); i++) {
1173ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust                        List<ITestResult> retryResults = Lists.newArrayList();
117443f186d3baa643622b94876b945380a4b7e29d55Cédric Beust
117589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                        failureCount =
117643f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                         retryFailed(failedInstances.toArray(),
117743f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                         i, testMethod, suite, testClass, beforeMethods,
117843f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                         afterMethods, groupMethods, retryResults,
117943f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                         failureCount, expectedExceptionHolder,
118043f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                         testContext, parameters, parametersIndex);
118143f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                      result.addAll(retryResults);
1182c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust                      }
118343f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    }
118489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
118543f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    //
118643f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    // If we have a failure, skip all the
118743f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    // other invocationCounts
118843f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    //
118989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
119043f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    // If not specified globally, use the attribute
119143f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    // on the annotation
119243f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    //
119343f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    if (! m_skipFailedInvocationCounts) {
119443f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                      m_skipFailedInvocationCounts = testMethod.skipFailedInvocations();
119543f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    }
119643f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    if (failureCount > 0 && m_skipFailedInvocationCounts) {
119743f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                      while (invocationCount-- > 0) {
1198252c45802df7624a4fafbce810e05d22048f437bCédric Beust                        result.add(registerSkippedTestResult(testMethod, instances[0], start));
1199c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust                      }
120043f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                      break;
120143f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    }
120243f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                  }// end
120343f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                parametersIndex++;
1204c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust              }
120562009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust            }
120643f186d3baa643622b94876b945380a4b7e29d55Cédric Beust          }
120743f186d3baa643622b94876b945380a4b7e29d55Cédric Beust          catch (Throwable cause) {
120889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin            ITestResult r =
120943f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                new TestResult(testMethod.getTestClass(),
121043f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                  instances[0],
121143f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                  testMethod,
121243f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                  cause,
121343f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                  start,
121443f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                  System.currentTimeMillis());
121543f186d3baa643622b94876b945380a4b7e29d55Cédric Beust              r.setStatus(TestResult.FAILURE);
121643f186d3baa643622b94876b945380a4b7e29d55Cédric Beust              result.add(r);
121743f186d3baa643622b94876b945380a4b7e29d55Cédric Beust              runTestListeners(r);
121843f186d3baa643622b94876b945380a4b7e29d55Cédric Beust              m_notifier.addFailedTest(testMethod, r);
121943f186d3baa643622b94876b945380a4b7e29d55Cédric Beust            } // catch
1220c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust          }
122189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin        } // isTestMethodEnabled
1222f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1223f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      } // okToProceed
1224f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      else {
1225f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        //
1226f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // Test is being skipped
1227f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        //
1228f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        ITestResult testResult= new TestResult(testClass, null,
1229f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                               testMethod,
1230f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                               null,
1231f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                               start,
1232f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                               System.currentTimeMillis());
1233f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        testResult.setEndMillis(System.currentTimeMillis());
1234f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        String missingGroup = testMethod.getMissingGroup();
1235f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if (missingGroup != null) {
123689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin          testResult.setThrowable(new Throwable("Method " + testMethod
1237f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              + " depends on nonexistent group \"" + missingGroup + "\""));
1238f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1239f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1240f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        testResult.setStatus(ITestResult.SKIP);
1241a4e6892fbfa21c968737eaf4e4f1e4b0b7f9163eCédric Beust        result.add(testResult);
1242f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        runTestListeners(testResult);
1243f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1244f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
124589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1246f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return result;
124789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1248f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  } // invokeTestMethod
1249f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1250252c45802df7624a4fafbce810e05d22048f437bCédric Beust  private ITestResult registerSkippedTestResult(ITestNGMethod testMethod, Object instance,
1251252c45802df7624a4fafbce810e05d22048f437bCédric Beust      long start) {
125289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin    ITestResult result =
1253252c45802df7624a4fafbce810e05d22048f437bCédric Beust      new TestResult(testMethod.getTestClass(),
1254252c45802df7624a4fafbce810e05d22048f437bCédric Beust        instance,
1255252c45802df7624a4fafbce810e05d22048f437bCédric Beust        testMethod,
1256252c45802df7624a4fafbce810e05d22048f437bCédric Beust        null,
1257252c45802df7624a4fafbce810e05d22048f437bCédric Beust        start,
1258252c45802df7624a4fafbce810e05d22048f437bCédric Beust        System.currentTimeMillis());
1259252c45802df7624a4fafbce810e05d22048f437bCédric Beust    result.setStatus(TestResult.SKIP);
1260252c45802df7624a4fafbce810e05d22048f437bCédric Beust    runTestListeners(result);
1261252c45802df7624a4fafbce810e05d22048f437bCédric Beust
1262252c45802df7624a4fafbce810e05d22048f437bCédric Beust    return result;
1263252c45802df7624a4fafbce810e05d22048f437bCédric Beust  }
1264252c45802df7624a4fafbce810e05d22048f437bCédric Beust
126528e899a6c1620c8d07cb04a92f96658550e4af16nullin  /**
126628e899a6c1620c8d07cb04a92f96658550e4af16nullin   * Gets an array of parameter values returned by data provider or the ones that
126728e899a6c1620c8d07cb04a92f96658550e4af16nullin   * are injected based on parameter type. The method also checks for {@code NoInjection}
126828e899a6c1620c8d07cb04a92f96658550e4af16nullin   * annotation
126928e899a6c1620c8d07cb04a92f96658550e4af16nullin   * @param parameterValues parameter values from a data provider
127028e899a6c1620c8d07cb04a92f96658550e4af16nullin   * @param method method to be invoked
127128e899a6c1620c8d07cb04a92f96658550e4af16nullin   * @param context test context
127228e899a6c1620c8d07cb04a92f96658550e4af16nullin   * @param testResult test result
127328e899a6c1620c8d07cb04a92f96658550e4af16nullin   * @return
127428e899a6c1620c8d07cb04a92f96658550e4af16nullin   */
12751e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust  private Object[] injectParameters(Object[] parameterValues, Method method,
127628e899a6c1620c8d07cb04a92f96658550e4af16nullin      ITestContext context, ITestResult testResult)
127728e899a6c1620c8d07cb04a92f96658550e4af16nullin    throws TestNGException {
12781e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust    List<Object> vResult = Lists.newArrayList();
12791e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust    int i = 0;
128028e899a6c1620c8d07cb04a92f96658550e4af16nullin    int numValues = parameterValues.length;
128128e899a6c1620c8d07cb04a92f96658550e4af16nullin    int numParams = method.getParameterTypes().length;
128228e899a6c1620c8d07cb04a92f96658550e4af16nullin
128328e899a6c1620c8d07cb04a92f96658550e4af16nullin    if (numValues > numParams) {
128428e899a6c1620c8d07cb04a92f96658550e4af16nullin      throw new TestNGException("Number of parameter values passed in using "
128528e899a6c1620c8d07cb04a92f96658550e4af16nullin          + "data provider exceeds number of parameters defined on test method");
128628e899a6c1620c8d07cb04a92f96658550e4af16nullin    }
128728e899a6c1620c8d07cb04a92f96658550e4af16nullin
128828e899a6c1620c8d07cb04a92f96658550e4af16nullin    // beyond this, numValues <= numParams
12891e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust    for (Class<?> cls : method.getParameterTypes()) {
1290aba3ac2f9fc3e370339b911598f62c7ffb6752aaCédric Beust      Annotation[] annotations = method.getParameterAnnotations()[i];
1291aba3ac2f9fc3e370339b911598f62c7ffb6752aaCédric Beust      boolean noInjection = false;
1292aba3ac2f9fc3e370339b911598f62c7ffb6752aaCédric Beust      for (Annotation a : annotations) {
1293aba3ac2f9fc3e370339b911598f62c7ffb6752aaCédric Beust        if (a instanceof NoInjection) {
1294aba3ac2f9fc3e370339b911598f62c7ffb6752aaCédric Beust          noInjection = true;
1295aba3ac2f9fc3e370339b911598f62c7ffb6752aaCédric Beust          break;
1296aba3ac2f9fc3e370339b911598f62c7ffb6752aaCédric Beust        }
1297aba3ac2f9fc3e370339b911598f62c7ffb6752aaCédric Beust      }
12981e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust      Object injected = Parameters.getInjectedParameter(cls, method, context, testResult);
1299aba3ac2f9fc3e370339b911598f62c7ffb6752aaCédric Beust      if (injected != null && ! noInjection) {
13001e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust        vResult.add(injected);
13011e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust      } else {
130228e899a6c1620c8d07cb04a92f96658550e4af16nullin        try {
130328e899a6c1620c8d07cb04a92f96658550e4af16nullin          vResult.add(parameterValues[i++]);
130428e899a6c1620c8d07cb04a92f96658550e4af16nullin        } catch (ArrayIndexOutOfBoundsException ex) {
130528e899a6c1620c8d07cb04a92f96658550e4af16nullin          throw new TestNGException("Number of parameter values passed in using "
130628e899a6c1620c8d07cb04a92f96658550e4af16nullin                + "data provider is less than number of parameters defined on "
130728e899a6c1620c8d07cb04a92f96658550e4af16nullin                + "test method and TestNG is unable in inject a suitable object", ex);
130828e899a6c1620c8d07cb04a92f96658550e4af16nullin        }
13091e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust      }
13101e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust    }
13111e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust    return vResult.toArray(new Object[vResult.size()]);
13121e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust  }
13131e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust
1314f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private ParameterBag handleParameters(ITestNGMethod testMethod,
1315f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Object instance,
1316f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Map<String, String> allParameterNames,
1317f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Map<String, String> parameters,
1318facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust      Object[] parameterValues,
1319f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      XmlSuite suite,
13208b9443a6ada20a1e9f3852b715f3e789a0f8d490Cédric Beust      ITestContext testContext,
1321da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust      Object fedInstance,
1322da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust      ITestResult testResult)
1323f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
1324f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    try {
1325c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust      return new ParameterBag(
1326c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust          Parameters.handleParameters(testMethod,
132789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin            allParameterNames,
132889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin            instance,
1329c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust            new Parameters.MethodParameters(parameters, parameterValues,
133089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                testMethod.getMethod(), testContext, testResult),
133189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin            suite,
1332c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust            m_annotationFinder,
133389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin            fedInstance),
1334c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust          null);
1335f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1336f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    catch(Throwable cause) {
133789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      return new ParameterBag(null,
1338f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          new TestResult(
133989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin              testMethod.getTestClass(),
134089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin              instance,
134189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin              testMethod,
134289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin              cause,
1343f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              System.currentTimeMillis(),
1344f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              System.currentTimeMillis()));
1345f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
134689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1347f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
134889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1349f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
135089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin   * Invokes a method that has a specified threadPoolSize.
1351f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
135289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin  private List<ITestResult> invokePooledTestMethods(ITestNGMethod testMethod,
135389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                    ITestNGMethod[] allTestMethods,
135489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                    XmlSuite suite,
135589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                    Map<String, String> parameters,
1356f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                                    ConfigurationGroupMethods groupMethods,
135789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                    ITestContext testContext)
1358f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
1359f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
1360f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Create the workers
1361f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
1362f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin    List<IWorker<ITestNGMethod>> workers = Lists.newArrayList();
136389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1364f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for (int i = 0; i < testMethod.getInvocationCount(); i++) {
1365f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // we use clones for reporting purposes
1366f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      ITestNGMethod clonedMethod= testMethod.clone();
1367f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      clonedMethod.setInvocationCount(1);
1368f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      clonedMethod.setThreadPoolSize(1);
1369f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1370f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      MethodInstance mi = new MethodInstance(clonedMethod, clonedMethod.getTestClass().getInstances(true));
1371f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      workers.add(new SingleTestMethodWorker(this,
1372f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          mi,
137389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin          suite,
1374f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          parameters,
1375f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          allTestMethods,
1376f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          testContext));
1377f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1378f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1379f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return runWorkers(testMethod, workers, testMethod.getThreadPoolSize(), groupMethods, suite, parameters);
1380f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
138189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1382f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1383f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param testMethod
1384f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param result
1385f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param failureCount
1386bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust   * @param expectedExceptionsHolder
1387f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return
1388f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
138989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin  int handleInvocationResults(ITestNGMethod testMethod,
1390f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                      List<ITestResult> result,
1391f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                      List<Object> failedInstances,
139289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                      int failureCount,
1393bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust                                      ExpectedExceptionsHolder expectedExceptionsHolder,
13946216d78ae0757b7d57aa6e94cc041447d610724dCédric Beust                                      boolean triggerListeners,
13956216d78ae0757b7d57aa6e94cc041447d610724dCédric Beust                                      boolean collectResults)
13966216d78ae0757b7d57aa6e94cc041447d610724dCédric Beust  {
1397f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
1398f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Go through all the results and create a TestResult for each of them
1399f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
1400ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust    List<ITestResult> resultsToRetry = Lists.newArrayList();
1401f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1402f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for (int i = 0; i < result.size(); i++) {
1403f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      ITestResult testResult = result.get(i);
1404f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Throwable ite= testResult.getThrowable();
1405f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      int status= testResult.getStatus();
1406f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1407f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // Exception thrown?
14084c02d89d66fe0319dd20083e705addd6b5f3e8cdCédric Beust      if (ite != null) {
1409f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1410f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        //  Invocation caused an exception, see if the method was annotated with @ExpectedException
1411bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust        if (isExpectedException(ite, expectedExceptionsHolder)) {
1412bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust          if (messageRegExpMatches(expectedExceptionsHolder.messageRegExp, ite)) {
1413bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust            testResult.setStatus(ITestResult.SUCCESS);
1414bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust            status= ITestResult.SUCCESS;
1415bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust          }
1416bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust          else {
1417bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust            testResult.setThrowable(
1418bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust                new TestException("The exception was thrown with the wrong message:" +
141989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                    " expected \"" + expectedExceptionsHolder.messageRegExp + "\"" +
1420fa37eadd5874782d0020b1df413489b0514888b5Cédric Beust                    " but got \"" + ite.getMessage() + "\"", ite));
1421bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust            status= ITestResult.FAILURE;
1422bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust          }
14234c02d89d66fe0319dd20083e705addd6b5f3e8cdCédric Beust        } else if (ite != null && expectedExceptionsHolder != null) {
14244c02d89d66fe0319dd20083e705addd6b5f3e8cdCédric Beust          testResult.setThrowable(
14254c02d89d66fe0319dd20083e705addd6b5f3e8cdCédric Beust              new TestException("Expected exception "
14264c02d89d66fe0319dd20083e705addd6b5f3e8cdCédric Beust                 + expectedExceptionsHolder.expectedClasses[0].getName()
1427fa37eadd5874782d0020b1df413489b0514888b5Cédric Beust                 + " but got " + ite, ite));
14284c02d89d66fe0319dd20083e705addd6b5f3e8cdCédric Beust          status= ITestResult.FAILURE;
1429f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1430f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        else if (SkipException.class.isAssignableFrom(ite.getClass())){
1431f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          SkipException skipEx= (SkipException) ite;
1432f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          if(skipEx.isSkip()) {
14334c02d89d66fe0319dd20083e705addd6b5f3e8cdCédric Beust            status = ITestResult.SKIP;
1434f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
1435f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          else {
1436f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            handleException(ite, testMethod, testResult, failureCount++);
14374c02d89d66fe0319dd20083e705addd6b5f3e8cdCédric Beust            status = ITestResult.FAILURE;
1438f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
1439f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1440f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        else {
1441f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          handleException(ite, testMethod, testResult, failureCount++);
1442f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          status= testResult.getStatus();
1443f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1444f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1445f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1446f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // No exception thrown, make sure we weren't expecting one
1447bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust      else if(status != ITestResult.SKIP && expectedExceptionsHolder != null) {
1448bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust        Class<?>[] classes = expectedExceptionsHolder.expectedClasses;
1449bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust        if (classes != null && classes.length > 0) {
1450f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          testResult.setThrowable(
145127e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust              new TestException("Method " + testMethod + " should have thrown an exception of "
145227e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust                  + expectedExceptionsHolder.expectedClasses[0]));
1453f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          status= ITestResult.FAILURE;
1454f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1455f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1456f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1457f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      testResult.setStatus(status);
1458f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1459f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      boolean retry = false;
146089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1461f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if (testResult.getStatus() == ITestResult.FAILURE) {
1462f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        IRetryAnalyzer retryAnalyzer = testMethod.getRetryAnalyzer();
1463f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
14649ae4e70bde40b32777755f9294a5b1b06b420005Cédric Beust        if (retryAnalyzer != null && failedInstances != null) {
1465f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          retry = retryAnalyzer.retry(testResult);
1466f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1467f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1468f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if (retry) {
1469f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          resultsToRetry.add(testResult);
1470f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          if (failedInstances != null) {
14719ae4e70bde40b32777755f9294a5b1b06b420005Cédric Beust            failedInstances.add(testResult.getInstance());
1472f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
1473f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
147489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      }
14756216d78ae0757b7d57aa6e94cc041447d610724dCédric Beust      if (!retry || collectResults) {
1476f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // Collect the results
1477f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if(ITestResult.SUCCESS == status) {
1478f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          m_notifier.addPassedTest(testMethod, testResult);
1479f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1480f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        else if(ITestResult.SKIP == status) {
1481f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          m_notifier.addSkippedTest(testMethod, testResult);
1482f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1483f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        else if(ITestResult.FAILURE == status) {
1484f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          m_notifier.addFailedTest(testMethod, testResult);
1485f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1486f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        else if(ITestResult.SUCCESS_PERCENTAGE_FAILURE == status) {
1487f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          m_notifier.addFailedButWithinSuccessPercentageTest(testMethod, testResult);
1488f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1489f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        else {
1490f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          assert false : "UNKNOWN STATUS:" + status;
1491f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
14927e735d9079026e11bc7cd06dab2b99d9ff9cd6c3Cédric Beust//        if (triggerListeners && status != ITestResult.SUCCESS) {
14937e735d9079026e11bc7cd06dab2b99d9ff9cd6c3Cédric Beust//          runTestListeners(testResult);
14947e735d9079026e11bc7cd06dab2b99d9ff9cd6c3Cédric Beust//        }
1495f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1496f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    } // for results
149789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1498f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return removeResultsToRetryFromResult(resultsToRetry, result, failureCount);
1499f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
150089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1501bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust  /**
1502bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust   *   message / regEx  .*      other
1503bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust   *   null             true    false
1504bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust   *   non-null         true    match
1505bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust   */
1506bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust  private boolean messageRegExpMatches(String messageRegExp, Throwable ite) {
1507bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust    if (".*".equals(messageRegExp)) {
1508bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust      return true;
1509bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust    } else {
15100f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      if (ite.getMessage() == null) {
15110f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        return false;
15120f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      } else {
15130f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        return Pattern.matches(messageRegExp, ite.getMessage());
15140f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      }
1515bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust    }
1516bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust  }
1517bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust
1518f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private int removeResultsToRetryFromResult(List<ITestResult> resultsToRetry,
1519f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      List<ITestResult> result, int failureCount) {
1520f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if (resultsToRetry != null) {
1521f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for (ITestResult res : resultsToRetry) {
1522f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        result.remove(res);
1523f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        failureCount--;
1524f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1525f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1526f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return failureCount;
1527f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
152889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1529f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1530f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * To reduce thread contention and also to correctly handle thread-confinement
1531f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * this method invokes the @BeforeGroups and @AfterGroups corresponding to the current @Test method.
1532f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
153389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin  private List<ITestResult> runWorkers(ITestNGMethod testMethod,
1534c4cadec5fb52419e211120aa93b6118a4ab756ecCédric Beust      List<IWorker<ITestNGMethod>> workers,
153589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      int threadPoolSize,
153689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      ConfigurationGroupMethods groupMethods,
153789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      XmlSuite suite,
1538f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Map<String, String> parameters)
1539f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
154089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin    // Invoke @BeforeGroups on the original method (reduce thread contention,
1541c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust    // and also solve thread confinement)
1542f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    ITestClass testClass= testMethod.getTestClass();
1543f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    Object[] instances = testClass.getInstances(true);
1544f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for(Object instance: instances) {
1545f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      invokeBeforeGroupsConfigurations(testClass, testMethod, groupMethods, suite, parameters, instance);
1546f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
154789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
154889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1549f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    long maxTimeOut= -1; // 10 seconds
1550f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1551f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin    for(IWorker<ITestNGMethod> tmw : workers) {
1552f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin      long mt= tmw.getTimeOut();
1553f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if(mt > maxTimeOut) {
1554f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        maxTimeOut= mt;
1555f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1556f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
155789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1558f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    ThreadUtil.execute(workers, threadPoolSize, maxTimeOut, true);
1559f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1560f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
1561f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Collect all the TestResults
1562f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
1563ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust    List<ITestResult> result = Lists.newArrayList();
1564f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin    for (IWorker<ITestNGMethod> tmw : workers) {
1565f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin      if (tmw instanceof TestMethodWorker) {
1566f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin        result.addAll(((TestMethodWorker)tmw).getTestResults());
1567f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin      }
1568f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
156989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1570f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for(Object instance: instances) {
1571f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      invokeAfterGroupsConfigurations(testClass, testMethod, groupMethods, suite, parameters, instance);
1572f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
157389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1574f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return result;
1575f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1576f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1577f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1578e934f66fb4fb247ebf5fec45770bc6820fbba29anullin   * Checks to see of the test method has certain dependencies that prevents
1579e934f66fb4fb247ebf5fec45770bc6820fbba29anullin   * TestNG from executing it
1580e934f66fb4fb247ebf5fec45770bc6820fbba29anullin   * @param testMethod test method being checked for
1581f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param testClass
1582f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return dependencies have been run successfully
1583f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
1584e934f66fb4fb247ebf5fec45770bc6820fbba29anullin  private boolean checkDependencies(ITestNGMethod testMethod,
1585a4e6892fbfa21c968737eaf4e4f1e4b0b7f9163eCédric Beust      ITestNGMethod[] allTestMethods)
1586f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
1587e934f66fb4fb247ebf5fec45770bc6820fbba29anullin    boolean result = true;
1588f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1589e934f66fb4fb247ebf5fec45770bc6820fbba29anullin    // If this method is marked alwaysRun, no need to check for its dependencies
1590f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if (testMethod.isAlwaysRun()) {
1591f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      return true;
1592f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
159389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1594f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Any missing group?
15950f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin    if (testMethod.getMissingGroup() != null
1596e934f66fb4fb247ebf5fec45770bc6820fbba29anullin          && !testMethod.ignoreMissingDependencies()) {
1597e934f66fb4fb247ebf5fec45770bc6820fbba29anullin      return false;
1598f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1599f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1600f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // If this method depends on groups, collect all the methods that
1601f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // belong to these groups and make sure they have been run successfully
1602e934f66fb4fb247ebf5fec45770bc6820fbba29anullin    if (dependsOnGroups(testMethod)) {
1603e934f66fb4fb247ebf5fec45770bc6820fbba29anullin      String[] groupsDependedUpon = testMethod.getGroupsDependedUpon();
1604f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1605f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // Get all the methods that belong to the group depended upon
16060f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      for (String element : groupsDependedUpon) {
160789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin        ITestNGMethod[] methods =
1608b1c182d51b05a40ac5350e562503a94d024a7c80nullin          MethodGroupsHelper.findMethodsThatBelongToGroup(testMethod,
1609f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              m_testContext.getAllTestMethods(),
16100f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin              element);
1611f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1612f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        result = result && haveBeenRunSuccessfully(methods);
1613f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1614f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    } // depends on groups
1615f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1616f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // If this method depends on other methods, make sure all these other
1617f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // methods have been run successfully
1618e934f66fb4fb247ebf5fec45770bc6820fbba29anullin    if (result && dependsOnMethods(testMethod)) {
161989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      ITestNGMethod[] methods =
1620b1c182d51b05a40ac5350e562503a94d024a7c80nullin        MethodHelper.findDependedUponMethods(testMethod, allTestMethods);
1621f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1622e934f66fb4fb247ebf5fec45770bc6820fbba29anullin      result = result && haveBeenRunSuccessfully(methods);
1623f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1624f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1625f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return result;
1626f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1627f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1628f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1629f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return true if all the methods have been run successfully
1630f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
1631f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private boolean haveBeenRunSuccessfully(ITestNGMethod[] methods) {
1632f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Make sure the method has been run successfully
16330f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin    for (ITestNGMethod method : methods) {
16340f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      Set<ITestResult> results= m_notifier.getPassedTests(method);
16350f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      Set<ITestResult> failedresults= m_notifier.getFailedTests(method);
163689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1637d3c04c36b8f179fd5aa1b53711a5b909cde06d09nalin.makar@gmail.com      // If failed results were returned, then these tests didn't pass
16380f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      if (failedresults != null && failedresults.size() > 0) {
16390f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        return false;
16400f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      }
164189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1642f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // If no results were returned, then these tests didn't pass
16430f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      if (results == null || results.size() == 0) {
16440f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        return false;
16450f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      }
164689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1647f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for (ITestResult result : results) {
1648f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if(!result.isSuccess()) {
1649f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          return false;
1650f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1651f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1652f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1653f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1654f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return true;
1655f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1656f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1657f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1658f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * An exception was thrown by the test, determine if this method
1659f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * should be marked as a failure or as failure_but_within_successPercentage
1660f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
1661f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private void handleException(Throwable throwable,
1662f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                               ITestNGMethod testMethod,
1663f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                               ITestResult testResult,
1664f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                               int failureCount) {
1665f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    testResult.setThrowable(throwable);
1666f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    int successPercentage= testMethod.getSuccessPercentage();
1667f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    int invocationCount= testMethod.getInvocationCount();
166821dad3370294d6595fdddc3faf55792f60a913f1nullin    float numberOfTestsThatCanFail= ((100 - successPercentage) * invocationCount) / 100f;
1669f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1670f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if(failureCount < numberOfTestsThatCanFail) {
1671f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      testResult.setStatus(ITestResult.SUCCESS_PERCENTAGE_FAILURE);
1672f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1673f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    else {
1674f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      testResult.setStatus(ITestResult.FAILURE);
1675f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1676f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1677f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1678f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1679f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1680f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param ite The exception that was just thrown
1681f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param expectedExceptions The list of expected exceptions for this
1682f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * test method
1683f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return true if the exception that was just thrown is part of the
1684f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * expected exceptions
1685f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
1686bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust  private boolean isExpectedException(Throwable ite, ExpectedExceptionsHolder exceptionHolder) {
1687bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust    if (exceptionHolder == null) {
1688f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      return false;
1689f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
169027e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust
169127e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust    // TestException is the wrapper exception that TestNG will be throwing when an exception was
169227e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust    // expected but not thrown
169327e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust    if (ite.getClass() == TestException.class) {
169427e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust      return false;
169527e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust    }
169627e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust
1697bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust    Class<?>[] exceptions = exceptionHolder.expectedClasses;
1698f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    Class<?> realExceptionClass= ite.getClass();
1699f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
17000f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin    for (Class<?> exception : exceptions) {
17010f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      if (exception.isAssignableFrom(realExceptionClass)) {
1702f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        return true;
1703f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1704f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1705f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1706f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return false;
1707f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1708f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1709f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1710f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return Only the ITestNGMethods applicable for this testClass
1711f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
1712f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private ITestNGMethod[] filterMethods(IClass testClass, ITestNGMethod[] methods) {
1713ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust    List<ITestNGMethod> vResult= Lists.newArrayList();
1714f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1715f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for(ITestNGMethod tm : methods) {
1716f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if(tm.canRunFromClass(testClass)) {
1717f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        log(9, "Keeping method " + tm + " for class " + testClass);
1718f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        vResult.add(tm);
1719f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1720f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      else {
1721f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        log(9, "Filtering out method " + tm + " for class " + testClass);
1722f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1723f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1724f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1725f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    ITestNGMethod[] result= vResult.toArray(new ITestNGMethod[vResult.size()]);
1726f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1727f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return result;
1728f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1729f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1730f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private ITestNGMethod[] filterMethodsUnique(IClass testClass, ITestNGMethod[] methods) {
1731f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if(null == testClass) {
1732f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      return methods;
1733f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1734f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1735ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust    List<ITestNGMethod> vResult= Lists.newArrayList();
1736f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1737f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for(ITestNGMethod tm : methods) {
17380b2ac5eab08098da2c2b63d4a3f87ba72ad5d6a1nullin      testClass= tm.getTestClass();
1739f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
17400b2ac5eab08098da2c2b63d4a3f87ba72ad5d6a1nullin      if (tm.getTestClass().getName().equals(testClass.getName())) {
1741f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        log(9, "        Keeping method " + tm + " for class " + testClass);
1742f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1743f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        vResult.add(tm);
1744f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1745f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      else {
1746f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        log(9, "        Filtering out method " + tm + " for class " + testClass);
1747f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1748f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1749f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
17500b2ac5eab08098da2c2b63d4a3f87ba72ad5d6a1nullin    return vResult.toArray(new ITestNGMethod[vResult.size()]);
1751f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1752f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1753f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1754f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return true if this method depends on certain groups.
1755f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
1756f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private boolean dependsOnGroups(ITestNGMethod tm) {
1757e934f66fb4fb247ebf5fec45770bc6820fbba29anullin    String[] groups = tm.getGroupsDependedUpon();
1758e934f66fb4fb247ebf5fec45770bc6820fbba29anullin    boolean result = (null != groups) && (groups.length > 0);
1759f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return result;
1760f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1761f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1762f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1763f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return true if this method depends on certain groups.
1764f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
1765f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private boolean dependsOnMethods(ITestNGMethod tm) {
1766e934f66fb4fb247ebf5fec45770bc6820fbba29anullin    String[] methods = tm.getMethodsDependedUpon();
1767e934f66fb4fb247ebf5fec45770bc6820fbba29anullin    boolean result = (null != methods) && (methods.length > 0);
1768f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return result;
1769f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1770f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1771f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private void runConfigurationListeners(ITestResult tr) {
1772f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for(IConfigurationListener icl: m_notifier.getConfigurationListeners()) {
1773f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      switch(tr.getStatus()) {
1774f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        case ITestResult.SKIP:
1775f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          icl.onConfigurationSkip(tr);
1776f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          break;
1777f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        case ITestResult.FAILURE:
1778f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          icl.onConfigurationFailure(tr);
1779f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          break;
1780f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        case ITestResult.SUCCESS:
1781f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          icl.onConfigurationSuccess(tr);
1782f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          break;
1783f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1784f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1785f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
178689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1787c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust  void runTestListeners(ITestResult tr) {
1788f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    runTestListeners(tr, m_notifier.getTestListeners());
1789f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
179089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1791f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  // TODO: move this from here as it is directly called from TestNG
1792f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  public static void runTestListeners(ITestResult tr, List<ITestListener> listeners) {
1793f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for (ITestListener itl : listeners) {
1794f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      switch(tr.getStatus()) {
1795f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        case ITestResult.SKIP: {
1796f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          itl.onTestSkipped(tr);
1797f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          break;
1798f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1799f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        case ITestResult.SUCCESS_PERCENTAGE_FAILURE: {
1800f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          itl.onTestFailedButWithinSuccessPercentage(tr);
1801f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          break;
1802f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1803f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        case ITestResult.FAILURE: {
1804f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          itl.onTestFailure(tr);
1805f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          break;
1806f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1807f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        case ITestResult.SUCCESS: {
1808f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          itl.onTestSuccess(tr);
1809f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          break;
1810f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1811f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1812f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        case ITestResult.STARTED: {
1813f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          itl.onTestStart(tr);
1814f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          break;
1815f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1816f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1817f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        default: {
1818f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          assert false : "UNKNOWN STATUS:" + tr;
1819f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1820f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1821f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1822f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1823f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1824f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private void log(int level, String s) {
1825f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    Utils.log("Invoker " + Thread.currentThread().hashCode(), level, s);
1826f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
182789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1828f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private static class ParameterBag {
1829c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust    final ParameterHolder parameterHolder;
1830ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust    final List<ITestResult> errorResults= Lists.newArrayList();
183189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1832c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust    public ParameterBag(ParameterHolder params, TestResult tr) {
1833c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust      parameterHolder = params;
1834f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if(tr != null) {
1835f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        errorResults.add(tr);
1836f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1837f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
183889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1839f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    public boolean hasErrors() {
1840f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      return !errorResults.isEmpty();
1841f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1842f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1843c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust
1844f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust}
1845