Invoker.java revision 1e15cc3fecfaea9149afe8124d2fd95f4356c193
1f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustpackage org.testng.internal;
2f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
3f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
4f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.IClass;
5f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.IHookable;
6398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beustimport org.testng.IInvokedMethod;
738ef90d96ee65073c1090455e7caff2a85d654e2Cédric Beustimport org.testng.IInvokedMethodListener;
868f450416a61dbdd31ba55933fe10d2b022c3908Cédric Beustimport org.testng.IInvokedMethodListener2;
9f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.IRetryAnalyzer;
10f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.ITestClass;
11f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.ITestContext;
12f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.ITestListener;
13f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.ITestNGMethod;
14f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.ITestResult;
15f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.Reporter;
16f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.SkipException;
17f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.SuiteRunState;
18f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.TestException;
19f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.TestNGException;
202d568355761a9632bf24a87984e241f8a079d724Cédric Beustimport org.testng.annotations.IConfigurationAnnotation;
21ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beustimport org.testng.collections.Lists;
220f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beustimport org.testng.collections.Maps;
23f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.internal.InvokeMethodRunnable.TestNGRuntimeException;
24f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.internal.annotations.AnnotationHelper;
25f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.internal.annotations.IAnnotationFinder;
26f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.internal.thread.ThreadExecutionException;
27f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.internal.thread.ThreadUtil;
28f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.xml.XmlClass;
29f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.xml.XmlSuite;
30f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.xml.XmlTest;
31f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
32398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beustimport java.lang.reflect.InvocationTargetException;
33398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beustimport java.lang.reflect.Method;
34398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beustimport java.util.ArrayList;
35d100d7188d4997b041c8c144876c9932a749485cCédric Beustimport java.util.Arrays;
36398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beustimport java.util.Hashtable;
37398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beustimport java.util.Iterator;
38398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beustimport java.util.List;
39398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beustimport java.util.Map;
40398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beustimport java.util.Set;
41bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beustimport java.util.regex.Pattern;
42398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust
43f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust/**
44f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust * This class is responsible for invoking methods:
45f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust * - test methods
46f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust * - configuration methods
47f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust * - possibly in a separate thread
48f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust * and then for notifying the result listeners.
49f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust *
50f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust * @author <a href="mailto:cedric@beust.com">Cedric Beust</a>
51f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust * @author <a href='mailto:the_mindstorm@evolva.ro'>Alexandru Popescu</a>
52f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust */
53f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustpublic class Invoker implements IInvoker {
54f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private ITestContext m_testContext;
55f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private ITestResultNotifier m_notifier;
56f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private IAnnotationFinder m_annotationFinder;
57f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private SuiteRunState m_suiteState;
586cf2e96a6b18fe7eecc44cac44bb0690a162f416Cédric Beust  private boolean m_skipFailedInvocationCounts;
59398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust  private List<IInvokedMethodListener> m_invokedMethodListeners;
60f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
61f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  public Invoker(ITestContext testContext,
62f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                 ITestResultNotifier notifier,
63f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                 SuiteRunState state,
646cf2e96a6b18fe7eecc44cac44bb0690a162f416Cédric Beust                 IAnnotationFinder annotationFinder,
6538ef90d96ee65073c1090455e7caff2a85d654e2Cédric Beust                 boolean skipFailedInvocationCounts,
66398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust                 List<IInvokedMethodListener> invokedMethodListeners) {
67f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    m_testContext= testContext;
68f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    m_suiteState= state;
69f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    m_notifier= notifier;
70f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    m_annotationFinder= annotationFinder;
716cf2e96a6b18fe7eecc44cac44bb0690a162f416Cédric Beust    m_skipFailedInvocationCounts = skipFailedInvocationCounts;
72398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust    m_invokedMethodListeners = invokedMethodListeners;
73f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
74f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
75f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
76f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * Invoke configuration methods if they belong to the same TestClass passed
77f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * in parameter.. <p/>TODO: Calculate ahead of time which methods should be
78f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * invoked for each class. Might speed things up for users who invoke the
79f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * same test class with different parameters in the same suite run.
80f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   *
81f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * If instance is non-null, the configuration will be run on it.  If it is null,
82f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * the configuration methods will be run on all the instances retrieved
83f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * from the ITestClass.
84f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
85f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  public void invokeConfigurations(IClass testClass,
86f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   ITestNGMethod[] allMethods,
87f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   XmlSuite suite,
88f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   Map<String, String> params,
89facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust                                   Object[] parameterValues,
90f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   Object instance)
91f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
92da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust    invokeConfigurations(testClass, null, allMethods, suite, params, parameterValues, instance,
93da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust        null);
94f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
95f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
96f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private void invokeConfigurations(IClass testClass,
97f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   ITestNGMethod currentTestMethod,
98f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   ITestNGMethod[] allMethods,
99f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   XmlSuite suite,
100f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   Map<String, String> params,
101facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust                                   Object[] parameterValues,
102da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust                                   Object instance,
103da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust                                   ITestResult testMethodResult)
104f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
105f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if(null == allMethods) {
106f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      log(5, "No @Configuration methods found");
107f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
108f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      return;
109f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
110f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
111f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    ITestNGMethod[] methods= filterMethodsUnique(testClass, allMethods);
112f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
113f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for(ITestNGMethod tm : methods) {
114f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if(null == testClass) {
115f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        testClass= tm.getTestClass();
116f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
117f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
118f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      ITestResult testResult= new TestResult(testClass,
119f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             instance,
120f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             tm,
121f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             null,
122f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             System.currentTimeMillis(),
123f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             System.currentTimeMillis());
124f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1252d568355761a9632bf24a87984e241f8a079d724Cédric Beust      IConfigurationAnnotation configurationAnnotation= null;
126f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      try {
127f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        Object[] instances= tm.getInstances();
128f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if (instances == null || instances.length == 0) instances = new Object[] { instance };
129f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        Class<?> objectClass= instances[0].getClass();
130f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        Method method= tm.getMethod();
131f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
132f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // Only run the configuration if
133f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // - the test is enabled and
134f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // - the Configuration method belongs to the same class or a parent
135f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if(MethodHelper.isEnabled(objectClass, m_annotationFinder)) {
1362d568355761a9632bf24a87984e241f8a079d724Cédric Beust          configurationAnnotation= (IConfigurationAnnotation) AnnotationHelper.findConfiguration(m_annotationFinder, method);
137f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
138e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust          if (MethodHelper.isEnabled(configurationAnnotation)) {
1390501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust            boolean isClassConfiguration = isClassConfiguration(configurationAnnotation);
1400501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust            boolean isSuiteConfiguration = isSuiteConfiguration(configurationAnnotation);
141e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            boolean alwaysRun= isAlwaysRun(configurationAnnotation);
142e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust
143e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            if(!confInvocationPassed(tm) && !alwaysRun) {
1440c3edfde6ca92fb2cfeb3072fa1c7cb08c1706c3DanFabulich              handleConfigurationSkip(tm, testResult, configurationAnnotation, suite);
145e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust              continue;
146e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            }
147e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust
148e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            log(3, "Invoking " + Utils.detailedMethodName(tm, true));
149e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust
150facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust            Object[] parameters = Parameters.createConfigurationParameters(tm.getMethod(),
151facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust                params,
152facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust                parameterValues,
153facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust                currentTestMethod,
154facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust                m_annotationFinder,
155facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust                suite,
156da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust                m_testContext,
157da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust                testMethodResult);
158e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            testResult.setParameters(parameters);
159e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust
160e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            Object[] newInstances= (null != instance) ? new Object[] { instance } : instances;
161e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust
162e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            invokeConfigurationMethod(newInstances, tm,
1630501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust              parameters, isClassConfiguration, isSuiteConfiguration, testResult);
164e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust
165e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            // TODO: probably we should trigger the event for each instance???
166e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            testResult.setEndMillis(System.currentTimeMillis());
167e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            runConfigurationListeners(testResult);
168e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust          }
169e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust          else {
170e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            log(3,
171e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust                "Skipping "
172e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust                + Utils.detailedMethodName(tm, true)
173e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust                + " because it is not enabled");
174f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
175f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        } // if is enabled
176f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        else {
177f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          log(3,
178f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              "Skipping "
179f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              + Utils.detailedMethodName(tm, true)
180f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              + " because "
181f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              + objectClass.getName()
182f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              + " is not enabled");
183f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
184f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
185f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      catch(InvocationTargetException ex) {
186f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        handleConfigurationFailure(ex, tm, testResult, configurationAnnotation, suite);
187f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
188f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      catch(TestNGException ex) {
189f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // Don't wrap TestNGExceptions, it could be a missing parameter on a
190f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // @Configuration method
191f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        handleConfigurationFailure(ex, tm, testResult, configurationAnnotation, suite);
192f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
193f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      catch(Throwable ex) { // covers the non-wrapper exceptions
194f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        handleConfigurationFailure(ex, tm, testResult, configurationAnnotation, suite);
195f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
196f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    } // for methods
197f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
198f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
199f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
200f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * Marks the currect <code>TestResult</code> as skipped and invokes the listeners.
201f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
2020c3edfde6ca92fb2cfeb3072fa1c7cb08c1706c3DanFabulich  private void handleConfigurationSkip(ITestNGMethod tm, ITestResult testResult, IConfigurationAnnotation annotation, XmlSuite suite) {
2030c3edfde6ca92fb2cfeb3072fa1c7cb08c1706c3DanFabulich    recordConfigurationInvocationFailed(tm, annotation, suite);
204f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    testResult.setStatus(ITestResult.SKIP);
205f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    runConfigurationListeners(testResult);
206f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
207f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
208f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
209f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * Is the current <code>IConfiguration</code> a class-level method.
210f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
2112d568355761a9632bf24a87984e241f8a079d724Cédric Beust  private  boolean isClassConfiguration(IConfigurationAnnotation configurationAnnotation) {
212f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if(null == configurationAnnotation) {
213f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      return false;
214f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
215f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
216f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    boolean before= (null != configurationAnnotation)
217f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      ? configurationAnnotation.getBeforeTestClass()
218f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      : false;
219f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
220f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    boolean after= (null != configurationAnnotation)
221f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      ? configurationAnnotation.getAfterTestClass()
222f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      : false;
223f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
224f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return (before || after);
225f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
226f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
227f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
2280501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust   * Is the current <code>IConfiguration</code> a suite level method.
2290501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust   */
2300501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust  private  boolean isSuiteConfiguration(IConfigurationAnnotation configurationAnnotation) {
2310501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust    if(null == configurationAnnotation) {
2320501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust      return false;
2330501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust    }
2340501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust
2350501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust    boolean before= (null != configurationAnnotation)
2360501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust      ? configurationAnnotation.getBeforeSuite()
2370501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust      : false;
2380501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust
2390501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust    boolean after= (null != configurationAnnotation)
2400501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust      ? configurationAnnotation.getAfterSuite()
2410501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust      : false;
2420501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust
2430501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust    return (before || after);
2440501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust  }
2450501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust
2460501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust  /**
247f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * Is the <code>IConfiguration</code> marked as alwaysRun.
248f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
2492d568355761a9632bf24a87984e241f8a079d724Cédric Beust  private boolean isAlwaysRun(IConfigurationAnnotation configurationAnnotation) {
250f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if(null == configurationAnnotation) {
251f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      return false;
252f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
253f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
254f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    boolean alwaysRun= false;
255f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if ((configurationAnnotation.getAfterSuite()
256f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        || configurationAnnotation.getAfterTest()
257f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        || configurationAnnotation.getAfterTestClass()
258f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        || configurationAnnotation.getAfterTestMethod())
259f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        && configurationAnnotation.getAlwaysRun())
260f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    {
261f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        alwaysRun= true;
262f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
263f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
264f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return alwaysRun;
265f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
266f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
267f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private void handleConfigurationFailure(Throwable ite,
268f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                          ITestNGMethod tm,
269f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                          ITestResult testResult,
2702d568355761a9632bf24a87984e241f8a079d724Cédric Beust                                          IConfigurationAnnotation annotation,
271f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                          XmlSuite suite)
272f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
273f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    Throwable cause= ite.getCause() != null ? ite.getCause() : ite;
274f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
275f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if(SkipException.class.isAssignableFrom(cause.getClass())) {
276f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      SkipException skipEx= (SkipException) cause;
2770c3edfde6ca92fb2cfeb3072fa1c7cb08c1706c3DanFabulich      if(skipEx.isSkip()) {
278f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        testResult.setThrowable(skipEx);
2790c3edfde6ca92fb2cfeb3072fa1c7cb08c1706c3DanFabulich        handleConfigurationSkip(tm, testResult, annotation, suite);
280f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        return;
281f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
282f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
283f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    Utils.log("", 3, "Failed to invoke @Configuration method "
284f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        + tm.getRealClass().getName() + "." + tm.getMethodName() + ":" + cause.getMessage());
285f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    handleException(cause, tm, testResult, 1);
286f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    runConfigurationListeners(testResult);
287f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
288f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
289f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // If in TestNG mode, need to take a look at the annotation to figure out
290f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // what kind of @Configuration method we're dealing with
291f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
292f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if (null != annotation) {
293f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      recordConfigurationInvocationFailed(tm, annotation, suite);
294f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
295f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
296f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
297f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
298f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return All the classes that belong to the same <test> tag as @param cls
299f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
300f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private XmlClass[] findClassesInSameTest(Class<?> cls, XmlSuite suite) {
3010f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beust    Map<String, XmlClass> vResult= Maps.newHashMap();
302f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    String className= cls.getName();
303f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for(XmlTest test : suite.getTests()) {
304f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for(XmlClass testClass : test.getXmlClasses()) {
305f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if(testClass.getName().equals(className)) {
306f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
307f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          // Found it, add all the classes in this test in the result
308f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          for(XmlClass thisClass : test.getXmlClasses()) {
309f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            vResult.put(thisClass.getName(), thisClass);
310f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
311f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          // Note:  we need to iterate through the entire suite since the same
312f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          // class might appear in several <test> tags
313f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
314f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
315f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
316f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
317f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    XmlClass[] result= vResult.values().toArray(new XmlClass[vResult.size()]);
318f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
319f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return result;
320f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
321f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
322f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
323f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * Record internally the failure of a Configuration, so that we can determine
324f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * later if @Test should be skipped.
325f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
3262d568355761a9632bf24a87984e241f8a079d724Cédric Beust  private void recordConfigurationInvocationFailed(ITestNGMethod tm, IConfigurationAnnotation annotation, XmlSuite suite) {
327f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // If beforeTestClass/beforeTestMethod or afterTestClass/afterTestMethod
328f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // failed, mark this entire class as failed, but only this class (the other
329f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // classes should keep running normally)
330ec199ce5ea28df318aeefbcf4aa463e42de410a1Cédric Beust    if (annotation.getBeforeTestClass()
331f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      || annotation.getAfterTestClass()
332f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      || annotation.getBeforeTestMethod()
333f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      || annotation.getAfterTestMethod())
334f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    {
335f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      setClassInvocationFailure(tm.getRealClass(), false);
336f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
337f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
338f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // If beforeSuite or afterSuite failed, mark *all* the classes as failed
339f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // for configurations.  At this point, the entire Suite is screwed
340f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    else if (annotation.getBeforeSuite() || annotation.getAfterSuite()) {
341f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      m_suiteState.failed();
342f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
343f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
344f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // beforeTest or afterTest:  mark all the classes in the same
345f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // <test> stanza as failed for configuration
346f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    else if (annotation.getBeforeTest() || annotation.getAfterTest()) {
347891c696c9965a0ff13e7bf6b61065121989bf9feCédric Beust      setClassInvocationFailure(tm.getRealClass(), false);
348f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      XmlClass[] classes= findClassesInSameTest(tm.getRealClass(), suite);
349f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for(XmlClass xmlClass : classes) {
350f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        setClassInvocationFailure(xmlClass.getSupportClass(), false);
351f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
352f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
353f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    String[] beforeGroups= annotation.getBeforeGroups();
354f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if(null != beforeGroups && beforeGroups.length > 0) {
355f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for(String group: beforeGroups) {
356f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        m_beforegroupsFailures.put(group, Boolean.FALSE);
357f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
358f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
359f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
360f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
361f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
362f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return true if this class has successfully run all its @Configuration
363f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * method or false if at least one of these methods failed.
364f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
365f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private boolean confInvocationPassed(ITestNGMethod method) {
366f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    boolean result= true;
367f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
368f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    Class<?> cls= method.getMethod().getDeclaringClass();
369f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
370f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if(m_suiteState.isFailed()) {
371f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      result= false;
372f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
373f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    else {
374f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if(m_classInvocationResults.containsKey(cls)) {
375f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        result= m_classInvocationResults.get(cls);
376f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
377f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      else {
378f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        for(Class<?> clazz: m_classInvocationResults.keySet()) {
3791e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust//          if (clazz == cls) {
380f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          if(clazz.isAssignableFrom(cls)) {
381f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            result= false;
382f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            break;
383f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
384f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
385f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
386f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
387f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
388f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // check if there are failed @BeforeGroups
389f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    String[] groups= method.getGroups();
390f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if(null != groups && groups.length > 0) {
391f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for(String group: groups) {
392f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if(m_beforegroupsFailures.containsKey(group)) {
393f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          result= false;
394f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          break;
395f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
396f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
397f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
398f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return result;
399f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
400f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
401f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /** Group failures must be synched as the Invoker is accessed concurrently */
402f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private Map<String, Boolean> m_beforegroupsFailures= new Hashtable<String, Boolean>();
403f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
404f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /** Class failures must be synched as the Invoker is accessed concurrently */
405f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private Map<Class<?>, Boolean> m_classInvocationResults= new Hashtable<Class<?>, Boolean>();
406f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
407f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private void setClassInvocationFailure(Class<?> clazz, boolean flag) {
408f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    m_classInvocationResults.put(clazz, flag);
409f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
410f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
411f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
412f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * Effectively invokes a configuration method on all passed in instances.
413f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   *
414f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param instances the instances to invoke the configuration method on
415f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param tm the configuration method
416f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param params the parameters needed for method invocation
417f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param isClass flag if the configuration method is a class level method // FIXME: this looks like a missusage
418f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param testResult
419f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @throws InvocationTargetException
420f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @throws IllegalAccessException
421f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
422f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private void invokeConfigurationMethod(Object[] instances,
423f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                         ITestNGMethod tm,
424f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                         Object[] params,
425f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                         boolean isClass,
4260501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust                                         boolean isSuite,
427f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                         ITestResult testResult)
428f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    throws InvocationTargetException, IllegalAccessException
429f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
430f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Mark this method with the current thread id
431f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    tm.setId(ThreadUtil.currentThreadInfo());
432f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
433f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for(Object targetInstance : instances) {
434f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      InvokedMethod im= new InvokedMethod(targetInstance,
435f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                          tm,
436f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                          params,
437f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                          false, /* isTest */
438f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                          isClass, /* ??? */
439f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                          System.currentTimeMillis());
440f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
441398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust      runInvokedMethodListeners(true /* before */, im, testResult);
442f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      m_notifier.addInvokedMethod(im);
443f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
444f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      try {
445f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        Reporter.setCurrentTestResult(testResult);
446f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        MethodHelper.invokeMethod(tm.getMethod(), targetInstance, params);
4470501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust        // Only run the method once if it's @BeforeSuite or @AfterSuite
4480501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust        if (isSuite) break;
449f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
450f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      finally {
451f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        Reporter.setCurrentTestResult(testResult);
452398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust        runInvokedMethodListeners(false /* after */, im, testResult);
453f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
454f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
455f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
456f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
457398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust  private void runInvokedMethodListeners(boolean before, IInvokedMethod method,
458398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust      ITestResult testResult)
459398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust  {
460398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust    if (m_invokedMethodListeners != null) {
461398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust      if (before) {
462398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust        for (IInvokedMethodListener l : m_invokedMethodListeners) {
46368f450416a61dbdd31ba55933fe10d2b022c3908Cédric Beust          if (l instanceof IInvokedMethodListener2) {
46468f450416a61dbdd31ba55933fe10d2b022c3908Cédric Beust            IInvokedMethodListener2 l2 = (IInvokedMethodListener2) l;
46568f450416a61dbdd31ba55933fe10d2b022c3908Cédric Beust            l2.beforeInvocation(method, testResult, m_testContext);
46668f450416a61dbdd31ba55933fe10d2b022c3908Cédric Beust          } else {
46768f450416a61dbdd31ba55933fe10d2b022c3908Cédric Beust            l.beforeInvocation(method, testResult);
46868f450416a61dbdd31ba55933fe10d2b022c3908Cédric Beust          }
469398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust        }
470398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust      }
471398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust      else {
472398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust        for (IInvokedMethodListener l : m_invokedMethodListeners) {
47368f450416a61dbdd31ba55933fe10d2b022c3908Cédric Beust          if (l instanceof IInvokedMethodListener2) {
47468f450416a61dbdd31ba55933fe10d2b022c3908Cédric Beust            IInvokedMethodListener2 l2 = (IInvokedMethodListener2) l;
47568f450416a61dbdd31ba55933fe10d2b022c3908Cédric Beust            l2.afterInvocation(method, testResult, m_testContext);
47668f450416a61dbdd31ba55933fe10d2b022c3908Cédric Beust          } else {
47768f450416a61dbdd31ba55933fe10d2b022c3908Cédric Beust            l.afterInvocation(method, testResult);
47868f450416a61dbdd31ba55933fe10d2b022c3908Cédric Beust          }
479398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust        }
480398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust      }
481398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust    }
482398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust  }
483398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust
484f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private ITestResult invokeMethod(Object[] instances,
485f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   int instanceIndex,
486f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   final ITestNGMethod tm,
487f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   Object[] parameterValues,
488f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   XmlSuite suite,
489f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   Map<String, String> params,
490f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   ITestClass testClass,
491f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   ITestNGMethod[] beforeMethods,
492f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   ITestNGMethod[] afterMethods,
493f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   ConfigurationGroupMethods groupMethods) {
49494efdf8e6ac7332eadf8bfe5d1fe699caee5d051Cédric Beust    TestResult testResult = new TestResult();
49594efdf8e6ac7332eadf8bfe5d1fe699caee5d051Cédric Beust
496f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
497f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Invoke beforeGroups configurations
498f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
499f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    invokeBeforeGroupsConfigurations(testClass, tm, groupMethods, suite, params,
500f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        instances[instanceIndex]);
501f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
502f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
50345a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust    // Invoke beforeMethods only if
50445a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust    // - firstTimeOnly is not set
50545a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust    // - firstTimeOnly is set, and we are reaching at the first invocationCount
506f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
50745a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust    invokeConfigurations(testClass, tm,
50845a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      filterConfigurationMethods(tm, beforeMethods, true /* beforeMethods */),
509facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust      suite, params, parameterValues,
51094efdf8e6ac7332eadf8bfe5d1fe699caee5d051Cédric Beust      instances[instanceIndex], testResult);
511f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
512f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
513f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Create the ExtraOutput for this method
514f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
51538ef90d96ee65073c1090455e7caff2a85d654e2Cédric Beust    InvokedMethod invokedMethod = null;
516f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    try {
51794efdf8e6ac7332eadf8bfe5d1fe699caee5d051Cédric Beust      testResult.init(testClass, instances[instanceIndex],
518f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                 tm,
519f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                 null,
520f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                 System.currentTimeMillis(),
521f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                 0);
522f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      testResult.setParameters(parameterValues);
523f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      testResult.setHost(m_testContext.getHost());
524f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      testResult.setStatus(ITestResult.STARTED);
525f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      runTestListeners(testResult);
526f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
52738ef90d96ee65073c1090455e7caff2a85d654e2Cédric Beust      invokedMethod= new InvokedMethod(instances[instanceIndex],
528f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          tm,
529f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          parameterValues,
530f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          true,
531f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          false,
532f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          System.currentTimeMillis());
533f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
534398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust      runInvokedMethodListeners(true, invokedMethod, testResult);
53538ef90d96ee65073c1090455e7caff2a85d654e2Cédric Beust
536f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      m_notifier.addInvokedMethod(invokedMethod);
537f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
538f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Method thisMethod= tm.getMethod();
539368dc7ebf91330935d1f5d49d39def94dd7751d2DanFabulich
540f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if(confInvocationPassed(tm)) {
541f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        log(3, "Invoking " + thisMethod.getDeclaringClass().getName() + "." +
542f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            thisMethod.getName());
543f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
544f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // If no timeOut, just invoke the method
545331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust        if (MethodHelper.calculateTimeOut(tm) <= 0) {
546711b9b624165b9185efea58f010a40275e19c972mendelson.paul          try {
547711b9b624165b9185efea58f010a40275e19c972mendelson.paul            Reporter.setCurrentTestResult(testResult);
548711b9b624165b9185efea58f010a40275e19c972mendelson.paul            //
549711b9b624165b9185efea58f010a40275e19c972mendelson.paul            // If this method is a IHookable, invoke its run() method
550711b9b624165b9185efea58f010a40275e19c972mendelson.paul            //
551711b9b624165b9185efea58f010a40275e19c972mendelson.paul            if (IHookable.class.isAssignableFrom(thisMethod.getDeclaringClass())) {
552711b9b624165b9185efea58f010a40275e19c972mendelson.paul              MethodHelper.invokeHookable(instances[instanceIndex],
553711b9b624165b9185efea58f010a40275e19c972mendelson.paul                  parameterValues, testClass, thisMethod, testResult);
554711b9b624165b9185efea58f010a40275e19c972mendelson.paul            }
555711b9b624165b9185efea58f010a40275e19c972mendelson.paul            //
556711b9b624165b9185efea58f010a40275e19c972mendelson.paul            // Not a IHookable, invoke directly
557711b9b624165b9185efea58f010a40275e19c972mendelson.paul            //
558711b9b624165b9185efea58f010a40275e19c972mendelson.paul            else {
559f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              MethodHelper.invokeMethod(thisMethod, instances[instanceIndex],
560f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                  parameterValues);
561f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            }
562711b9b624165b9185efea58f010a40275e19c972mendelson.paul            testResult.setStatus(ITestResult.SUCCESS);
563711b9b624165b9185efea58f010a40275e19c972mendelson.paul          }
564711b9b624165b9185efea58f010a40275e19c972mendelson.paul          finally {
565711b9b624165b9185efea58f010a40275e19c972mendelson.paul            Reporter.setCurrentTestResult(null);
566f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
567f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
568f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        else {
569331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust          //
570331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust          // Method with a timeout
571331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust          //
572f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          try {
573f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            Reporter.setCurrentTestResult(testResult);
574f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            MethodHelper.invokeWithTimeout(tm, instances[instanceIndex],
575f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                parameterValues, testResult);
576f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
577f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          finally {
578f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            Reporter.setCurrentTestResult(null);
579f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
580f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
581f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
582f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      else {
583f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        testResult.setStatus(ITestResult.SKIP);
584f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
585f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
586f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    catch(InvocationTargetException ite) {
587f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      testResult.setThrowable(ite.getCause());
588f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
589f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    catch(ThreadExecutionException tee) { // wrapper for TestNGRuntimeException
590f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Throwable cause= tee.getCause();
591f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if(TestNGRuntimeException.class.equals(cause.getClass())) {
592f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        testResult.setThrowable(cause.getCause());
593f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
594f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      else {
595f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        testResult.setThrowable(cause);
596f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
597f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
598f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    catch(Throwable thr) { // covers the non-wrapper exceptions
599f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      testResult.setThrowable(thr);
600f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
601f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    finally {
60238ef90d96ee65073c1090455e7caff2a85d654e2Cédric Beust
603398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust      runInvokedMethodListeners(false, invokedMethod, testResult);
604318a4e47ce813109c76fc8281c9db5f04448f3f1Cédric Beust
605bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust      ExpectedExceptionsHolder expectedExceptionClasses
606318a4e47ce813109c76fc8281c9db5f04448f3f1Cédric Beust          = MethodHelper.findExpectedExceptions(m_annotationFinder, tm.getMethod());
607ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust      List<ITestResult> results = Lists.newArrayList();
608318a4e47ce813109c76fc8281c9db5f04448f3f1Cédric Beust      results.add(testResult);
6096216d78ae0757b7d57aa6e94cc041447d610724dCédric Beust      handleInvocationResults(tm, results, null, 0, expectedExceptionClasses, false,
6106216d78ae0757b7d57aa6e94cc041447d610724dCédric Beust          true /* collect results */);
61138ef90d96ee65073c1090455e7caff2a85d654e2Cédric Beust
612dd84c4f1673772d6b1febb72add6a2ae40f4e4ccCédric Beust      // If this method has a data provider and just failed, memorize the number
613dd84c4f1673772d6b1febb72add6a2ae40f4e4ccCédric Beust      // at which it failed.
6141ed096c7af783713cdeb4a3e9c0c4a02491d65fcCédric Beust      // Note: we're not exactly testing that this method has a data provider, just
6151ed096c7af783713cdeb4a3e9c0c4a02491d65fcCédric Beust      // that it has parameters, so might have to revisit this if bugs get reported
6161ed096c7af783713cdeb4a3e9c0c4a02491d65fcCédric Beust      // for the case where this method has parameters that don't come from a data
6171ed096c7af783713cdeb4a3e9c0c4a02491d65fcCédric Beust      // provider
618dd84c4f1673772d6b1febb72add6a2ae40f4e4ccCédric Beust      if (testResult.getThrowable() != null && parameterValues.length > 0) {
619dd84c4f1673772d6b1febb72add6a2ae40f4e4ccCédric Beust        tm.addFailedInvocationNumber(tm.getCurrentInvocationCount());
620dd84c4f1673772d6b1febb72add6a2ae40f4e4ccCédric Beust      }
621dd84c4f1673772d6b1febb72add6a2ae40f4e4ccCédric Beust
622f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
623f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // Increment the invocation count for this method
624f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
625f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      tm.incrementCurrentInvocationCount();
626f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
627f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if (testResult != null) {
628f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        testResult.setEndMillis(System.currentTimeMillis());
629f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
630f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
63145a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      // Invoke afterMethods only if
63245a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      // - lastTimeOnly is not set
63345a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      // - lastTimeOnly is set, and we are reaching the last invocationCount
634f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
63545a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      invokeConfigurations(testClass, tm,
63645a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust          filterConfigurationMethods(tm, afterMethods, false /* beforeMethods */),
637facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust          suite, params, parameterValues,
638da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust          instances[instanceIndex],
639da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust          testResult);
640f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
641f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
64245a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      // Invoke afterGroups configurations
643f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
644f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      invokeAfterGroupsConfigurations(testClass, tm, groupMethods, suite,
645f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          params, instances[instanceIndex]);
646f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
64794efdf8e6ac7332eadf8bfe5d1fe699caee5d051Cédric Beust
648f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return testResult;
649f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
650f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
651f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
65245a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust   * The array of methods contains @BeforeMethods if isBefore if true, @AfterMethods
65345a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust   * otherwise.  This function removes all the methods that should not be run at this
65445a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust   * point because they are either firstTimeOnly or lastTimeOnly and we haven't reached
65545a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust   * the current invocationCount yet
65645a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust   */
65745a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust  private ITestNGMethod[] filterConfigurationMethods(ITestNGMethod tm,
65845a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      ITestNGMethod[] methods, boolean isBefore)
65945a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust  {
660ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust    List<ITestNGMethod> result = Lists.newArrayList();
66145a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust    for (ITestNGMethod m : methods) {
66245a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      ConfigurationMethod cm = (ConfigurationMethod) m;
66345a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      if (isBefore) {
66445a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust        if (! cm.isFirstTimeOnly() ||
66545a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust            (cm.isFirstTimeOnly() && tm.getCurrentInvocationCount() == 0))
66645a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust        {
66745a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust          result.add(m);
66845a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust        }
66945a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      }
67045a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      else {
671d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust        int current = tm.getCurrentInvocationCount();
672d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust        boolean isLast = false;
6732fc881781da9eb64b913650c8bb856d1f97c64cdCédric Beust        // If we have parameters, set the boolean if we are about to run
6742fc881781da9eb64b913650c8bb856d1f97c64cdCédric Beust        // the last invocation
675d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust        if (tm.getParameterInvocationCount() > 0) {
676d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust          isLast = current == tm.getParameterInvocationCount();
677d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust        }
6782fc881781da9eb64b913650c8bb856d1f97c64cdCédric Beust        // If we have invocationCount > 1, set the boolean if we are about to
6792fc881781da9eb64b913650c8bb856d1f97c64cdCédric Beust        // run the last invocation
680d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust        else if (tm.getInvocationCount() > 1) {
681d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust          isLast = current == tm.getInvocationCount();
682d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust        }
683d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust        if (! cm.isLastTimeOnly() || (cm.isLastTimeOnly() && isLast)) {
68445a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust          result.add(m);
68545a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust        }
68645a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      }
68745a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust    }
68845a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust
68945a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust    return result.toArray(new ITestNGMethod[result.size()]);
69045a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust  }
69145a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust
69245a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust  /**
693f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * {@link #invokeTestMethods()} eventually converge here to invoke a single @Test method.
694f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * <p/>
695f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * This method is responsible for actually invoking the method. It decides if the invocation
696f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * must be done:
697f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * <ul>
698f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * <li>through an <code>IHookable</code></li>
699f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * <li>directly (through reflection)</li>
700f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * <li>in a separate thread (in case it needs to timeout)
701f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * </ul>
702f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   *
703f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * <p/>
704f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * This method is also reponsible for invoking @BeforeGroup, @BeforeMethod, @AfterMethod, @AfterGroup
705f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * if it is the case for the passed in @Test method.
706f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
707c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust  public List<ITestResult> invokeTestMethod(Object[] instances,
708f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             final ITestNGMethod tm,
709f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             Object[] parameterValues,
710f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             XmlSuite suite,
711f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             Map<String, String> params,
712f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             ITestClass testClass,
713f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             ITestNGMethod[] beforeMethods,
714f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             ITestNGMethod[] afterMethods,
715f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             ConfigurationGroupMethods groupMethods)
716f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
717ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust    List<ITestResult> results = Lists.newArrayList();
718f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
719f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Mark this method with the current thread id
720f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    tm.setId(ThreadUtil.currentThreadInfo());
721f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
722f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for(int i= 0; i < instances.length; i++) {
72394efdf8e6ac7332eadf8bfe5d1fe699caee5d051Cédric Beust      results.add(invokeMethod(instances, i, tm, parameterValues, suite, params,
72494efdf8e6ac7332eadf8bfe5d1fe699caee5d051Cédric Beust          testClass, beforeMethods, afterMethods, groupMethods));
725f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
726f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
727f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return results;
728f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
729f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
730f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
731f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * Filter all the beforeGroups methods and invoke only those that apply
732f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * to the current test method
733f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
734f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private void invokeBeforeGroupsConfigurations(ITestClass testClass,
735f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                                ITestNGMethod currentTestMethod,
736f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                                ConfigurationGroupMethods groupMethods,
737f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                                XmlSuite suite,
738f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                                Map<String, String> params,
739f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                                Object instance)
740f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
741f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    synchronized(groupMethods) {
742ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust      List<ITestNGMethod> filteredMethods = Lists.newArrayList();
743f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      String[] groups = currentTestMethod.getGroups();
744f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Map<String, List<ITestNGMethod>> beforeGroupMap = groupMethods.getBeforeGroupsMap();
745f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
746f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for (String group : groups) {
747f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        List<ITestNGMethod> methods = beforeGroupMap.get(group);
748f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if (methods != null) {
749f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          filteredMethods.addAll(methods);
750f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
751f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
752f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
753f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      ITestNGMethod[] beforeMethodsArray = filteredMethods.toArray(new ITestNGMethod[filteredMethods.size()]);
754f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
755f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // Invoke the right groups methods
756f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
757f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if(beforeMethodsArray.length > 0) {
758f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // don't pass the IClass or the instance as the method may be external
759f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // the invocation must be similar to @BeforeTest/@BeforeSuite
760facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust        invokeConfigurations(null, beforeMethodsArray, suite, params,
761facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust            null, /* no parameter values */
762facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust            null);
763f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
764f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
765f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
766f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // Remove them so they don't get run again
767f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
768f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      groupMethods.removeBeforeGroups(groups);
769f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
770f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
771f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
772f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private void invokeAfterGroupsConfigurations(ITestClass testClass,
773f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                               ITestNGMethod currentTestMethod,
774f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                               ConfigurationGroupMethods groupMethods,
775f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                               XmlSuite suite,
776f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                               Map<String, String> params,
777f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                               Object instance)
778f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
779f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Skip this if the current method doesn't belong to any group
780f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // (only a method that belongs to a group can trigger the invocation
781f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // of afterGroups methods)
782f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if (currentTestMethod.getGroups().length == 0) return;
783f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
784f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // See if the currentMethod is the last method in any of the groups
785f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // it belongs to
7860f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beust    Map<String, String> filteredGroups = Maps.newHashMap();
787f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    String[] groups = currentTestMethod.getGroups();
788f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    synchronized(groupMethods) {
789f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for (String group : groups) {
790f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if (groupMethods.isLastMethodForGroup(group, currentTestMethod)) {
791f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          filteredGroups.put(group, group);
792f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
793f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
794f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
795f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if(filteredGroups.isEmpty()) return;
796f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
797f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // The list of afterMethods to run
7980f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beust      Map<ITestNGMethod, ITestNGMethod> afterMethods = Maps.newHashMap();
799f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
800f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // Now filteredGroups contains all the groups for which we need to run the afterGroups
801f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // method.  Find all the methods that correspond to these groups and invoke them.
802f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Map<String, List<ITestNGMethod>> map = groupMethods.getAfterGroupsMap();
803f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for (String g : filteredGroups.values()) {
804f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        List<ITestNGMethod> methods = map.get(g);
805f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // Note:  should put them in a map if we want to make sure the same afterGroups
806f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // doesn't get run twice
807f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if (methods != null) {
808f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          for (ITestNGMethod m : methods) {
809f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            afterMethods.put(m, m);
810f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
811f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
812f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
813f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
814f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // Got our afterMethods, invoke them
815f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      ITestNGMethod[] afterMethodsArray = afterMethods.keySet().toArray(new ITestNGMethod[afterMethods.size()]);
816f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // don't pass the IClass or the instance as the method may be external
817f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // the invocation must be similar to @BeforeTest/@BeforeSuite
818facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust      invokeConfigurations(null, afterMethodsArray, suite, params,
819facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust          null, /* no parameter values */
820facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust          null);
821f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
822f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // Remove the groups so they don't get run again
823f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      groupMethods.removeAfterGroups(filteredGroups.keySet());
824f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
825f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
826f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
827f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private Object[] getParametersFromIndex(Iterator<Object[]> parametersValues, int index) {
828f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    while (parametersValues.hasNext()) {
829f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Object[] parameters = parametersValues.next();
830f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
831f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if (index == 0) {
832f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        return parameters;
833f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
834f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      index--;
835f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
836f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return null;
837f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
838f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
839c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust  int retryFailed(Object[] instances,
840f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           int instanceIndex,
841f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           final ITestNGMethod tm,
842f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           XmlSuite suite,
843f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           ITestClass testClass,
844f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           ITestNGMethod[] beforeMethods,
845f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           ITestNGMethod[] afterMethods,
846f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           ConfigurationGroupMethods groupMethods,
847f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           List<ITestResult> result,
848f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           int failureCount,
849bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust                           ExpectedExceptionsHolder expectedExceptionHolder,
850f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           ITestContext testContext,
851f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           Map<String, String> parameters,
852f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           int parametersIndex) {
85392206009b23ecbbf29e5a0d20f6b095a552afcb8Cédric Beust    List<Object> failedInstances;
854f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
85592206009b23ecbbf29e5a0d20f6b095a552afcb8Cédric Beust    do {
856ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust      failedInstances = Lists.newArrayList();
8570f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beust      Map<String, String> allParameters = Maps.newHashMap();
858f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      /**
859f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust       * TODO: This recreates all the parameters every time when we only need
860f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust       * one specific set. Should optimize it by only recreating the set needed.
861f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust       */
862f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      ParameterBag bag = createParameters(testClass, tm, parameters,
863da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust          allParameters, null, suite, testContext, null /* fedInstance */, null /* testResult */);
864c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust      Object[] parameterValues =
865c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust          getParametersFromIndex(bag.parameterHolder.parameters, parametersIndex);
866f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
86794efdf8e6ac7332eadf8bfe5d1fe699caee5d051Cédric Beust      result.add(invokeMethod(instances, instanceIndex, tm, parameterValues, suite,
86894efdf8e6ac7332eadf8bfe5d1fe699caee5d051Cédric Beust          allParameters, testClass, beforeMethods, afterMethods, groupMethods));
869f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      failureCount = handleInvocationResults(tm, result, failedInstances,
870bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust          failureCount, expectedExceptionHolder, true, true /* collect results */);
871f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
872f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    while (!failedInstances.isEmpty());
873f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return failureCount;
874f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
875f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
876f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private ParameterBag createParameters(ITestClass testClass,
877f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                        ITestNGMethod testMethod,
878f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                        Map<String, String> parameters,
879f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                        Map<String, String> allParameterNames,
880facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust                                        Object[] parameterValues,
881f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                        XmlSuite suite,
8828b9443a6ada20a1e9f3852b715f3e789a0f8d490Cédric Beust                                        ITestContext testContext,
883da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust                                        Object fedInstance,
884da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust                                        ITestResult testResult)
8858778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust  {
8868778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust    Object instance;
8878778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust    if (fedInstance != null) {
8888778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust      instance = fedInstance;
8898778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust    }
8908778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust    else {
8918778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust      Object[] instances = testClass.getInstances(true);
8928778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust      instance = instances[0];
8938778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust    }
8948778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust
895f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    ParameterBag bag= handleParameters(testMethod,
896da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust        instance, allParameterNames, parameters, parameterValues, suite, testContext, fedInstance,
897da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust        testResult);
898f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
899f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return bag;
900f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
901f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
902f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
903f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * Invoke all the test methods.  Note the plural:  the method passed in
904f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * parameter might be invoked several times if the test class it belongs
905f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * to has more than one instance (i.e., if an @Factory method has been
906f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * declared somewhere that returns several instances of this TestClass).
907f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * If no @Factory method was specified, testMethod will only be invoked
908f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * once.
909f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * <p/>
910f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * Note that this method also takes care of invoking the beforeTestMethod
911f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * and afterTestMethod, if any.
912f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   *
913f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * Note (alex): this method can be refactored to use a SingleTestMethodWorker that
914f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * directly invokes
915f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * {@link #invokeTestMethod(Object[], ITestNGMethod, Object[], XmlSuite, Map, ITestClass, ITestNGMethod[], ITestNGMethod[], ConfigurationGroupMethods)}
916f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * and this would simplify the implementation (see how DataTestMethodWorker is used)
917f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
918f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  public List<ITestResult> invokeTestMethods(ITestNGMethod testMethod,
919f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             ITestNGMethod[] allTestMethods,
920f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             int testMethodIndex,
921f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             XmlSuite suite,
922f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             Map<String, String> parameters,
923f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             ConfigurationGroupMethods groupMethods,
924f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             Object[] instances,
925f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             ITestContext testContext)
926f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
927f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Potential bug here if the test method was declared on a parent class
928f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    assert null != testMethod.getTestClass()
929f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    : "COULDN'T FIND TESTCLASS FOR " + testMethod.getMethod().getDeclaringClass();
930f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
931ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust    List<ITestResult> result = Lists.newArrayList();
932f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
933f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    ITestClass testClass= testMethod.getTestClass();
934f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    long start= System.currentTimeMillis();
935f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
936f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
937f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // TODO:
938f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // - [DONE] revisit invocationCount, threadPoolSize values
939f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // - try to remove the isWithinThreadedMethod: still needed to determine the @BeforeMethod + @AfterMethod
940f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // - [DONE] solve the results different approaches: assignment and addAll
941f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
9426cf2e96a6b18fe7eecc44cac44bb0690a162f416Cédric Beust    // For invocationCount>1 and threadPoolSize>1 the method will be invoked on a thread pool
943331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust    long timeOutInvocationCount = testMethod.getInvocationTimeOut();
944331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust    boolean onlyOne = testMethod.getThreadPoolSize() > 1 ||
945331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust      timeOutInvocationCount > 0;
946331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust
947331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust    int invocationCount = onlyOne ? 1 : testMethod.getInvocationCount();
948f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
949f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    int failureCount = 0;
950f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
951bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust    ExpectedExceptionsHolder expectedExceptionHolder =
952f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        MethodHelper.findExpectedExceptions(m_annotationFinder, testMethod.getMethod());
953f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    while(invocationCount-- > 0) {
954f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      boolean okToProceed = checkDependencies(testMethod, testClass, allTestMethods);
955f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
956f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if (okToProceed) {
957f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        //
958f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // Invoke the test method if it's enabled
959f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        //
960f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if (MethodHelper.isEnabled(testMethod.getMethod(), m_annotationFinder)) {
96162009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust          //
96262009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust          // If threadPoolSize specified, run this method in its own pool thread.
96362009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust          //
96462009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust          if (testMethod.getThreadPoolSize() > 1 && testMethod.getInvocationCount() > 1) {
96562009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust              return invokePooledTestMethods(testMethod, allTestMethods, suite,
96662009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust                  parameters, groupMethods, testContext);
96762009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust          }
96862009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust
96962009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust          //
97062009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust          // No threads, regular invocation
97162009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust          //
97262009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust          else {
97362009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust            ITestNGMethod[] beforeMethods = filterMethods(testClass, testClass.getBeforeTestMethods());
97462009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust            ITestNGMethod[] afterMethods = filterMethods(testClass, testClass.getAfterTestMethods());
975f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
976f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
9770f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beust            Map<String, String> allParameterNames = Maps.newHashMap();
97862009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust            ParameterBag bag = createParameters(testClass, testMethod,
979da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust                parameters, allParameterNames, null, suite, testContext, instances[0],
980da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust                null);
981f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
98262009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust            if(bag.hasErrors()) {
98362009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust              failureCount = handleInvocationResults(testMethod,
98462009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust                  bag.errorResults, null, failureCount, expectedExceptionHolder, true,
98562009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust                  true /* collect results */);
98662009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust              // there is nothing we can do more
98762009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust              continue;
98862009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust            }
98962009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust
99062009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust            Iterator<Object[]> allParameterValues= bag.parameterHolder.parameters;
99162009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust
99243f186d3baa643622b94876b945380a4b7e29d55Cédric Beust            int parametersIndex = 0;
99343f186d3baa643622b94876b945380a4b7e29d55Cédric Beust
99443f186d3baa643622b94876b945380a4b7e29d55Cédric Beust            try {
99562009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust//                if (true) { // @@
99601e59f7bdf6515f065bd697832db53253ca78b1aCédric Beust              List<TestMethodWithDataProviderMethodWorker> workers = Lists.newArrayList();
997c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust
998fa2cf92e7ea0d250cc09764054b3594326db0d0eCédric Beust//                  if (false) { // bag.parameterHolder.origin == ParameterHolder.ORIGIN_DATA_PROVIDER) {
99943f186d3baa643622b94876b945380a4b7e29d55Cédric Beust              if (bag.parameterHolder.origin == ParameterHolder.ORIGIN_DATA_PROVIDER &&
100043f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                  bag.parameterHolder.dataProviderHolder.annotation.isParallel()) {
100143f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                while (allParameterValues.hasNext()) {
100243f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                  Object[] parameterValues= allParameterValues.next();
100343f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                  TestMethodWithDataProviderMethodWorker w =
100443f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    new TestMethodWithDataProviderMethodWorker(this,
100543f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                        testMethod, parametersIndex,
100643f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                        parameterValues, instances, suite, parameters, testClass,
100743f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                        beforeMethods, afterMethods, groupMethods,
100843f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                        expectedExceptionHolder, testContext, m_skipFailedInvocationCounts,
100943f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                        invocationCount, failureCount, m_notifier);
101043f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                  workers.add(w);
101143f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                }
101243f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                PoolService ps = PoolService.getInstance();
101343f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                List<ITestResult> r = ps.submitTasksAndWait(testMethod, workers);
101443f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                result.addAll(r);
101543f186d3baa643622b94876b945380a4b7e29d55Cédric Beust
101643f186d3baa643622b94876b945380a4b7e29d55Cédric Beust              } else {
101743f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                while (allParameterValues.hasNext()) {
10181e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust                  Object[] rawParameterValues= allParameterValues.next();
101943f186d3baa643622b94876b945380a4b7e29d55Cédric Beust
10201e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust                  Object[] parameterValues = injectParameters(rawParameterValues,
10211e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust                      testMethod.getMethod(), testContext, null /* test result */);
10221e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust//                  Object[] parameterValues = rawParameterValues;
102343f186d3baa643622b94876b945380a4b7e29d55Cédric Beust
1024ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust                  List<ITestResult> tmpResults = Lists.newArrayList();
102543f186d3baa643622b94876b945380a4b7e29d55Cédric Beust
102643f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                  try {
102743f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    tmpResults.addAll(invokeTestMethod(instances,
102843f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                                                       testMethod,
102943f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                                                       parameterValues,
103043f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                                                       suite,
103143f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                                                       parameters,
103243f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                                                       testClass,
103343f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                                                       beforeMethods,
103443f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                                                       afterMethods,
103543f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                                                       groupMethods));
1036f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                  }
103743f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                  finally {
1038ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust                    List<Object> failedInstances = Lists.newArrayList();
103943f186d3baa643622b94876b945380a4b7e29d55Cédric Beust
104043f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    failureCount = handleInvocationResults(testMethod, tmpResults,
104143f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                        failedInstances, failureCount, expectedExceptionHolder, true,
104243f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                        false /* don't collect results */);
104343f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    if (failedInstances.isEmpty()) {
104443f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                      result.addAll(tmpResults);
104543f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    } else {
104643f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                      for (int i = 0; i < failedInstances.size(); i++) {
1047ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust                        List<ITestResult> retryResults = Lists.newArrayList();
104843f186d3baa643622b94876b945380a4b7e29d55Cédric Beust
104943f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                        failureCount =
105043f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                         retryFailed(failedInstances.toArray(),
105143f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                         i, testMethod, suite, testClass, beforeMethods,
105243f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                         afterMethods, groupMethods, retryResults,
105343f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                         failureCount, expectedExceptionHolder,
105443f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                         testContext, parameters, parametersIndex);
105543f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                      result.addAll(retryResults);
1056c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust                      }
105743f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    }
105843f186d3baa643622b94876b945380a4b7e29d55Cédric Beust
105943f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    //
106043f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    // If we have a failure, skip all the
106143f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    // other invocationCounts
106243f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    //
106343f186d3baa643622b94876b945380a4b7e29d55Cédric Beust
106443f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    // If not specified globally, use the attribute
106543f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    // on the annotation
106643f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    //
106743f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    if (! m_skipFailedInvocationCounts) {
106843f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                      m_skipFailedInvocationCounts = testMethod.skipFailedInvocations();
106943f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    }
107043f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    if (failureCount > 0 && m_skipFailedInvocationCounts) {
107143f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                      while (invocationCount-- > 0) {
107243f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                        ITestResult r =
107343f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                          new TestResult(testMethod.getTestClass(),
107443f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                            instances[0],
107543f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                            testMethod,
107643f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                            null,
107743f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                            start,
107843f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                            System.currentTimeMillis());
107943f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                        r.setStatus(TestResult.SKIP);
108043f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                        result.add(r);
108143f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                        runTestListeners(r);
108243f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                        m_notifier.addSkippedTest(testMethod, r);
1083c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust                      }
108443f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                      break;
108543f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                    }
108643f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                  }// end
108743f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                parametersIndex++;
1088c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust              }
108962009f0ba50539b198d8fa87291bcc9906de28e9Cédric Beust            }
109043f186d3baa643622b94876b945380a4b7e29d55Cédric Beust          }
109143f186d3baa643622b94876b945380a4b7e29d55Cédric Beust          catch (Throwable cause) {
109243f186d3baa643622b94876b945380a4b7e29d55Cédric Beust            ITestResult r =
109343f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                new TestResult(testMethod.getTestClass(),
109443f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                  instances[0],
109543f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                  testMethod,
109643f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                  cause,
109743f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                  start,
109843f186d3baa643622b94876b945380a4b7e29d55Cédric Beust                  System.currentTimeMillis());
109943f186d3baa643622b94876b945380a4b7e29d55Cédric Beust              r.setStatus(TestResult.FAILURE);
110043f186d3baa643622b94876b945380a4b7e29d55Cédric Beust              result.add(r);
110143f186d3baa643622b94876b945380a4b7e29d55Cédric Beust              runTestListeners(r);
110243f186d3baa643622b94876b945380a4b7e29d55Cédric Beust              m_notifier.addFailedTest(testMethod, r);
110343f186d3baa643622b94876b945380a4b7e29d55Cédric Beust            } // catch
1104c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust          }
1105f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        } // isTestMethodEnabled
1106f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1107f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      } // okToProceed
1108f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      else {
1109f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        //
1110f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // Test is being skipped
1111f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        //
1112f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        ITestResult testResult= new TestResult(testClass, null,
1113f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                               testMethod,
1114f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                               null,
1115f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                               start,
1116f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                               System.currentTimeMillis());
1117f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        testResult.setEndMillis(System.currentTimeMillis());
1118f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        String missingGroup = testMethod.getMissingGroup();
1119f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if (missingGroup != null) {
1120f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          testResult.setThrowable(new Throwable("Method " + testMethod
1121f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              + " depends on nonexistent group \"" + missingGroup + "\""));
1122f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1123f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1124f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        testResult.setStatus(ITestResult.SKIP);
1125a4e6892fbfa21c968737eaf4e4f1e4b0b7f9163eCédric Beust        result.add(testResult);
1126f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        m_notifier.addSkippedTest(testMethod, testResult);
1127f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        runTestListeners(testResult);
1128f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1129f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1130f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1131f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return result;
1132f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1133f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  } // invokeTestMethod
1134f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
11351e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust  private Object[] injectParameters(Object[] parameterValues, Method method,
11361e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust      ITestContext context, ITestResult testResult) {
11371e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust    List<Object> vResult = Lists.newArrayList();
11381e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust    int i = 0;
11391e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust    for (Class<?> cls : method.getParameterTypes()) {
11401e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust      Object injected = Parameters.getInjectedParameter(cls, method, context, testResult);
11411e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust      if (injected != null) {
11421e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust        vResult.add(injected);
11431e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust      } else {
11441e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust        vResult.add(parameterValues[i++]);
11451e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust      }
11461e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust    }
11471e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust    return vResult.toArray(new Object[vResult.size()]);
11481e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust  }
11491e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust
1150f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private ParameterBag handleParameters(ITestNGMethod testMethod,
1151f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Object instance,
1152f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Map<String, String> allParameterNames,
1153f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Map<String, String> parameters,
1154facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust      Object[] parameterValues,
1155f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      XmlSuite suite,
11568b9443a6ada20a1e9f3852b715f3e789a0f8d490Cédric Beust      ITestContext testContext,
1157da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust      Object fedInstance,
1158da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust      ITestResult testResult)
1159f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
1160f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    try {
1161c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust      return new ParameterBag(
1162c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust          Parameters.handleParameters(testMethod,
1163c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust            allParameterNames,
1164c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust            instance,
1165c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust            new Parameters.MethodParameters(parameters, parameterValues,
1166da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust                testMethod.getMethod(), testContext, testResult),
1167c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust            suite,
1168c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust            m_annotationFinder,
1169c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust            fedInstance),
1170c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust          null);
1171f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1172f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    catch(Throwable cause) {
1173f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      return new ParameterBag(null,
1174f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          new TestResult(
1175f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              testMethod.getTestClass(),
1176f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              instance,
1177f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              testMethod,
1178f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              cause,
1179f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              System.currentTimeMillis(),
1180f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              System.currentTimeMillis()));
1181f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1182f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1183f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1184f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1185f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1186f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * Invokes a method that has a specified threadPoolSize.
1187f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
1188f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private List<ITestResult> invokePooledTestMethods(ITestNGMethod testMethod,
1189f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                                    ITestNGMethod[] allTestMethods,
1190f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                                    XmlSuite suite,
1191f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                                    Map<String, String> parameters,
1192f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                                    ConfigurationGroupMethods groupMethods,
1193f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                                    ITestContext testContext)
1194f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
1195f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
1196f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Create the workers
1197f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
119801e59f7bdf6515f065bd697832db53253ca78b1aCédric Beust    List<IMethodWorker> workers = Lists.newArrayList();
1199f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1200f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for (int i = 0; i < testMethod.getInvocationCount(); i++) {
1201f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // we use clones for reporting purposes
1202f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      ITestNGMethod clonedMethod= testMethod.clone();
1203f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      clonedMethod.setInvocationCount(1);
1204f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      clonedMethod.setThreadPoolSize(1);
1205f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1206f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      MethodInstance mi = new MethodInstance(clonedMethod, clonedMethod.getTestClass().getInstances(true));
1207f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      workers.add(new SingleTestMethodWorker(this,
1208f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          mi,
1209f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          suite,
1210f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          parameters,
1211f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          allTestMethods,
1212f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          testContext));
1213f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1214f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1215f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return runWorkers(testMethod, workers, testMethod.getThreadPoolSize(), groupMethods, suite, parameters);
1216f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1217f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1218f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1219f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param testMethod
1220f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param result
1221f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param failureCount
1222bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust   * @param expectedExceptionsHolder
1223f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return
1224f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
1225c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust  int handleInvocationResults(ITestNGMethod testMethod,
1226f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                      List<ITestResult> result,
1227f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                      List<Object> failedInstances,
1228f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                      int failureCount,
1229bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust                                      ExpectedExceptionsHolder expectedExceptionsHolder,
12306216d78ae0757b7d57aa6e94cc041447d610724dCédric Beust                                      boolean triggerListeners,
12316216d78ae0757b7d57aa6e94cc041447d610724dCédric Beust                                      boolean collectResults)
12326216d78ae0757b7d57aa6e94cc041447d610724dCédric Beust  {
1233f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
1234f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Go through all the results and create a TestResult for each of them
1235f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
1236ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust    List<ITestResult> resultsToRetry = Lists.newArrayList();
1237f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1238f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for (int i = 0; i < result.size(); i++) {
1239f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      ITestResult testResult = result.get(i);
1240f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Throwable ite= testResult.getThrowable();
1241f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      int status= testResult.getStatus();
1242f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1243f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // Exception thrown?
12444c02d89d66fe0319dd20083e705addd6b5f3e8cdCédric Beust      if (ite != null) {
1245f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1246f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        //  Invocation caused an exception, see if the method was annotated with @ExpectedException
1247bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust        if (isExpectedException(ite, expectedExceptionsHolder)) {
1248bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust          if (messageRegExpMatches(expectedExceptionsHolder.messageRegExp, ite)) {
1249bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust            testResult.setStatus(ITestResult.SUCCESS);
1250bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust            status= ITestResult.SUCCESS;
1251bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust          }
1252bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust          else {
1253bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust            testResult.setThrowable(
1254bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust                new TestException("The exception was thrown with the wrong message:" +
1255bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust                		" expected \"" + expectedExceptionsHolder.messageRegExp + "\"" +
1256bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust                		" but got \"" + ite.getMessage() + "\""));
1257bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust            status= ITestResult.FAILURE;
1258bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust          }
12594c02d89d66fe0319dd20083e705addd6b5f3e8cdCédric Beust        } else if (ite != null && expectedExceptionsHolder != null) {
12604c02d89d66fe0319dd20083e705addd6b5f3e8cdCédric Beust          testResult.setThrowable(
12614c02d89d66fe0319dd20083e705addd6b5f3e8cdCédric Beust              new TestException("Expected exception "
12624c02d89d66fe0319dd20083e705addd6b5f3e8cdCédric Beust                 + expectedExceptionsHolder.expectedClasses[0].getName()
12634c02d89d66fe0319dd20083e705addd6b5f3e8cdCédric Beust                 + " but got " + ite));
12644c02d89d66fe0319dd20083e705addd6b5f3e8cdCédric Beust          status= ITestResult.FAILURE;
1265f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1266f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        else if (SkipException.class.isAssignableFrom(ite.getClass())){
1267f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          SkipException skipEx= (SkipException) ite;
1268f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          if(skipEx.isSkip()) {
12694c02d89d66fe0319dd20083e705addd6b5f3e8cdCédric Beust            status = ITestResult.SKIP;
1270f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
1271f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          else {
1272f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            handleException(ite, testMethod, testResult, failureCount++);
12734c02d89d66fe0319dd20083e705addd6b5f3e8cdCédric Beust            status = ITestResult.FAILURE;
1274f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
1275f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1276f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        else {
1277f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          handleException(ite, testMethod, testResult, failureCount++);
1278f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          status= testResult.getStatus();
1279f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1280f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1281f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1282f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // No exception thrown, make sure we weren't expecting one
1283bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust      else if(status != ITestResult.SKIP && expectedExceptionsHolder != null) {
1284bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust        Class<?>[] classes = expectedExceptionsHolder.expectedClasses;
1285bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust        if (classes != null && classes.length > 0) {
1286f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          testResult.setThrowable(
128727e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust              new TestException("Method " + testMethod + " should have thrown an exception of "
128827e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust                  + expectedExceptionsHolder.expectedClasses[0]));
1289f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          status= ITestResult.FAILURE;
1290f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1291f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1292f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1293f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      testResult.setStatus(status);
1294f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1295f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      boolean retry = false;
1296f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1297f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if (testResult.getStatus() == ITestResult.FAILURE) {
1298f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        IRetryAnalyzer retryAnalyzer = testMethod.getRetryAnalyzer();
1299f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1300f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if (retryAnalyzer != null) {
1301f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          retry = retryAnalyzer.retry(testResult);
1302f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1303f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1304f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if (retry) {
1305f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          resultsToRetry.add(testResult);
1306f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          if (failedInstances != null) {
1307f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            failedInstances.add(testResult.getMethod().getInstances()[i]);
1308f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
1309f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1310f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
13116216d78ae0757b7d57aa6e94cc041447d610724dCédric Beust      if (!retry || collectResults) {
1312f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // Collect the results
1313f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if(ITestResult.SUCCESS == status) {
1314f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          m_notifier.addPassedTest(testMethod, testResult);
1315f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1316f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        else if(ITestResult.SKIP == status) {
1317f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          m_notifier.addSkippedTest(testMethod, testResult);
1318f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1319f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        else if(ITestResult.FAILURE == status) {
1320f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          m_notifier.addFailedTest(testMethod, testResult);
1321f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1322f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        else if(ITestResult.SUCCESS_PERCENTAGE_FAILURE == status) {
1323f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          m_notifier.addFailedButWithinSuccessPercentageTest(testMethod, testResult);
1324f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1325f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        else {
1326f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          assert false : "UNKNOWN STATUS:" + status;
1327f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1328f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1329f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if (triggerListeners) {
1330f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          runTestListeners(testResult);
1331f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1332f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1333f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    } // for results
1334f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1335f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return removeResultsToRetryFromResult(resultsToRetry, result, failureCount);
1336f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1337f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1338bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust  /**
1339bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust   *   message / regEx  .*      other
1340bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust   *   null             true    false
1341bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust   *   non-null         true    match
1342bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust   */
1343bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust  private boolean messageRegExpMatches(String messageRegExp, Throwable ite) {
1344bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust    if (".*".equals(messageRegExp)) {
1345bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust      return true;
1346bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust    } else {
1347bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust      if (ite.getMessage() == null) return false;
1348bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust      else return Pattern.matches(messageRegExp, ite.getMessage());
1349bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust    }
1350bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust  }
1351bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust
1352f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private int removeResultsToRetryFromResult(List<ITestResult> resultsToRetry,
1353f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      List<ITestResult> result, int failureCount) {
1354f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if (resultsToRetry != null) {
1355f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for (ITestResult res : resultsToRetry) {
1356f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        result.remove(res);
1357f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        failureCount--;
1358f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1359f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1360f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return failureCount;
1361f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1362f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1363f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1364f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * To reduce thread contention and also to correctly handle thread-confinement
1365f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * this method invokes the @BeforeGroups and @AfterGroups corresponding to the current @Test method.
1366f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
1367f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private List<ITestResult> runWorkers(ITestNGMethod testMethod,
1368f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      List<IMethodWorker> workers,
1369f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      int threadPoolSize,
1370f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      ConfigurationGroupMethods groupMethods,
1371f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      XmlSuite suite,
1372f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Map<String, String> parameters)
1373f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
1374c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust    // Invoke @BeforeGroups on the original method (reduce thread contention,
1375c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust    // and also solve thread confinement)
1376f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    ITestClass testClass= testMethod.getTestClass();
1377f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    Object[] instances = testClass.getInstances(true);
1378f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for(Object instance: instances) {
1379f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      invokeBeforeGroupsConfigurations(testClass, testMethod, groupMethods, suite, parameters, instance);
1380f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1381f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1382f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1383f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    long maxTimeOut= -1; // 10 seconds
1384f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1385f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for(IMethodWorker tmw : workers) {
1386f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      long mt= tmw.getMaxTimeOut();
1387f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if(mt > maxTimeOut) {
1388f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        maxTimeOut= mt;
1389f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1390f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1391f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1392f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    ThreadUtil.execute(workers, threadPoolSize, maxTimeOut, true);
1393f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1394f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
1395f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Collect all the TestResults
1396f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
1397ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust    List<ITestResult> result = Lists.newArrayList();
1398f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for (IMethodWorker tmw : workers) {
1399f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      result.addAll(tmw.getTestResults());
1400f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1401f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1402f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for(Object instance: instances) {
1403f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      invokeAfterGroupsConfigurations(testClass, testMethod, groupMethods, suite, parameters, instance);
1404f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1405f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1406f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return result;
1407f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1408f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1409f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1410f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param testMethod
1411f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param testClass
1412f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return dependencies have been run successfully
1413f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
1414a4e6892fbfa21c968737eaf4e4f1e4b0b7f9163eCédric Beust  private boolean checkDependencies(ITestNGMethod testMethod, ITestClass testClass,
1415a4e6892fbfa21c968737eaf4e4f1e4b0b7f9163eCédric Beust      ITestNGMethod[] allTestMethods)
1416f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
1417f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    boolean result= true;
1418f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1419f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // If this method is marked alwaysRun, no need to check for its
1420f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // dependencies
1421f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if (testMethod.isAlwaysRun()) {
1422f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      return true;
1423f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1424f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1425f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Any missing group?
1426f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if (testMethod.getMissingGroup() != null) {
14279bf49482d840550074c670dd8924be47314f15a2DanFabulich      if (!testMethod.ignoreMissingDependencies()) return false;
1428f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1429f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1430f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // If this method depends on groups, collect all the methods that
1431f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // belong to these groups and make sure they have been run successfully
1432f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if(dependsOnGroups(testMethod)) {
1433f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      String[] groupsDependedUpon= testMethod.getGroupsDependedUpon();
1434f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1435f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // Get all the methods that belong to the group depended upon
1436f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for(int i= 0; i < groupsDependedUpon.length; i++) {
1437f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        ITestNGMethod[] methods =
1438f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          MethodHelper.findMethodsThatBelongToGroup(testMethod,
1439f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              m_testContext.getAllTestMethods(),
1440f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              groupsDependedUpon[i]);
1441f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1442f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        result = result && haveBeenRunSuccessfully(methods);
1443f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1444f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    } // depends on groups
1445f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1446f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // If this method depends on other methods, make sure all these other
1447f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // methods have been run successfully
1448f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if(dependsOnMethods(testMethod)) {
1449f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      ITestNGMethod[] methods =
14509bf49482d840550074c670dd8924be47314f15a2DanFabulich        MethodHelper.findMethodsNamed(testMethod, allTestMethods, testMethod.getMethodsDependedUpon());
1451f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1452f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      result= result && haveBeenRunSuccessfully(methods);
1453f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1454f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1455f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return result;
1456f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1457f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1458f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1459f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return true if all the methods have been run successfully
1460f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
1461f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private boolean haveBeenRunSuccessfully(ITestNGMethod[] methods) {
1462f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Make sure the method has been run successfully
1463f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for(int j= 0; j < methods.length; j++) {
1464f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Set<ITestResult> results= m_notifier.getPassedTests(methods[j]);
1465f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1466f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // If no results were returned, then these tests didn't pass
1467f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if (results == null || results.size() == 0) return false;
1468f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1469f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for (ITestResult result : results) {
1470f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if(!result.isSuccess()) {
1471f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          return false;
1472f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1473f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1474f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1475f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1476f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return true;
1477f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1478f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1479f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1480f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * An exception was thrown by the test, determine if this method
1481f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * should be marked as a failure or as failure_but_within_successPercentage
1482f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
1483f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private void handleException(Throwable throwable,
1484f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                               ITestNGMethod testMethod,
1485f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                               ITestResult testResult,
1486f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                               int failureCount) {
1487f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    testResult.setThrowable(throwable);
1488f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    int successPercentage= testMethod.getSuccessPercentage();
1489f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    int invocationCount= testMethod.getInvocationCount();
1490f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    float numberOfTestsThatCanFail= ((100 - successPercentage) * invocationCount) / 100;
1491f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1492f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if(failureCount < numberOfTestsThatCanFail) {
1493f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      testResult.setStatus(ITestResult.SUCCESS_PERCENTAGE_FAILURE);
1494f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1495f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    else {
1496f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      testResult.setStatus(ITestResult.FAILURE);
1497f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1498f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1499f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1500f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1501f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1502f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param ite The exception that was just thrown
1503f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param expectedExceptions The list of expected exceptions for this
1504f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * test method
1505f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return true if the exception that was just thrown is part of the
1506f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * expected exceptions
1507f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
1508bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust  private boolean isExpectedException(Throwable ite, ExpectedExceptionsHolder exceptionHolder) {
1509bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust    if (exceptionHolder == null) {
1510f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      return false;
1511f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
151227e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust
151327e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust    // TestException is the wrapper exception that TestNG will be throwing when an exception was
151427e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust    // expected but not thrown
151527e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust    if (ite.getClass() == TestException.class) {
151627e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust      return false;
151727e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust    }
151827e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust
1519bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust    Class<?>[] exceptions = exceptionHolder.expectedClasses;
1520bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust    String messageRegExp = exceptionHolder.messageRegExp;
1521f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1522f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    Class<?> realExceptionClass= ite.getClass();
1523f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1524f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for(int i= 0; i < exceptions.length; i++) {
1525bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust      if (exceptions[i].isAssignableFrom(realExceptionClass)) {
1526f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        return true;
1527f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1528f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1529f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1530f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return false;
1531f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1532f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1533f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1534f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return Only the ITestNGMethods applicable for this testClass
1535f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
1536f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private ITestNGMethod[] filterMethods(IClass testClass, ITestNGMethod[] methods) {
1537ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust    List<ITestNGMethod> vResult= Lists.newArrayList();
1538f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1539f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for(ITestNGMethod tm : methods) {
1540f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if(tm.canRunFromClass(testClass)) {
1541f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        log(9, "Keeping method " + tm + " for class " + testClass);
1542f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        vResult.add(tm);
1543f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1544f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      else {
1545f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        log(9, "Filtering out method " + tm + " for class " + testClass);
1546f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1547f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1548f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1549f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    ITestNGMethod[] result= vResult.toArray(new ITestNGMethod[vResult.size()]);
1550f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1551f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return result;
1552f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1553f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1554f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private ITestNGMethod[] filterMethodsUnique(IClass testClass, ITestNGMethod[] methods) {
1555f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if(null == testClass) {
1556f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      return methods;
1557f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1558f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1559ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust    List<ITestNGMethod> vResult= Lists.newArrayList();
1560f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1561f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for(ITestNGMethod tm : methods) {
1562f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if(null == testClass) {
1563f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        testClass= tm.getTestClass();
1564f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1565f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1566f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if(tm.getTestClass().getName().equals(testClass.getName())) {
1567f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        log(9, "        Keeping method " + tm + " for class " + testClass);
1568f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1569f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        vResult.add(tm);
1570f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1571f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      else {
1572f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        log(9, "        Filtering out method " + tm + " for class " + testClass);
1573f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1574f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1575f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1576f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    ITestNGMethod[] result= vResult.toArray(new ITestNGMethod[vResult.size()]);
1577f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1578f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return result;
1579f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1580f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1581f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1582f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return true if this method depends on certain groups.
1583f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
1584f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private boolean dependsOnGroups(ITestNGMethod tm) {
1585f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    String[] groups= tm.getGroupsDependedUpon();
1586f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    boolean result= (null != groups) && (groups.length > 0);
1587f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1588f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return result;
1589f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1590f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1591f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1592f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return true if this method depends on certain groups.
1593f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
1594f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private boolean dependsOnMethods(ITestNGMethod tm) {
1595f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    String[] methods= tm.getMethodsDependedUpon();
1596f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    boolean result= (null != methods) && (methods.length > 0);
1597f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1598f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return result;
1599f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1600f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1601f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private void runConfigurationListeners(ITestResult tr) {
1602f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for(IConfigurationListener icl: m_notifier.getConfigurationListeners()) {
1603f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      switch(tr.getStatus()) {
1604f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        case ITestResult.SKIP:
1605f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          icl.onConfigurationSkip(tr);
1606f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          break;
1607f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        case ITestResult.FAILURE:
1608f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          icl.onConfigurationFailure(tr);
1609f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          break;
1610f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        case ITestResult.SUCCESS:
1611f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          icl.onConfigurationSuccess(tr);
1612f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          break;
1613f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1614f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1615f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1616f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1617c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust  void runTestListeners(ITestResult tr) {
1618f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    runTestListeners(tr, m_notifier.getTestListeners());
1619f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1620f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1621f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  // TODO: move this from here as it is directly called from TestNG
1622f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  public static void runTestListeners(ITestResult tr, List<ITestListener> listeners) {
1623f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for (ITestListener itl : listeners) {
1624f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      switch(tr.getStatus()) {
1625f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        case ITestResult.SKIP: {
1626f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          itl.onTestSkipped(tr);
1627f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          break;
1628f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1629f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        case ITestResult.SUCCESS_PERCENTAGE_FAILURE: {
1630f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          itl.onTestFailedButWithinSuccessPercentage(tr);
1631f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          break;
1632f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1633f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        case ITestResult.FAILURE: {
1634f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          itl.onTestFailure(tr);
1635f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          break;
1636f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1637f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        case ITestResult.SUCCESS: {
1638f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          itl.onTestSuccess(tr);
1639f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          break;
1640f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1641f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1642f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        case ITestResult.STARTED: {
1643f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          itl.onTestStart(tr);
1644f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          break;
1645f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1646f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1647f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        default: {
1648f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          assert false : "UNKNOWN STATUS:" + tr;
1649f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1650f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1651f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1652f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1653f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1654f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private static void ppp(String s) {
1655f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    System.out.println("[Invoker]" + s);
1656f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1657f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1658f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private void log(int level, String s) {
1659f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    Utils.log("Invoker " + Thread.currentThread().hashCode(), level, s);
1660f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1661f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1662bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//  private class DataTestMethodWorker implements IMethodWorker {
1663bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//    final Object[] m_instances;
1664bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//    final ITestNGMethod m_testMethod;
1665bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//    final ITestNGMethod[] m_beforeMethods;
1666bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//    final ITestNGMethod[] m_afterMethods;
1667bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//    final ConfigurationGroupMethods m_groupMethods;
1668bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//    final Object[] m_parameters;
1669bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//    final XmlSuite m_suite;
1670bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//    final Map<String, String> m_allParameterNames;
1671bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//
1672bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//    List<ITestResult> m_results;
1673bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//
1674bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//    public DataTestMethodWorker(Object[] instances,
1675bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//        ITestNGMethod testMethod,
1676bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//        Object[] params,
1677bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//        ITestNGMethod[] befores,
1678bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//        ITestNGMethod[] afters,
1679bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//        ConfigurationGroupMethods groupMethods,
1680bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//        XmlSuite suite,
1681bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//        Map<String, String> paramNames) {
1682bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//      m_instances= instances;
1683bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//      m_testMethod= testMethod;
1684bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//      m_parameters= params;
1685bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//      m_beforeMethods= befores;
1686bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//      m_afterMethods= afters;
1687bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//      m_groupMethods= groupMethods;
1688bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//      m_suite= suite;
1689bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//      m_allParameterNames= paramNames;
1690bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//    }
1691bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//
1692bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//    public long getMaxTimeOut() {
1693bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//      return 0;
1694bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//    }
1695bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//
1696bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//    public void run() {
1697bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//      m_results= invokeTestMethod(m_instances,
1698bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//          m_testMethod,
1699bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//          m_parameters,
1700bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//          m_suite,
1701bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//          m_allParameterNames,
1702bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//          m_testMethod.getTestClass(),
1703bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//          m_beforeMethods,
1704bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//          m_afterMethods,
1705bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//          m_groupMethods);
1706bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//    }
1707bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//
1708bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//    public List<ITestResult> getTestResults() {
1709bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//      return m_results;
1710bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//    }
1711bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//
1712bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//    public List<ITestNGMethod> getMethods() {
1713bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//      return Arrays.asList(m_testMethod);
1714bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//    }
1715bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//
1716bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//    public int getPriority() {
1717bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//      return 1;
1718bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//    }
1719bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//
1720bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//    public int compareTo(IMethodWorker other) {
1721bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//      return getPriority() - other.getPriority();
1722bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//    }
1723bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//
1724bf8793f759516dd01031191df20dddd2de71cd69Cédric Beust//  } // DataTestMethodWorker
1725f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1726f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private static class ParameterBag {
1727c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust    final ParameterHolder parameterHolder;
1728ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust    final List<ITestResult> errorResults= Lists.newArrayList();
1729f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1730c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust    public ParameterBag(ParameterHolder params, TestResult tr) {
1731c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust      parameterHolder = params;
1732f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if(tr != null) {
1733f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        errorResults.add(tr);
1734f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1735f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1736f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1737f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    public boolean hasErrors() {
1738f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      return !errorResults.isEmpty();
1739f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1740f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1741c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust
1742f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust}
1743