Invoker.java revision db04b1679d3367e54e61d7e6f8c225354e90081c
1f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustpackage org.testng.internal;
2f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
334ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beustimport static org.testng.internal.invokers.InvokedMethodListenerMethod.AFTER_INVOCATION;
434ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beustimport static org.testng.internal.invokers.InvokedMethodListenerMethod.BEFORE_INVOCATION;
534ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust
6f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.IClass;
70bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beustimport org.testng.IConfigurable;
8ee8e37d41d7e14252ee649f13768022fee714afbCédric Beustimport org.testng.IConfigurationListener;
9eef09e0a0ec23bcea1995c0813ca6d29580c7869Cédric Beustimport org.testng.IConfigurationListener2;
10f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.IHookable;
11398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beustimport org.testng.IInvokedMethod;
1238ef90d96ee65073c1090455e7caff2a85d654e2Cédric Beustimport org.testng.IInvokedMethodListener;
13f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.IRetryAnalyzer;
14f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.ITestClass;
15f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.ITestContext;
16f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.ITestListener;
17f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.ITestNGMethod;
18f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.ITestResult;
19f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.Reporter;
20f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.SkipException;
21f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.SuiteRunState;
22f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.TestException;
23f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.TestNGException;
242d568355761a9632bf24a87984e241f8a079d724Cédric Beustimport org.testng.annotations.IConfigurationAnnotation;
25aba3ac2f9fc3e370339b911598f62c7ffb6752aaCédric Beustimport org.testng.annotations.NoInjection;
26ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beustimport org.testng.collections.Lists;
270f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beustimport org.testng.collections.Maps;
28f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.internal.InvokeMethodRunnable.TestNGRuntimeException;
299150cdf3bacb4715cee345cd153d4f0ab3dbd198nullinimport org.testng.internal.ParameterHolder.ParameterOrigin;
30f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.internal.annotations.AnnotationHelper;
31f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.internal.annotations.IAnnotationFinder;
32f035a01bd8ac47425984d6b9e07a733f3abb3c37nullinimport org.testng.internal.annotations.Sets;
3392d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermannimport org.testng.internal.invokers.InvokedMethodListenerInvoker;
3492d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermannimport org.testng.internal.invokers.InvokedMethodListenerMethod;
35f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.internal.thread.ThreadExecutionException;
36f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.internal.thread.ThreadUtil;
37f035a01bd8ac47425984d6b9e07a733f3abb3c37nullinimport org.testng.internal.thread.graph.IWorker;
38f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.xml.XmlClass;
39f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.xml.XmlSuite;
40f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustimport org.testng.xml.XmlTest;
41f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
42423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beustimport java.lang.annotation.Annotation;
43423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beustimport java.lang.reflect.InvocationTargetException;
44423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beustimport java.lang.reflect.Method;
45caaf31e9587ae83c6b6064fa41fb939d362b4e37Cédric Beustimport java.util.Arrays;
46423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beustimport java.util.Iterator;
47423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beustimport java.util.List;
48423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beustimport java.util.Map;
49423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beustimport java.util.Set;
50423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beustimport java.util.regex.Pattern;
51423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust
52f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust/**
53f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust * This class is responsible for invoking methods:
54f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust * - test methods
55f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust * - configuration methods
56f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust * - possibly in a separate thread
57f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust * and then for notifying the result listeners.
58f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust *
59f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust * @author <a href="mailto:cedric@beust.com">Cedric Beust</a>
60f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust * @author <a href='mailto:the_mindstorm@evolva.ro'>Alexandru Popescu</a>
61f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust */
62f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beustpublic class Invoker implements IInvoker {
6321dad3370294d6595fdddc3faf55792f60a913f1nullin  private final ITestContext m_testContext;
6421dad3370294d6595fdddc3faf55792f60a913f1nullin  private final ITestResultNotifier m_notifier;
6521dad3370294d6595fdddc3faf55792f60a913f1nullin  private final IAnnotationFinder m_annotationFinder;
6621dad3370294d6595fdddc3faf55792f60a913f1nullin  private final SuiteRunState m_suiteState;
67eddb4a9423c14fee808a30e92ad77a16e88b320enullin  private final boolean m_skipFailedInvocationCounts;
6821dad3370294d6595fdddc3faf55792f60a913f1nullin  private final List<IInvokedMethodListener> m_invokedMethodListeners;
69eddb4a9423c14fee808a30e92ad77a16e88b320enullin  private final boolean m_continueOnFailedConfiguration;
7089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
7121dad3370294d6595fdddc3faf55792f60a913f1nullin  /** Group failures must be synced as the Invoker is accessed concurrently */
72423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust  private Map<String, Boolean> m_beforegroupsFailures = Maps.newHashtable();
7389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
7421dad3370294d6595fdddc3faf55792f60a913f1nullin  /** Class failures must be synced as the Invoker is accessed concurrently */
75f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin  private Map<Class<?>, Set<Object>> m_classInvocationResults = Maps.newHashtable();
7689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
7762a82c6aa5725c9e9d600af5ee06a5852100208cnullin  /** Test methods whose configuration methods have failed. */
78f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin  private Map<ITestNGMethod, Set<Object>> m_methodInvocationResults = Maps.newHashtable();
793297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust  private IConfiguration m_configuration;
8089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
819d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust  /** Predicate to filter methods */
829d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust  private static Predicate CAN_RUN_FROM_CLASS = new CanRunFromClassPredicate();
839d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust  /** Predicate to filter methods */
849d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust  private static final Predicate SAME_CLASS = new SameClassNamePredicate();
859d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust
86423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust  private void setClassInvocationFailure(Class<?> clazz, Object instance) {
87f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin    Set<Object> instances = m_classInvocationResults.get( clazz );
88423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust    if (instances == null) {
89f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin      instances = Sets.newHashSet();
90423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust      m_classInvocationResults.put(clazz, instances);
91423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust    }
92423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust    instances.add(instance);
9362a82c6aa5725c9e9d600af5ee06a5852100208cnullin  }
9489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
95423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust  private void setMethodInvocationFailure(ITestNGMethod method, Object instance) {
96f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin    Set<Object> instances = m_methodInvocationResults.get(method);
97423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust    if (instances == null) {
98f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin      instances = Sets.newHashSet();
99423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust      m_methodInvocationResults.put(method, instances);
100423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust    }
101423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust    instances.add(instance);
10262a82c6aa5725c9e9d600af5ee06a5852100208cnullin  }
103f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1043297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust  public Invoker(IConfiguration configuration,
1053297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust                 ITestContext testContext,
106f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                 ITestResultNotifier notifier,
107f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                 SuiteRunState state,
10838ef90d96ee65073c1090455e7caff2a85d654e2Cédric Beust                 boolean skipFailedInvocationCounts,
109398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust                 List<IInvokedMethodListener> invokedMethodListeners) {
1103297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust    m_configuration = configuration;
111f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    m_testContext= testContext;
112f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    m_suiteState= state;
113f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    m_notifier= notifier;
1143297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust    m_annotationFinder= configuration.getAnnotationFinder();
1156cf2e96a6b18fe7eecc44cac44bb0690a162f416Cédric Beust    m_skipFailedInvocationCounts = skipFailedInvocationCounts;
116398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust    m_invokedMethodListeners = invokedMethodListeners;
11762a82c6aa5725c9e9d600af5ee06a5852100208cnullin    m_continueOnFailedConfiguration = XmlSuite.CONTINUE.equals(testContext.getSuite().getXmlSuite().getConfigFailurePolicy());
118f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
119f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
120f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
121f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * Invoke configuration methods if they belong to the same TestClass passed
122f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * in parameter.. <p/>TODO: Calculate ahead of time which methods should be
123f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * invoked for each class. Might speed things up for users who invoke the
124f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * same test class with different parameters in the same suite run.
125f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   *
126f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * If instance is non-null, the configuration will be run on it.  If it is null,
127f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * the configuration methods will be run on all the instances retrieved
128f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * from the ITestClass.
129f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
130423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust  @Override
131f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  public void invokeConfigurations(IClass testClass,
132f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   ITestNGMethod[] allMethods,
133f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   XmlSuite suite,
134f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   Map<String, String> params,
135facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust                                   Object[] parameterValues,
136f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   Object instance)
137f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
138da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust    invokeConfigurations(testClass, null, allMethods, suite, params, parameterValues, instance,
139da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust        null);
140f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
141f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
142f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private void invokeConfigurations(IClass testClass,
143f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   ITestNGMethod currentTestMethod,
144f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   ITestNGMethod[] allMethods,
145f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   XmlSuite suite,
146f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   Map<String, String> params,
147facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust                                   Object[] parameterValues,
148da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust                                   Object instance,
149da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust                                   ITestResult testMethodResult)
150f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
151f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if(null == allMethods) {
152161d9860588ad89389848d70eb0a2f6f0cb46d1bCédric Beust      log(5, "No configuration methods found");
153f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
154f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      return;
155f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
156f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1579d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust    ITestNGMethod[] methods= filterMethods(testClass, allMethods, SAME_CLASS);
158f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
159f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for(ITestNGMethod tm : methods) {
160f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if(null == testClass) {
161f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        testClass= tm.getTestClass();
162f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
163f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
16489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      ITestResult testResult= new TestResult(testClass,
165f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             instance,
166f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             tm,
167f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             null,
168f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             System.currentTimeMillis(),
169f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             System.currentTimeMillis());
170f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1712d568355761a9632bf24a87984e241f8a079d724Cédric Beust      IConfigurationAnnotation configurationAnnotation= null;
172f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      try {
173f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        Object[] instances= tm.getInstances();
1740f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        if (instances == null || instances.length == 0) {
1750f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin          instances = new Object[] { instance };
1760f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        }
177f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        Class<?> objectClass= instances[0].getClass();
178f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        Method method= tm.getMethod();
179f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
180f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // Only run the configuration if
181f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // - the test is enabled and
182f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // - the Configuration method belongs to the same class or a parent
183f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if(MethodHelper.isEnabled(objectClass, m_annotationFinder)) {
184423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust          configurationAnnotation = AnnotationHelper.findConfiguration(m_annotationFinder, method);
185f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
186e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust          if (MethodHelper.isEnabled(configurationAnnotation)) {
1870501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust            boolean isClassConfiguration = isClassConfiguration(configurationAnnotation);
18889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin            boolean isSuiteConfiguration = isSuiteConfiguration(configurationAnnotation);
189e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            boolean alwaysRun= isAlwaysRun(configurationAnnotation);
19089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
191423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust            if (!confInvocationPassed(tm, currentTestMethod, testClass, instance) && !alwaysRun) {
192423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust              handleConfigurationSkip(tm, testResult, configurationAnnotation, currentTestMethod, instance, suite);
193e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust              continue;
194e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            }
19589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
196e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            log(3, "Invoking " + Utils.detailedMethodName(tm, true));
19789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
198facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust            Object[] parameters = Parameters.createConfigurationParameters(tm.getMethod(),
199facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust                params,
200facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust                parameterValues,
201facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust                currentTestMethod,
202facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust                m_annotationFinder,
203facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust                suite,
204da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust                m_testContext,
205da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust                testMethodResult);
206e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            testResult.setParameters(parameters);
20789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
208e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            Object[] newInstances= (null != instance) ? new Object[] { instance } : instances;
20989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
210ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust            runConfigurationListeners(testResult, true /* before */);
211ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust
212e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            invokeConfigurationMethod(newInstances, tm,
2130501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust              parameters, isClassConfiguration, isSuiteConfiguration, testResult);
21489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
215e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            // TODO: probably we should trigger the event for each instance???
216e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            testResult.setEndMillis(System.currentTimeMillis());
217ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust            runConfigurationListeners(testResult, false /* after */);
218e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust          }
219e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust          else {
220e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            log(3,
221e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust                "Skipping "
222e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust                + Utils.detailedMethodName(tm, true)
223e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust                + " because it is not enabled");
224f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
225f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        } // if is enabled
226f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        else {
227f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          log(3,
228f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              "Skipping "
229f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              + Utils.detailedMethodName(tm, true)
230f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              + " because "
231f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              + objectClass.getName()
232f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              + " is not enabled");
233f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
234f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
235f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      catch(InvocationTargetException ex) {
236423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust        handleConfigurationFailure(ex, tm, testResult, configurationAnnotation, currentTestMethod, instance, suite);
237f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
238f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      catch(TestNGException ex) {
239f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // Don't wrap TestNGExceptions, it could be a missing parameter on a
240f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // @Configuration method
241423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust        handleConfigurationFailure(ex, tm, testResult, configurationAnnotation, currentTestMethod, instance, suite);
242f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
243f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      catch(Throwable ex) { // covers the non-wrapper exceptions
244423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust        handleConfigurationFailure(ex, tm, testResult, configurationAnnotation, currentTestMethod, instance, suite);
245f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
246f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    } // for methods
247f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
24889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
249f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
25062a82c6aa5725c9e9d600af5ee06a5852100208cnullin   * Marks the current <code>TestResult</code> as skipped and invokes the listeners.
251f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
25289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin  private void handleConfigurationSkip(ITestNGMethod tm,
25389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                       ITestResult testResult,
25489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                       IConfigurationAnnotation annotation,
25589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                       ITestNGMethod currentTestMethod,
256423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust                                       Object instance,
25762a82c6aa5725c9e9d600af5ee06a5852100208cnullin                                       XmlSuite suite) {
258423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust    recordConfigurationInvocationFailed(tm, testResult.getTestClass(), annotation, currentTestMethod, instance, suite);
259f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    testResult.setStatus(ITestResult.SKIP);
260ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust    runConfigurationListeners(testResult, false /* after */);
261f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
26289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
263f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
264f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * Is the current <code>IConfiguration</code> a class-level method.
265f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
2662d568355761a9632bf24a87984e241f8a079d724Cédric Beust  private  boolean isClassConfiguration(IConfigurationAnnotation configurationAnnotation) {
2670b2ac5eab08098da2c2b63d4a3f87ba72ad5d6a1nullin    if (null == configurationAnnotation) {
268f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      return false;
269f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
270f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
2710b2ac5eab08098da2c2b63d4a3f87ba72ad5d6a1nullin    boolean before = configurationAnnotation.getBeforeTestClass();
2720b2ac5eab08098da2c2b63d4a3f87ba72ad5d6a1nullin    boolean after = configurationAnnotation.getAfterTestClass();
273f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
2740b2ac5eab08098da2c2b63d4a3f87ba72ad5d6a1nullin    return before || after;
275f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
276f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
277f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
2780501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust   * Is the current <code>IConfiguration</code> a suite level method.
2790501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust   */
2800501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust  private  boolean isSuiteConfiguration(IConfigurationAnnotation configurationAnnotation) {
2810b2ac5eab08098da2c2b63d4a3f87ba72ad5d6a1nullin    if (null == configurationAnnotation) {
2820501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust      return false;
2830501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust    }
2840501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust
2850b2ac5eab08098da2c2b63d4a3f87ba72ad5d6a1nullin    boolean before = configurationAnnotation.getBeforeSuite();
2860b2ac5eab08098da2c2b63d4a3f87ba72ad5d6a1nullin    boolean after = configurationAnnotation.getAfterSuite();
2870501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust
2880b2ac5eab08098da2c2b63d4a3f87ba72ad5d6a1nullin    return before || after;
2890501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust  }
2900501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust
2910501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust  /**
292f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * Is the <code>IConfiguration</code> marked as alwaysRun.
293f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
2942d568355761a9632bf24a87984e241f8a079d724Cédric Beust  private boolean isAlwaysRun(IConfigurationAnnotation configurationAnnotation) {
295f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if(null == configurationAnnotation) {
296f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      return false;
297f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
29889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
299f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    boolean alwaysRun= false;
300f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if ((configurationAnnotation.getAfterSuite()
301f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        || configurationAnnotation.getAfterTest()
302f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        || configurationAnnotation.getAfterTestClass()
303f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        || configurationAnnotation.getAfterTestMethod())
304f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        && configurationAnnotation.getAlwaysRun())
305f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    {
306f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        alwaysRun= true;
307f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
30889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
309f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return alwaysRun;
310f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
31189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
312f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private void handleConfigurationFailure(Throwable ite,
313f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                          ITestNGMethod tm,
314f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                          ITestResult testResult,
3152d568355761a9632bf24a87984e241f8a079d724Cédric Beust                                          IConfigurationAnnotation annotation,
31662a82c6aa5725c9e9d600af5ee06a5852100208cnullin                                          ITestNGMethod currentTestMethod,
317423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust                                          Object instance,
31889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                          XmlSuite suite)
319f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
320f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    Throwable cause= ite.getCause() != null ? ite.getCause() : ite;
32189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
322f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if(SkipException.class.isAssignableFrom(cause.getClass())) {
323f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      SkipException skipEx= (SkipException) cause;
3240c3edfde6ca92fb2cfeb3072fa1c7cb08c1706c3DanFabulich      if(skipEx.isSkip()) {
325f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        testResult.setThrowable(skipEx);
326423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust        handleConfigurationSkip(tm, testResult, annotation, currentTestMethod, instance, suite);
327f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        return;
328f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
329f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
330161d9860588ad89389848d70eb0a2f6f0cb46d1bCédric Beust    Utils.log("", 3, "Failed to invoke configuration method "
331f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        + tm.getRealClass().getName() + "." + tm.getMethodName() + ":" + cause.getMessage());
332f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    handleException(cause, tm, testResult, 1);
333ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust    runConfigurationListeners(testResult, false /* after */);
334f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
33589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin    //
336f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // If in TestNG mode, need to take a look at the annotation to figure out
337f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // what kind of @Configuration method we're dealing with
338f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
339f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if (null != annotation) {
340423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust      recordConfigurationInvocationFailed(tm, testResult.getTestClass(), annotation, currentTestMethod, instance, suite);
341f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
342f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
343f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
344f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
345f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return All the classes that belong to the same <test> tag as @param cls
346f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
347f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private XmlClass[] findClassesInSameTest(Class<?> cls, XmlSuite suite) {
3480f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beust    Map<String, XmlClass> vResult= Maps.newHashMap();
349f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    String className= cls.getName();
350f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for(XmlTest test : suite.getTests()) {
351f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for(XmlClass testClass : test.getXmlClasses()) {
352f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if(testClass.getName().equals(className)) {
353f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
354f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          // Found it, add all the classes in this test in the result
355f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          for(XmlClass thisClass : test.getXmlClasses()) {
356f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            vResult.put(thisClass.getName(), thisClass);
357f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
358f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          // Note:  we need to iterate through the entire suite since the same
359f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          // class might appear in several <test> tags
360f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
361f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
362f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
363f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
364f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    XmlClass[] result= vResult.values().toArray(new XmlClass[vResult.size()]);
365f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
366f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return result;
367f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
368f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
369f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
370f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * Record internally the failure of a Configuration, so that we can determine
371f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * later if @Test should be skipped.
372f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
37389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin  private void recordConfigurationInvocationFailed(ITestNGMethod tm,
37489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                   IClass testClass,
37589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                   IConfigurationAnnotation annotation,
37689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                   ITestNGMethod currentTestMethod,
377423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust                                                   Object instance,
37862a82c6aa5725c9e9d600af5ee06a5852100208cnullin                                                   XmlSuite suite) {
37962a82c6aa5725c9e9d600af5ee06a5852100208cnullin    // If beforeTestClass or afterTestClass failed, mark either the config method's
38062a82c6aa5725c9e9d600af5ee06a5852100208cnullin    // entire class as failed, or the class under tests as failed, depending on
38162a82c6aa5725c9e9d600af5ee06a5852100208cnullin    // the configuration failure policy
38262a82c6aa5725c9e9d600af5ee06a5852100208cnullin    if (annotation.getBeforeTestClass() || annotation.getAfterTestClass()) {
38362a82c6aa5725c9e9d600af5ee06a5852100208cnullin      // tm is the configuration method, and currentTestMethod is null for BeforeClass
38462a82c6aa5725c9e9d600af5ee06a5852100208cnullin      // methods, so we need testClass
38562a82c6aa5725c9e9d600af5ee06a5852100208cnullin      if (m_continueOnFailedConfiguration) {
386423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust        setClassInvocationFailure(testClass.getRealClass(), instance);
38762a82c6aa5725c9e9d600af5ee06a5852100208cnullin      } else {
388423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust        setClassInvocationFailure(tm.getRealClass(), instance);
38962a82c6aa5725c9e9d600af5ee06a5852100208cnullin      }
39062a82c6aa5725c9e9d600af5ee06a5852100208cnullin    }
39189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
39262a82c6aa5725c9e9d600af5ee06a5852100208cnullin    // If before/afterTestMethod failed, mark either the config method's entire
39362a82c6aa5725c9e9d600af5ee06a5852100208cnullin    // class as failed, or just the current test method as failed, depending on
39462a82c6aa5725c9e9d600af5ee06a5852100208cnullin    // the configuration failure policy
39562a82c6aa5725c9e9d600af5ee06a5852100208cnullin    else if (annotation.getBeforeTestMethod() || annotation.getAfterTestMethod()) {
39662a82c6aa5725c9e9d600af5ee06a5852100208cnullin      if (m_continueOnFailedConfiguration) {
397423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust        setMethodInvocationFailure(currentTestMethod, instance);
39862a82c6aa5725c9e9d600af5ee06a5852100208cnullin      } else {
399423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust        setClassInvocationFailure(tm.getRealClass(), instance);
40062a82c6aa5725c9e9d600af5ee06a5852100208cnullin      }
401f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
402f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
403f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // If beforeSuite or afterSuite failed, mark *all* the classes as failed
404f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // for configurations.  At this point, the entire Suite is screwed
405f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    else if (annotation.getBeforeSuite() || annotation.getAfterSuite()) {
406f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      m_suiteState.failed();
407f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
408f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
409f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // beforeTest or afterTest:  mark all the classes in the same
410f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // <test> stanza as failed for configuration
411f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    else if (annotation.getBeforeTest() || annotation.getAfterTest()) {
412423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust      setClassInvocationFailure(tm.getRealClass(), instance);
413f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      XmlClass[] classes= findClassesInSameTest(tm.getRealClass(), suite);
414f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for(XmlClass xmlClass : classes) {
415423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust        setClassInvocationFailure(xmlClass.getSupportClass(), instance);
416f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
417f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
418f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    String[] beforeGroups= annotation.getBeforeGroups();
419f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if(null != beforeGroups && beforeGroups.length > 0) {
420f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for(String group: beforeGroups) {
421f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        m_beforegroupsFailures.put(group, Boolean.FALSE);
422f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
423f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
424f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
42589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
426f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
427f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return true if this class has successfully run all its @Configuration
428f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * method or false if at least one of these methods failed.
429f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
430423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust  private boolean confInvocationPassed(ITestNGMethod method, ITestNGMethod currentTestMethod, IClass testClass, Object instance) {
431f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    boolean result= true;
432f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
43362a82c6aa5725c9e9d600af5ee06a5852100208cnullin    // If continuing on config failure, check invocation results for the class
43462a82c6aa5725c9e9d600af5ee06a5852100208cnullin    // under test, otherwise use the method's declaring class
43589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin    Class<?> cls = m_continueOnFailedConfiguration ?
43662a82c6aa5725c9e9d600af5ee06a5852100208cnullin            testClass.getRealClass() : method.getMethod().getDeclaringClass();
43762a82c6aa5725c9e9d600af5ee06a5852100208cnullin
438f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if(m_suiteState.isFailed()) {
439f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      result= false;
440f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
441f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    else {
442423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust      if (m_classInvocationResults.containsKey(cls)) {
4430f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        if (! m_continueOnFailedConfiguration) {
4440f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin          result = !m_classInvocationResults.containsKey(cls);
4450f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        } else {
4460f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin          result = !m_classInvocationResults.get(cls).contains(instance);
4470f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        }
448f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
44962a82c6aa5725c9e9d600af5ee06a5852100208cnullin      // if method is BeforeClass, currentTestMethod will be null
45089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      else if (m_continueOnFailedConfiguration &&
45189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin              currentTestMethod != null &&
45262a82c6aa5725c9e9d600af5ee06a5852100208cnullin              m_methodInvocationResults.containsKey(currentTestMethod)) {
453423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust        result = !m_methodInvocationResults.get(currentTestMethod).contains(instance);
45462a82c6aa5725c9e9d600af5ee06a5852100208cnullin      }
455423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust      else if (! m_continueOnFailedConfiguration) {
456f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        for(Class<?> clazz: m_classInvocationResults.keySet()) {
4571e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust//          if (clazz == cls) {
458f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          if(clazz.isAssignableFrom(cls)) {
459f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            result= false;
460f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            break;
461f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
462f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
463f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
464f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
465f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
466f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // check if there are failed @BeforeGroups
467f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    String[] groups= method.getGroups();
468f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if(null != groups && groups.length > 0) {
469f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for(String group: groups) {
470f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if(m_beforegroupsFailures.containsKey(group)) {
471f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          result= false;
472f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          break;
473f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
474f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
475f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
476f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return result;
477f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
478f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
479f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
480f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * Effectively invokes a configuration method on all passed in instances.
481d3c04c36b8f179fd5aa1b53711a5b909cde06d09nalin.makar@gmail.com   * TODO: Should change this method to be more like invokeMethod() so that we can
482d3c04c36b8f179fd5aa1b53711a5b909cde06d09nalin.makar@gmail.com   * handle calls to {@code IInvokedMethodListener} better.
48389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin   *
484f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param instances the instances to invoke the configuration method on
485f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param tm the configuration method
486f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param params the parameters needed for method invocation
487f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param isClass flag if the configuration method is a class level method // FIXME: this looks like a missusage
488f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param testResult
489f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @throws InvocationTargetException
490f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @throws IllegalAccessException
491f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
492f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private void invokeConfigurationMethod(Object[] instances,
493f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                         ITestNGMethod tm,
494f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                         Object[] params,
495f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                         boolean isClass,
4960501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust                                         boolean isSuite,
497f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                         ITestResult testResult)
49889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin    throws InvocationTargetException, IllegalAccessException
499f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
500f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Mark this method with the current thread id
501f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    tm.setId(ThreadUtil.currentThreadInfo());
502f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
503caaf31e9587ae83c6b6064fa41fb939d362b4e37Cédric Beust    // Only a @BeforeMethod/@AfterMethod needs to be run before each instance, all the other
504caaf31e9587ae83c6b6064fa41fb939d362b4e37Cédric Beust    // configuration methods only need to be run once
505caaf31e9587ae83c6b6064fa41fb939d362b4e37Cédric Beust    List<Object> actualInstances = Lists.newArrayList();
506caaf31e9587ae83c6b6064fa41fb939d362b4e37Cédric Beust    if (tm.isBeforeMethodConfiguration() || tm.isAfterMethodConfiguration()) {
507caaf31e9587ae83c6b6064fa41fb939d362b4e37Cédric Beust      actualInstances.addAll(Arrays.asList(instances));
508caaf31e9587ae83c6b6064fa41fb939d362b4e37Cédric Beust    } else {
509caaf31e9587ae83c6b6064fa41fb939d362b4e37Cédric Beust      actualInstances.add(instances[0]);
510caaf31e9587ae83c6b6064fa41fb939d362b4e37Cédric Beust    }
511caaf31e9587ae83c6b6064fa41fb939d362b4e37Cédric Beust    for(Object targetInstance : actualInstances) {
51292d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann      InvokedMethod invokedMethod= new InvokedMethod(targetInstance,
513f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                          tm,
514f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                          params,
515f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                          false, /* isTest */
516f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                          isClass, /* ??? */
517f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                          System.currentTimeMillis());
518f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
51992d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann      runInvokedMethodListeners(BEFORE_INVOCATION, invokedMethod, testResult);
52092d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann      m_notifier.addInvokedMethod(invokedMethod);
521f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      try {
522f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        Reporter.setCurrentTestResult(testResult);
5230bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust        Method method = tm.getMethod();
524e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust
525e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust        //
526e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust        // If this method is a IHookable, invoke its run() method
527e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust        //
528e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust        IConfigurable configurableInstance =
529e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust          IConfigurable.class.isAssignableFrom(tm.getMethod().getDeclaringClass()) ?
530e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust          (IConfigurable) targetInstance : m_configuration.getConfigurable();
531e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust        if (configurableInstance != null) {
5320bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust          //
5330bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust          // If this method is a IConfigurable, invoke its run() method
5340bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust          //
535b1c182d51b05a40ac5350e562503a94d024a7c80nullin          MethodInvocationHelper.invokeConfigurable(targetInstance, params, configurableInstance, method,
536e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust              testResult);
5370bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust        }
5380bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust        else {
5390bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust          //
540830ff4bf3fbfae0d63cb762b9c0d9a184feb58a3Cédric Beust          // Not a IConfigurable, invoke directly
5410bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust          //
542830ff4bf3fbfae0d63cb762b9c0d9a184feb58a3Cédric Beust          if (MethodHelper.calculateTimeOut(tm) <= 0) {
543b1c182d51b05a40ac5350e562503a94d024a7c80nullin            MethodInvocationHelper.invokeMethod(method, targetInstance, params);
544830ff4bf3fbfae0d63cb762b9c0d9a184feb58a3Cédric Beust          }
545830ff4bf3fbfae0d63cb762b9c0d9a184feb58a3Cédric Beust          else {
546b1c182d51b05a40ac5350e562503a94d024a7c80nullin            MethodInvocationHelper.invokeWithTimeout(tm, targetInstance, params, testResult);
547830ff4bf3fbfae0d63cb762b9c0d9a184feb58a3Cédric Beust            if (!testResult.isSuccess()) {
548830ff4bf3fbfae0d63cb762b9c0d9a184feb58a3Cédric Beust              // A time out happened
549830ff4bf3fbfae0d63cb762b9c0d9a184feb58a3Cédric Beust              throwConfigurationFailure(testResult, testResult.getThrowable());
550830ff4bf3fbfae0d63cb762b9c0d9a184feb58a3Cédric Beust              throw testResult.getThrowable();
551830ff4bf3fbfae0d63cb762b9c0d9a184feb58a3Cédric Beust            }
552830ff4bf3fbfae0d63cb762b9c0d9a184feb58a3Cédric Beust          }
5530bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust        }
5540501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust        // Only run the method once if it's @BeforeSuite or @AfterSuite
5550f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        if (isSuite) {
5560f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin          break;
5570f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        }
558db66a3de4428040dd9f7e377a3b6835965c8b0cdCédric Beust      }
559d3c04c36b8f179fd5aa1b53711a5b909cde06d09nalin.makar@gmail.com      catch (InvocationTargetException ex) {
5600bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust       throwConfigurationFailure(testResult, ex);
5610bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust       throw ex;
562d3c04c36b8f179fd5aa1b53711a5b909cde06d09nalin.makar@gmail.com      }
563d3c04c36b8f179fd5aa1b53711a5b909cde06d09nalin.makar@gmail.com      catch (IllegalAccessException ex) {
5640bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust        throwConfigurationFailure(testResult, ex);
5650bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust        throw ex;
5660bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust      }
5670bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust      catch (NoSuchMethodException ex) {
5680bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust        throwConfigurationFailure(testResult, ex);
5690bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust        throw new TestNGException(ex);
5700bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust      }
5710bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust      catch (Throwable ex) {
5720bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust        throwConfigurationFailure(testResult, ex);
5730bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust        throw new TestNGException(ex);
5740bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust      }
5750bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust      finally {
576f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        Reporter.setCurrentTestResult(testResult);
57792d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann        runInvokedMethodListeners(AFTER_INVOCATION, invokedMethod, testResult);
57889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      }
579f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
580f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
581f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
5820bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust  private void throwConfigurationFailure(ITestResult testResult, Throwable ex)
5830bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust  {
5840bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust    testResult.setStatus(ITestResult.FAILURE);;
5850bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust    testResult.setThrowable(ex.getCause() == null ? ex : ex.getCause());
5860bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust  }
5870bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust
58892d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann  private void runInvokedMethodListeners(InvokedMethodListenerMethod listenerMethod, IInvokedMethod invokedMethod,
589398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust      ITestResult testResult)
590398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust  {
59192d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann    if ( noListenersPresent() ) {
59292d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann      return;
593398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust    }
59492d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann
59592d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann    InvokedMethodListenerInvoker invoker = new InvokedMethodListenerInvoker(listenerMethod, testResult, m_testContext);
59692d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann    for (IInvokedMethodListener currentListener : m_invokedMethodListeners) {
59792d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann      invoker.invokeListener(currentListener, invokedMethod);
59892d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann    }
59992d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann  }
60092d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann
60192d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann  private boolean noListenersPresent() {
60292d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann    return (m_invokedMethodListeners == null) || (m_invokedMethodListeners.size() == 0);
603398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust  }
604398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust
605927a6d8a655520943e3a8a9ea9f09cbfe56f2ae6Cédric Beust  // pass both paramValues and paramIndex to be thread safe in case parallel=true + dataprovider.
606f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private ITestResult invokeMethod(Object[] instances,
607f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   int instanceIndex,
608f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   final ITestNGMethod tm,
609f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   Object[] parameterValues,
610927a6d8a655520943e3a8a9ea9f09cbfe56f2ae6Cédric Beust                                   int parametersIndex,
611f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   XmlSuite suite,
612f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   Map<String, String> params,
613f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   ITestClass testClass,
614f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   ITestNGMethod[] beforeMethods,
615f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   ITestNGMethod[] afterMethods,
616f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   ConfigurationGroupMethods groupMethods) {
61794efdf8e6ac7332eadf8bfe5d1fe699caee5d051Cédric Beust    TestResult testResult = new TestResult();
61894efdf8e6ac7332eadf8bfe5d1fe699caee5d051Cédric Beust
619f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
620f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Invoke beforeGroups configurations
621f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
6223297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust    Object instance = instances[instanceIndex];
623f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    invokeBeforeGroupsConfigurations(testClass, tm, groupMethods, suite, params,
6243297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust        instance);
625f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
626f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
62745a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust    // Invoke beforeMethods only if
62845a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust    // - firstTimeOnly is not set
62945a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust    // - firstTimeOnly is set, and we are reaching at the first invocationCount
630f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
63189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin    invokeConfigurations(testClass, tm,
63245a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      filterConfigurationMethods(tm, beforeMethods, true /* beforeMethods */),
633facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust      suite, params, parameterValues,
6343297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust      instance, testResult);
63589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
636f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
637f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Create the ExtraOutput for this method
638f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
63938ef90d96ee65073c1090455e7caff2a85d654e2Cédric Beust    InvokedMethod invokedMethod = null;
640f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    try {
6413297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust      testResult.init(testClass, instance,
642f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                 tm,
643f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                 null,
644f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                 System.currentTimeMillis(),
645f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                 0);
646f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      testResult.setParameters(parameterValues);
647f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      testResult.setHost(m_testContext.getHost());
648f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      testResult.setStatus(ITestResult.STARTED);
649f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
6503297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust      invokedMethod= new InvokedMethod(instance,
651f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          tm,
652f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          parameterValues,
653e934f66fb4fb247ebf5fec45770bc6820fbba29anullin          true /* isTest */,
654e934f66fb4fb247ebf5fec45770bc6820fbba29anullin          false /* isConfiguration */,
655f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          System.currentTimeMillis());
656f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
657272431b36621155717086ce4a384855f3003fff1Ansgar Konermann      // Fix from ansgarkonermann
658272431b36621155717086ce4a384855f3003fff1Ansgar Konermann      // invokedMethod is used in the finally, which can be invoked if
659272431b36621155717086ce4a384855f3003fff1Ansgar Konermann      // any of the test listeners throws an exception, therefore,
660272431b36621155717086ce4a384855f3003fff1Ansgar Konermann      // invokedMethod must have a value before we get here
66159d29c5fddc09eb6dc132569b0f4c4026f033b1aAnsgar Konermann      runTestListeners(testResult);
66259d29c5fddc09eb6dc132569b0f4c4026f033b1aAnsgar Konermann
66392d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann      runInvokedMethodListeners(BEFORE_INVOCATION, invokedMethod, testResult);
66438ef90d96ee65073c1090455e7caff2a85d654e2Cédric Beust
665f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      m_notifier.addInvokedMethod(invokedMethod);
66689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
667f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Method thisMethod= tm.getMethod();
66889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
6693297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust      if(confInvocationPassed(tm, tm, testClass, instance)) {
670f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        log(3, "Invoking " + thisMethod.getDeclaringClass().getName() + "." +
671f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            thisMethod.getName());
672f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
673f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // If no timeOut, just invoke the method
674331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust        if (MethodHelper.calculateTimeOut(tm) <= 0) {
675711b9b624165b9185efea58f010a40275e19c972mendelson.paul          try {
676711b9b624165b9185efea58f010a40275e19c972mendelson.paul            Reporter.setCurrentTestResult(testResult);
677711b9b624165b9185efea58f010a40275e19c972mendelson.paul            //
678711b9b624165b9185efea58f010a40275e19c972mendelson.paul            // If this method is a IHookable, invoke its run() method
679711b9b624165b9185efea58f010a40275e19c972mendelson.paul            //
680e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust            IHookable hookableInstance =
681e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust              IHookable.class.isAssignableFrom(thisMethod.getDeclaringClass()) ?
682e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust              (IHookable) instance : m_configuration.getHookable();
683e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust            if (hookableInstance != null) {
684b1c182d51b05a40ac5350e562503a94d024a7c80nullin              MethodInvocationHelper.invokeHookable(instance,
685e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust                  parameterValues, hookableInstance, thisMethod, testResult);
686711b9b624165b9185efea58f010a40275e19c972mendelson.paul            }
687711b9b624165b9185efea58f010a40275e19c972mendelson.paul            //
688711b9b624165b9185efea58f010a40275e19c972mendelson.paul            // Not a IHookable, invoke directly
689711b9b624165b9185efea58f010a40275e19c972mendelson.paul            //
690711b9b624165b9185efea58f010a40275e19c972mendelson.paul            else {
691b1c182d51b05a40ac5350e562503a94d024a7c80nullin              MethodInvocationHelper.invokeMethod(thisMethod, instance,
692f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                  parameterValues);
69389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin            }
694711b9b624165b9185efea58f010a40275e19c972mendelson.paul            testResult.setStatus(ITestResult.SUCCESS);
695711b9b624165b9185efea58f010a40275e19c972mendelson.paul          }
696711b9b624165b9185efea58f010a40275e19c972mendelson.paul          finally {
697711b9b624165b9185efea58f010a40275e19c972mendelson.paul            Reporter.setCurrentTestResult(null);
698f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
699f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
700f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        else {
701331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust          //
702331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust          // Method with a timeout
703331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust          //
704f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          try {
705f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            Reporter.setCurrentTestResult(testResult);
706b1c182d51b05a40ac5350e562503a94d024a7c80nullin            MethodInvocationHelper.invokeWithTimeout(tm, instance, parameterValues, testResult);
707f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
708f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          finally {
709f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            Reporter.setCurrentTestResult(null);
710f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
711f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
712f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
713f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      else {
714f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        testResult.setStatus(ITestResult.SKIP);
715f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
716f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
717f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    catch(InvocationTargetException ite) {
718f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      testResult.setThrowable(ite.getCause());
719d3c04c36b8f179fd5aa1b53711a5b909cde06d09nalin.makar@gmail.com      testResult.setStatus(ITestResult.FAILURE);
720f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
721f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    catch(ThreadExecutionException tee) { // wrapper for TestNGRuntimeException
722f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Throwable cause= tee.getCause();
723f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if(TestNGRuntimeException.class.equals(cause.getClass())) {
724f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        testResult.setThrowable(cause.getCause());
725f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
726f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      else {
727f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        testResult.setThrowable(cause);
728f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
729d3c04c36b8f179fd5aa1b53711a5b909cde06d09nalin.makar@gmail.com      testResult.setStatus(ITestResult.FAILURE);
730f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
731f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    catch(Throwable thr) { // covers the non-wrapper exceptions
732f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      testResult.setThrowable(thr);
733d3c04c36b8f179fd5aa1b53711a5b909cde06d09nalin.makar@gmail.com      testResult.setStatus(ITestResult.FAILURE);
734f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
735f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    finally {
736bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust      ExpectedExceptionsHolder expectedExceptionClasses
737318a4e47ce813109c76fc8281c9db5f04448f3f1Cédric Beust          = MethodHelper.findExpectedExceptions(m_annotationFinder, tm.getMethod());
738ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust      List<ITestResult> results = Lists.newArrayList();
739318a4e47ce813109c76fc8281c9db5f04448f3f1Cédric Beust      results.add(testResult);
7406216d78ae0757b7d57aa6e94cc041447d610724dCédric Beust      handleInvocationResults(tm, results, null, 0, expectedExceptionClasses, false,
74134ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust          false /* collect results */);
74289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
743dd84c4f1673772d6b1febb72add6a2ae40f4e4ccCédric Beust      // If this method has a data provider and just failed, memorize the number
744dd84c4f1673772d6b1febb72add6a2ae40f4e4ccCédric Beust      // at which it failed.
7451ed096c7af783713cdeb4a3e9c0c4a02491d65fcCédric Beust      // Note: we're not exactly testing that this method has a data provider, just
7461ed096c7af783713cdeb4a3e9c0c4a02491d65fcCédric Beust      // that it has parameters, so might have to revisit this if bugs get reported
7471ed096c7af783713cdeb4a3e9c0c4a02491d65fcCédric Beust      // for the case where this method has parameters that don't come from a data
7481ed096c7af783713cdeb4a3e9c0c4a02491d65fcCédric Beust      // provider
749dd84c4f1673772d6b1febb72add6a2ae40f4e4ccCédric Beust      if (testResult.getThrowable() != null && parameterValues.length > 0) {
750927a6d8a655520943e3a8a9ea9f09cbfe56f2ae6Cédric Beust        tm.addFailedInvocationNumber(parametersIndex);
751dd84c4f1673772d6b1febb72add6a2ae40f4e4ccCédric Beust      }
752dd84c4f1673772d6b1febb72add6a2ae40f4e4ccCédric Beust
753f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
754f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // Increment the invocation count for this method
755f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
756f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      tm.incrementCurrentInvocationCount();
757f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
758f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if (testResult != null) {
759f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        testResult.setEndMillis(System.currentTimeMillis());
760f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
761bacea92cd4a97cc839df9533025400c343a4689fCédric Beust
7627ba4f0edf349cd33491ea94c9ccf88ba9e1fa117Cédric Beust      // Run invokedMethodListeners after updating TestResult
7637ba4f0edf349cd33491ea94c9ccf88ba9e1fa117Cédric Beust      runInvokedMethodListeners(AFTER_INVOCATION, invokedMethod, testResult);
7647ba4f0edf349cd33491ea94c9ccf88ba9e1fa117Cédric Beust      runTestListeners(testResult);
76534ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust      collectResults(tm, results, testResult);
766bacea92cd4a97cc839df9533025400c343a4689fCédric Beust
767f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
76845a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      // Invoke afterMethods only if
76945a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      // - lastTimeOnly is not set
77045a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      // - lastTimeOnly is set, and we are reaching the last invocationCount
771f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
77289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      invokeConfigurations(testClass, tm,
77345a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust          filterConfigurationMethods(tm, afterMethods, false /* beforeMethods */),
774facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust          suite, params, parameterValues,
7753297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust          instance,
776da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust          testResult);
77789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
778f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
77945a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      // Invoke afterGroups configurations
780f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
781f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      invokeAfterGroupsConfigurations(testClass, tm, groupMethods, suite,
7823297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust          params, instance);
783f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
78494efdf8e6ac7332eadf8bfe5d1fe699caee5d051Cédric Beust
785f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return testResult;
786f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
78789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
78834ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust  private void collectResults(ITestNGMethod testMethod, List<ITestResult> results, TestResult testResult) {
78934ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust    for (int i = 0; i < results.size(); i++) {
79034ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust      // Collect the results
79134ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust      int status = results.get(i).getStatus();
79234ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust      if(ITestResult.SUCCESS == status) {
79334ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust        m_notifier.addPassedTest(testMethod, testResult);
79434ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust      }
79534ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust      else if(ITestResult.SKIP == status) {
79634ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust        m_notifier.addSkippedTest(testMethod, testResult);
79734ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust      }
79834ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust      else if(ITestResult.FAILURE == status) {
79934ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust        m_notifier.addFailedTest(testMethod, testResult);
80034ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust      }
80134ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust      else if(ITestResult.SUCCESS_PERCENTAGE_FAILURE == status) {
80234ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust        m_notifier.addFailedButWithinSuccessPercentageTest(testMethod, testResult);
80334ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust      }
80434ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust      else {
80534ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust        assert false : "UNKNOWN STATUS:" + status;
80634ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust      }
80734ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust    }
80834ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust  }
80934ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust
810f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
81145a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust   * The array of methods contains @BeforeMethods if isBefore if true, @AfterMethods
81245a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust   * otherwise.  This function removes all the methods that should not be run at this
81345a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust   * point because they are either firstTimeOnly or lastTimeOnly and we haven't reached
81445a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust   * the current invocationCount yet
81545a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust   */
81645a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust  private ITestNGMethod[] filterConfigurationMethods(ITestNGMethod tm,
81745a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      ITestNGMethod[] methods, boolean isBefore)
81845a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust  {
819ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust    List<ITestNGMethod> result = Lists.newArrayList();
82045a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust    for (ITestNGMethod m : methods) {
82145a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      ConfigurationMethod cm = (ConfigurationMethod) m;
82245a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      if (isBefore) {
82345a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust        if (! cm.isFirstTimeOnly() ||
82445a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust            (cm.isFirstTimeOnly() && tm.getCurrentInvocationCount() == 0))
82545a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust        {
82645a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust          result.add(m);
82745a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust        }
82845a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      }
82945a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      else {
830d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust        int current = tm.getCurrentInvocationCount();
831d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust        boolean isLast = false;
8322fc881781da9eb64b913650c8bb856d1f97c64cdCédric Beust        // If we have parameters, set the boolean if we are about to run
8332fc881781da9eb64b913650c8bb856d1f97c64cdCédric Beust        // the last invocation
834d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust        if (tm.getParameterInvocationCount() > 0) {
835d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust          isLast = current == tm.getParameterInvocationCount();
836d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust        }
8372fc881781da9eb64b913650c8bb856d1f97c64cdCédric Beust        // If we have invocationCount > 1, set the boolean if we are about to
8382fc881781da9eb64b913650c8bb856d1f97c64cdCédric Beust        // run the last invocation
839d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust        else if (tm.getInvocationCount() > 1) {
840d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust          isLast = current == tm.getInvocationCount();
841d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust        }
842d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust        if (! cm.isLastTimeOnly() || (cm.isLastTimeOnly() && isLast)) {
84345a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust          result.add(m);
84445a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust        }
84545a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      }
84645a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust    }
84745a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust
84845a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust    return result.toArray(new ITestNGMethod[result.size()]);
84945a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust  }
85045a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust
85145a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust  /**
85289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin   * {@link #invokeTestMethods()} eventually converge here to invoke a single @Test method.
853f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * <p/>
854f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * This method is responsible for actually invoking the method. It decides if the invocation
855f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * must be done:
856f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * <ul>
85789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin   * <li>through an <code>IHookable</code></li>
858f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * <li>directly (through reflection)</li>
859f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * <li>in a separate thread (in case it needs to timeout)
860f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * </ul>
86189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin   *
862f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * <p/>
863f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * This method is also reponsible for invoking @BeforeGroup, @BeforeMethod, @AfterMethod, @AfterGroup
864f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * if it is the case for the passed in @Test method.
865f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
86621dad3370294d6595fdddc3faf55792f60a913f1nullin  protected List<ITestResult> invokeTestMethod(Object[] instances,
867f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             final ITestNGMethod tm,
868f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             Object[] parameterValues,
869927a6d8a655520943e3a8a9ea9f09cbfe56f2ae6Cédric Beust                                             int parametersIndex,
870f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             XmlSuite suite,
871f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             Map<String, String> params,
872f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             ITestClass testClass,
873f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             ITestNGMethod[] beforeMethods,
874f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             ITestNGMethod[] afterMethods,
875f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             ConfigurationGroupMethods groupMethods)
876f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
877ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust    List<ITestResult> results = Lists.newArrayList();
878f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
879f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Mark this method with the current thread id
880f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    tm.setId(ThreadUtil.currentThreadInfo());
881f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
882f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for(int i= 0; i < instances.length; i++) {
883927a6d8a655520943e3a8a9ea9f09cbfe56f2ae6Cédric Beust      results.add(invokeMethod(instances, i, tm, parameterValues, parametersIndex, suite, params,
88494efdf8e6ac7332eadf8bfe5d1fe699caee5d051Cédric Beust          testClass, beforeMethods, afterMethods, groupMethods));
885f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
886f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
887f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return results;
888f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
889f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
890f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
891f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * Filter all the beforeGroups methods and invoke only those that apply
892f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * to the current test method
893f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
89489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin  private void invokeBeforeGroupsConfigurations(ITestClass testClass,
89589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                ITestNGMethod currentTestMethod,
89689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                ConfigurationGroupMethods groupMethods,
89789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                XmlSuite suite,
89889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                Map<String, String> params,
89989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                Object instance)
900f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
901f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    synchronized(groupMethods) {
902ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust      List<ITestNGMethod> filteredMethods = Lists.newArrayList();
903f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      String[] groups = currentTestMethod.getGroups();
904f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Map<String, List<ITestNGMethod>> beforeGroupMap = groupMethods.getBeforeGroupsMap();
90589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
906f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for (String group : groups) {
907f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        List<ITestNGMethod> methods = beforeGroupMap.get(group);
908f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if (methods != null) {
909f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          filteredMethods.addAll(methods);
910f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
911f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
91289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
913f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      ITestNGMethod[] beforeMethodsArray = filteredMethods.toArray(new ITestNGMethod[filteredMethods.size()]);
914f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
915f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // Invoke the right groups methods
916f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
917f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if(beforeMethodsArray.length > 0) {
918f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // don't pass the IClass or the instance as the method may be external
919f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // the invocation must be similar to @BeforeTest/@BeforeSuite
92089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin        invokeConfigurations(null, beforeMethodsArray, suite, params,
921facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust            null, /* no parameter values */
922facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust            null);
923f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
92489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
925f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
926f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // Remove them so they don't get run again
927f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
928f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      groupMethods.removeBeforeGroups(groups);
929f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
930f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
931f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
93289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin  private void invokeAfterGroupsConfigurations(ITestClass testClass,
933f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                               ITestNGMethod currentTestMethod,
934f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                               ConfigurationGroupMethods groupMethods,
93589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                               XmlSuite suite,
93689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                               Map<String, String> params,
93789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                               Object instance)
938f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
939f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Skip this if the current method doesn't belong to any group
940f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // (only a method that belongs to a group can trigger the invocation
941f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // of afterGroups methods)
9420f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin    if (currentTestMethod.getGroups().length == 0) {
9430f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      return;
9440f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin    }
94589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
946f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // See if the currentMethod is the last method in any of the groups
947f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // it belongs to
9480f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beust    Map<String, String> filteredGroups = Maps.newHashMap();
949f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    String[] groups = currentTestMethod.getGroups();
950f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    synchronized(groupMethods) {
951f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for (String group : groups) {
952f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if (groupMethods.isLastMethodForGroup(group, currentTestMethod)) {
953f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          filteredGroups.put(group, group);
954f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
955f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
95689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
9570f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      if(filteredGroups.isEmpty()) {
9580f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        return;
9590f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      }
96089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
961f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // The list of afterMethods to run
9620f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beust      Map<ITestNGMethod, ITestNGMethod> afterMethods = Maps.newHashMap();
96389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
964f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // Now filteredGroups contains all the groups for which we need to run the afterGroups
965f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // method.  Find all the methods that correspond to these groups and invoke them.
966f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Map<String, List<ITestNGMethod>> map = groupMethods.getAfterGroupsMap();
967f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for (String g : filteredGroups.values()) {
968f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        List<ITestNGMethod> methods = map.get(g);
969f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // Note:  should put them in a map if we want to make sure the same afterGroups
970f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // doesn't get run twice
971f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if (methods != null) {
972f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          for (ITestNGMethod m : methods) {
973f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            afterMethods.put(m, m);
974f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
975f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
976f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
97789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
978f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // Got our afterMethods, invoke them
979f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      ITestNGMethod[] afterMethodsArray = afterMethods.keySet().toArray(new ITestNGMethod[afterMethods.size()]);
980f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // don't pass the IClass or the instance as the method may be external
981f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // the invocation must be similar to @BeforeTest/@BeforeSuite
98289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      invokeConfigurations(null, afterMethodsArray, suite, params,
983facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust          null, /* no parameter values */
984facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust          null);
985f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
986f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // Remove the groups so they don't get run again
98789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      groupMethods.removeAfterGroups(filteredGroups.keySet());
988f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
989f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
990f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
991f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private Object[] getParametersFromIndex(Iterator<Object[]> parametersValues, int index) {
992f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    while (parametersValues.hasNext()) {
993f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Object[] parameters = parametersValues.next();
994f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
995f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if (index == 0) {
996f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        return parameters;
997f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
998f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      index--;
999f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1000f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return null;
1001f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
100289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1003c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust  int retryFailed(Object[] instances,
1004f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           int instanceIndex,
1005f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           final ITestNGMethod tm,
1006f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           XmlSuite suite,
1007f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           ITestClass testClass,
1008f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           ITestNGMethod[] beforeMethods,
1009f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           ITestNGMethod[] afterMethods,
1010f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           ConfigurationGroupMethods groupMethods,
1011f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           List<ITestResult> result,
1012f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           int failureCount,
1013bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust                           ExpectedExceptionsHolder expectedExceptionHolder,
1014f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           ITestContext testContext,
1015f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           Map<String, String> parameters,
1016f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           int parametersIndex) {
101792206009b23ecbbf29e5a0d20f6b095a552afcb8Cédric Beust    List<Object> failedInstances;
1018f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
101992206009b23ecbbf29e5a0d20f6b095a552afcb8Cédric Beust    do {
1020ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust      failedInstances = Lists.newArrayList();
10210f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beust      Map<String, String> allParameters = Maps.newHashMap();
1022f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      /**
1023f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust       * TODO: This recreates all the parameters every time when we only need
1024f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust       * one specific set. Should optimize it by only recreating the set needed.
1025f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust       */
1026db04b1679d3367e54e61d7e6f8c225354e90081cCédric Beust      ParameterBag bag = createParameters(tm, parameters,
1027da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust          allParameters, null, suite, testContext, null /* fedInstance */, null /* testResult */);
1028c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust      Object[] parameterValues =
1029c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust          getParametersFromIndex(bag.parameterHolder.parameters, parametersIndex);
1030f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
103189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      result.add(invokeMethod(instances, instanceIndex, tm, parameterValues,parametersIndex, suite,
103294efdf8e6ac7332eadf8bfe5d1fe699caee5d051Cédric Beust          allParameters, testClass, beforeMethods, afterMethods, groupMethods));
1033f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      failureCount = handleInvocationResults(tm, result, failedInstances,
1034bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust          failureCount, expectedExceptionHolder, true, true /* collect results */);
1035f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1036f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    while (!failedInstances.isEmpty());
1037f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return failureCount;
1038f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
103989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1040db04b1679d3367e54e61d7e6f8c225354e90081cCédric Beust  private ParameterBag createParameters(ITestNGMethod testMethod,
1041f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                        Map<String, String> parameters,
1042f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                        Map<String, String> allParameterNames,
1043facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust                                        Object[] parameterValues,
1044f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                        XmlSuite suite,
10458b9443a6ada20a1e9f3852b715f3e789a0f8d490Cédric Beust                                        ITestContext testContext,
1046da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust                                        Object fedInstance,
1047da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust                                        ITestResult testResult)
10488778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust  {
10498778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust    Object instance;
10508778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust    if (fedInstance != null) {
10518778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust      instance = fedInstance;
10528778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust    }
10538778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust    else {
10547955b9d255852b83f9c96277dece4d6807cb69f5Cédric Beust      instance = testMethod.getInstance();
10558778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust    }
105689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
105789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin    ParameterBag bag= handleParameters(testMethod,
1058da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust        instance, allParameterNames, parameters, parameterValues, suite, testContext, fedInstance,
1059da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust        testResult);
1060f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1061f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return bag;
1062f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
106389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1064f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1065eddb4a9423c14fee808a30e92ad77a16e88b320enullin   * Invoke all the test methods. Note the plural: the method passed in
1066f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * parameter might be invoked several times if the test class it belongs
1067f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * to has more than one instance (i.e., if an @Factory method has been
1068f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * declared somewhere that returns several instances of this TestClass).
1069f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * If no @Factory method was specified, testMethod will only be invoked
1070f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * once.
1071f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * <p/>
1072f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * Note that this method also takes care of invoking the beforeTestMethod
1073f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * and afterTestMethod, if any.
107489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin   *
107589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin   * Note (alex): this method can be refactored to use a SingleTestMethodWorker that
107689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin   * directly invokes
1077f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * {@link #invokeTestMethod(Object[], ITestNGMethod, Object[], XmlSuite, Map, ITestClass, ITestNGMethod[], ITestNGMethod[], ConfigurationGroupMethods)}
1078f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * and this would simplify the implementation (see how DataTestMethodWorker is used)
1079f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
1080423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust  @Override
1081f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  public List<ITestResult> invokeTestMethods(ITestNGMethod testMethod,
1082f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             ITestNGMethod[] allTestMethods,
1083f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             int testMethodIndex,
1084f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             XmlSuite suite,
1085f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             Map<String, String> parameters,
1086f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             ConfigurationGroupMethods groupMethods,
1087f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             Object[] instances,
1088f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             ITestContext testContext)
1089f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
1090f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Potential bug here if the test method was declared on a parent class
109189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin    assert null != testMethod.getTestClass()
1092f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    : "COULDN'T FIND TESTCLASS FOR " + testMethod.getMethod().getDeclaringClass();
109389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1094ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust    List<ITestResult> result = Lists.newArrayList();
109589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1096eddb4a9423c14fee808a30e92ad77a16e88b320enullin    if (!MethodHelper.isEnabled(testMethod.getMethod(), m_annotationFinder)) {
1097eddb4a9423c14fee808a30e92ad77a16e88b320enullin      /*
1098eddb4a9423c14fee808a30e92ad77a16e88b320enullin       * return if the method is not enabled. No need to do any more calculations
1099eddb4a9423c14fee808a30e92ad77a16e88b320enullin       */
1100eddb4a9423c14fee808a30e92ad77a16e88b320enullin      return result;
1101eddb4a9423c14fee808a30e92ad77a16e88b320enullin    }
1102eddb4a9423c14fee808a30e92ad77a16e88b320enullin
1103f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    ITestClass testClass= testMethod.getTestClass();
11040b2ac5eab08098da2c2b63d4a3f87ba72ad5d6a1nullin    long start = System.currentTimeMillis();
1105f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
11069150cdf3bacb4715cee345cd153d4f0ab3dbd198nullin    // For invocationCount > 1 and threadPoolSize > 1 the method will be invoked on a thread pool
1107331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust    long timeOutInvocationCount = testMethod.getInvocationTimeOut();
1108eddb4a9423c14fee808a30e92ad77a16e88b320enullin    //FIXME: Is this correct?
1109331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust    boolean onlyOne = testMethod.getThreadPoolSize() > 1 ||
1110331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust      timeOutInvocationCount > 0;
111189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1112331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust    int invocationCount = onlyOne ? 1 : testMethod.getInvocationCount();
1113f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    int failureCount = 0;
1114f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
111589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin    ExpectedExceptionsHolder expectedExceptionHolder =
1116f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        MethodHelper.findExpectedExceptions(m_annotationFinder, testMethod.getMethod());
1117f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    while(invocationCount-- > 0) {
1118e934f66fb4fb247ebf5fec45770bc6820fbba29anullin      boolean okToProceed = checkDependencies(testMethod, allTestMethods);
1119f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1120eddb4a9423c14fee808a30e92ad77a16e88b320enullin      if (!okToProceed) {
1121f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        //
1122eddb4a9423c14fee808a30e92ad77a16e88b320enullin        // Not okToProceed. Test is being skipped
1123f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        //
1124eddb4a9423c14fee808a30e92ad77a16e88b320enullin        ITestResult testResult = new TestResult(testClass, null /* instance */,
1125f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                               testMethod,
1126eddb4a9423c14fee808a30e92ad77a16e88b320enullin                                               null /* cause */,
1127f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                               start,
1128f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                               System.currentTimeMillis());
1129f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        String missingGroup = testMethod.getMissingGroup();
1130f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if (missingGroup != null) {
113189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin          testResult.setThrowable(new Throwable("Method " + testMethod
1132f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              + " depends on nonexistent group \"" + missingGroup + "\""));
1133f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1134f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1135f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        testResult.setStatus(ITestResult.SKIP);
1136a4e6892fbfa21c968737eaf4e4f1e4b0b7f9163eCédric Beust        result.add(testResult);
1137676b37b4af4a4eeeb0d858f0ff577c0a1d549b83Cédric Beust        m_notifier.addSkippedTest(testMethod, testResult);
1138f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        runTestListeners(testResult);
1139eddb4a9423c14fee808a30e92ad77a16e88b320enullin        return result;
1140eddb4a9423c14fee808a30e92ad77a16e88b320enullin      }
1141eddb4a9423c14fee808a30e92ad77a16e88b320enullin
1142eddb4a9423c14fee808a30e92ad77a16e88b320enullin      //
1143eddb4a9423c14fee808a30e92ad77a16e88b320enullin      // If threadPoolSize specified, run this method in its own pool thread.
1144eddb4a9423c14fee808a30e92ad77a16e88b320enullin      //
1145eddb4a9423c14fee808a30e92ad77a16e88b320enullin      if (testMethod.getThreadPoolSize() > 1 && testMethod.getInvocationCount() > 1) {
1146eddb4a9423c14fee808a30e92ad77a16e88b320enullin          return invokePooledTestMethods(testMethod, allTestMethods, suite,
1147eddb4a9423c14fee808a30e92ad77a16e88b320enullin              parameters, groupMethods, testContext);
1148eddb4a9423c14fee808a30e92ad77a16e88b320enullin      }
1149eddb4a9423c14fee808a30e92ad77a16e88b320enullin      //
1150eddb4a9423c14fee808a30e92ad77a16e88b320enullin      // No threads, regular invocation
1151eddb4a9423c14fee808a30e92ad77a16e88b320enullin      //
1152eddb4a9423c14fee808a30e92ad77a16e88b320enullin      else {
11539d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust        ITestNGMethod[] beforeMethods = filterMethods(testClass, testClass.getBeforeTestMethods(),
11549d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust            CAN_RUN_FROM_CLASS);
11559d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust        ITestNGMethod[] afterMethods = filterMethods(testClass, testClass.getAfterTestMethods(),
11569d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust            CAN_RUN_FROM_CLASS);
1157eddb4a9423c14fee808a30e92ad77a16e88b320enullin
1158eddb4a9423c14fee808a30e92ad77a16e88b320enullin        Map<String, String> allParameterNames = Maps.newHashMap();
1159db04b1679d3367e54e61d7e6f8c225354e90081cCédric Beust        ParameterBag bag = createParameters(testMethod,
1160eddb4a9423c14fee808a30e92ad77a16e88b320enullin            parameters, allParameterNames, null, suite, testContext, instances[0],
1161eddb4a9423c14fee808a30e92ad77a16e88b320enullin            null);
1162eddb4a9423c14fee808a30e92ad77a16e88b320enullin
1163eddb4a9423c14fee808a30e92ad77a16e88b320enullin        if (bag.hasErrors()) {
1164eddb4a9423c14fee808a30e92ad77a16e88b320enullin          failureCount = handleInvocationResults(testMethod,
1165eddb4a9423c14fee808a30e92ad77a16e88b320enullin              bag.errorResults, null, failureCount, expectedExceptionHolder, true,
1166eddb4a9423c14fee808a30e92ad77a16e88b320enullin              true /* collect results */);
1167fe08327fabe1654f4f509edcf28c3296ad054fc5Cédric Beust          ITestResult tr = registerSkippedTestResult(testMethod, instances[0], start,
1168fe08327fabe1654f4f509edcf28c3296ad054fc5Cédric Beust              bag.errorResults.get(0).getThrowable());
1169061a9ae01a09d45e337c69b64d1b5a81ebee3868Cédric Beust          result.add(tr);
1170eddb4a9423c14fee808a30e92ad77a16e88b320enullin          continue;
1171eddb4a9423c14fee808a30e92ad77a16e88b320enullin        }
1172eddb4a9423c14fee808a30e92ad77a16e88b320enullin
1173eddb4a9423c14fee808a30e92ad77a16e88b320enullin        Iterator<Object[]> allParameterValues = bag.parameterHolder.parameters;
1174eddb4a9423c14fee808a30e92ad77a16e88b320enullin        int parametersIndex = 0;
1175eddb4a9423c14fee808a30e92ad77a16e88b320enullin
1176eddb4a9423c14fee808a30e92ad77a16e88b320enullin        try {
1177eddb4a9423c14fee808a30e92ad77a16e88b320enullin          List<TestMethodWithDataProviderMethodWorker> workers = Lists.newArrayList();
1178eddb4a9423c14fee808a30e92ad77a16e88b320enullin
1179eddb4a9423c14fee808a30e92ad77a16e88b320enullin          if (bag.parameterHolder.origin == ParameterOrigin.ORIGIN_DATA_PROVIDER &&
1180eddb4a9423c14fee808a30e92ad77a16e88b320enullin              bag.parameterHolder.dataProviderHolder.annotation.isParallel()) {
1181eddb4a9423c14fee808a30e92ad77a16e88b320enullin            while (allParameterValues.hasNext()) {
1182eddb4a9423c14fee808a30e92ad77a16e88b320enullin              Object[] parameterValues = injectParameters(allParameterValues.next(),
1183eddb4a9423c14fee808a30e92ad77a16e88b320enullin                  testMethod.getMethod(), testContext, null /* test result */);
1184eddb4a9423c14fee808a30e92ad77a16e88b320enullin              TestMethodWithDataProviderMethodWorker w =
1185eddb4a9423c14fee808a30e92ad77a16e88b320enullin                new TestMethodWithDataProviderMethodWorker(this,
1186eddb4a9423c14fee808a30e92ad77a16e88b320enullin                    testMethod, parametersIndex,
1187eddb4a9423c14fee808a30e92ad77a16e88b320enullin                    parameterValues, instances, suite, parameters, testClass,
1188eddb4a9423c14fee808a30e92ad77a16e88b320enullin                    beforeMethods, afterMethods, groupMethods,
1189eddb4a9423c14fee808a30e92ad77a16e88b320enullin                    expectedExceptionHolder, testContext, m_skipFailedInvocationCounts,
1190eddb4a9423c14fee808a30e92ad77a16e88b320enullin                    invocationCount, failureCount, m_notifier);
1191eddb4a9423c14fee808a30e92ad77a16e88b320enullin              workers.add(w);
1192eddb4a9423c14fee808a30e92ad77a16e88b320enullin              // testng387: increment the param index in the bag.
1193eddb4a9423c14fee808a30e92ad77a16e88b320enullin              parametersIndex++;
1194eddb4a9423c14fee808a30e92ad77a16e88b320enullin            }
1195eddb4a9423c14fee808a30e92ad77a16e88b320enullin            PoolService ps = PoolService.getInstance();
1196eddb4a9423c14fee808a30e92ad77a16e88b320enullin            List<ITestResult> r = ps.submitTasksAndWait(testMethod, workers);
1197eddb4a9423c14fee808a30e92ad77a16e88b320enullin            result.addAll(r);
1198eddb4a9423c14fee808a30e92ad77a16e88b320enullin
1199eddb4a9423c14fee808a30e92ad77a16e88b320enullin          } else {
1200eddb4a9423c14fee808a30e92ad77a16e88b320enullin            while (allParameterValues.hasNext()) {
1201eddb4a9423c14fee808a30e92ad77a16e88b320enullin              Object[] parameterValues = injectParameters(allParameterValues.next(),
1202eddb4a9423c14fee808a30e92ad77a16e88b320enullin                  testMethod.getMethod(), testContext, null /* test result */);
1203eddb4a9423c14fee808a30e92ad77a16e88b320enullin
1204eddb4a9423c14fee808a30e92ad77a16e88b320enullin              List<ITestResult> tmpResults = Lists.newArrayList();
1205eddb4a9423c14fee808a30e92ad77a16e88b320enullin
1206eddb4a9423c14fee808a30e92ad77a16e88b320enullin              try {
1207eddb4a9423c14fee808a30e92ad77a16e88b320enullin                tmpResults.addAll(invokeTestMethod(instances,
1208eddb4a9423c14fee808a30e92ad77a16e88b320enullin                                                   testMethod,
1209eddb4a9423c14fee808a30e92ad77a16e88b320enullin                                                   parameterValues,
1210eddb4a9423c14fee808a30e92ad77a16e88b320enullin                                                   parametersIndex,
1211eddb4a9423c14fee808a30e92ad77a16e88b320enullin                                                   suite,
1212eddb4a9423c14fee808a30e92ad77a16e88b320enullin                                                   parameters,
1213eddb4a9423c14fee808a30e92ad77a16e88b320enullin                                                   testClass,
1214eddb4a9423c14fee808a30e92ad77a16e88b320enullin                                                   beforeMethods,
1215eddb4a9423c14fee808a30e92ad77a16e88b320enullin                                                   afterMethods,
1216eddb4a9423c14fee808a30e92ad77a16e88b320enullin                                                   groupMethods));
1217eddb4a9423c14fee808a30e92ad77a16e88b320enullin              }
1218eddb4a9423c14fee808a30e92ad77a16e88b320enullin              finally {
1219eddb4a9423c14fee808a30e92ad77a16e88b320enullin                List<Object> failedInstances = Lists.newArrayList();
1220eddb4a9423c14fee808a30e92ad77a16e88b320enullin
1221eddb4a9423c14fee808a30e92ad77a16e88b320enullin                failureCount = handleInvocationResults(testMethod, tmpResults,
1222eddb4a9423c14fee808a30e92ad77a16e88b320enullin                    failedInstances, failureCount, expectedExceptionHolder, true,
1223eddb4a9423c14fee808a30e92ad77a16e88b320enullin                    false /* don't collect results */);
1224eddb4a9423c14fee808a30e92ad77a16e88b320enullin                if (failedInstances.isEmpty()) {
1225eddb4a9423c14fee808a30e92ad77a16e88b320enullin                  result.addAll(tmpResults);
1226eddb4a9423c14fee808a30e92ad77a16e88b320enullin                } else {
1227eddb4a9423c14fee808a30e92ad77a16e88b320enullin                  for (int i = 0; i < failedInstances.size(); i++) {
1228eddb4a9423c14fee808a30e92ad77a16e88b320enullin                    List<ITestResult> retryResults = Lists.newArrayList();
1229eddb4a9423c14fee808a30e92ad77a16e88b320enullin
1230eddb4a9423c14fee808a30e92ad77a16e88b320enullin                    failureCount =
1231eddb4a9423c14fee808a30e92ad77a16e88b320enullin                     retryFailed(failedInstances.toArray(),
1232eddb4a9423c14fee808a30e92ad77a16e88b320enullin                     i, testMethod, suite, testClass, beforeMethods,
1233eddb4a9423c14fee808a30e92ad77a16e88b320enullin                     afterMethods, groupMethods, retryResults,
1234eddb4a9423c14fee808a30e92ad77a16e88b320enullin                     failureCount, expectedExceptionHolder,
1235eddb4a9423c14fee808a30e92ad77a16e88b320enullin                     testContext, parameters, parametersIndex);
1236eddb4a9423c14fee808a30e92ad77a16e88b320enullin                  result.addAll(retryResults);
1237eddb4a9423c14fee808a30e92ad77a16e88b320enullin                  }
1238eddb4a9423c14fee808a30e92ad77a16e88b320enullin                }
1239eddb4a9423c14fee808a30e92ad77a16e88b320enullin
1240eddb4a9423c14fee808a30e92ad77a16e88b320enullin                //
1241eddb4a9423c14fee808a30e92ad77a16e88b320enullin                // If we have a failure, skip all the
1242eddb4a9423c14fee808a30e92ad77a16e88b320enullin                // other invocationCounts
1243eddb4a9423c14fee808a30e92ad77a16e88b320enullin                //
1244eddb4a9423c14fee808a30e92ad77a16e88b320enullin                if (failureCount > 0
1245eddb4a9423c14fee808a30e92ad77a16e88b320enullin                      && (m_skipFailedInvocationCounts
1246eddb4a9423c14fee808a30e92ad77a16e88b320enullin                            || testMethod.skipFailedInvocations())) {
1247eddb4a9423c14fee808a30e92ad77a16e88b320enullin                  while (invocationCount-- > 0) {
1248fe08327fabe1654f4f509edcf28c3296ad054fc5Cédric Beust                    result.add(registerSkippedTestResult(testMethod, instances[0], start, null));
1249eddb4a9423c14fee808a30e92ad77a16e88b320enullin                  }
1250eddb4a9423c14fee808a30e92ad77a16e88b320enullin                  break;
1251eddb4a9423c14fee808a30e92ad77a16e88b320enullin                }
1252eddb4a9423c14fee808a30e92ad77a16e88b320enullin              }// end finally
1253eddb4a9423c14fee808a30e92ad77a16e88b320enullin              parametersIndex++;
1254eddb4a9423c14fee808a30e92ad77a16e88b320enullin            }
1255eddb4a9423c14fee808a30e92ad77a16e88b320enullin          }
1256eddb4a9423c14fee808a30e92ad77a16e88b320enullin        }
1257eddb4a9423c14fee808a30e92ad77a16e88b320enullin        catch (Throwable cause) {
1258eddb4a9423c14fee808a30e92ad77a16e88b320enullin          ITestResult r =
1259eddb4a9423c14fee808a30e92ad77a16e88b320enullin              new TestResult(testMethod.getTestClass(),
1260eddb4a9423c14fee808a30e92ad77a16e88b320enullin                instances[0],
1261eddb4a9423c14fee808a30e92ad77a16e88b320enullin                testMethod,
1262eddb4a9423c14fee808a30e92ad77a16e88b320enullin                cause,
1263eddb4a9423c14fee808a30e92ad77a16e88b320enullin                start,
1264eddb4a9423c14fee808a30e92ad77a16e88b320enullin                System.currentTimeMillis());
1265eddb4a9423c14fee808a30e92ad77a16e88b320enullin            r.setStatus(TestResult.FAILURE);
1266eddb4a9423c14fee808a30e92ad77a16e88b320enullin            result.add(r);
1267eddb4a9423c14fee808a30e92ad77a16e88b320enullin            runTestListeners(r);
1268eddb4a9423c14fee808a30e92ad77a16e88b320enullin            m_notifier.addFailedTest(testMethod, r);
1269eddb4a9423c14fee808a30e92ad77a16e88b320enullin        } // catch
1270f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1271f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
127289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1273f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return result;
127489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1275f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  } // invokeTestMethod
1276f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1277252c45802df7624a4fafbce810e05d22048f437bCédric Beust  private ITestResult registerSkippedTestResult(ITestNGMethod testMethod, Object instance,
1278fe08327fabe1654f4f509edcf28c3296ad054fc5Cédric Beust      long start, Throwable throwable) {
127989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin    ITestResult result =
1280252c45802df7624a4fafbce810e05d22048f437bCédric Beust      new TestResult(testMethod.getTestClass(),
1281252c45802df7624a4fafbce810e05d22048f437bCédric Beust        instance,
1282252c45802df7624a4fafbce810e05d22048f437bCédric Beust        testMethod,
1283fe08327fabe1654f4f509edcf28c3296ad054fc5Cédric Beust        throwable,
1284252c45802df7624a4fafbce810e05d22048f437bCédric Beust        start,
1285252c45802df7624a4fafbce810e05d22048f437bCédric Beust        System.currentTimeMillis());
1286252c45802df7624a4fafbce810e05d22048f437bCédric Beust    result.setStatus(TestResult.SKIP);
1287252c45802df7624a4fafbce810e05d22048f437bCédric Beust    runTestListeners(result);
1288252c45802df7624a4fafbce810e05d22048f437bCédric Beust
1289252c45802df7624a4fafbce810e05d22048f437bCédric Beust    return result;
1290252c45802df7624a4fafbce810e05d22048f437bCédric Beust  }
1291252c45802df7624a4fafbce810e05d22048f437bCédric Beust
129228e899a6c1620c8d07cb04a92f96658550e4af16nullin  /**
129328e899a6c1620c8d07cb04a92f96658550e4af16nullin   * Gets an array of parameter values returned by data provider or the ones that
129428e899a6c1620c8d07cb04a92f96658550e4af16nullin   * are injected based on parameter type. The method also checks for {@code NoInjection}
129528e899a6c1620c8d07cb04a92f96658550e4af16nullin   * annotation
129628e899a6c1620c8d07cb04a92f96658550e4af16nullin   * @param parameterValues parameter values from a data provider
129728e899a6c1620c8d07cb04a92f96658550e4af16nullin   * @param method method to be invoked
129828e899a6c1620c8d07cb04a92f96658550e4af16nullin   * @param context test context
129928e899a6c1620c8d07cb04a92f96658550e4af16nullin   * @param testResult test result
130028e899a6c1620c8d07cb04a92f96658550e4af16nullin   * @return
130128e899a6c1620c8d07cb04a92f96658550e4af16nullin   */
13021e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust  private Object[] injectParameters(Object[] parameterValues, Method method,
130328e899a6c1620c8d07cb04a92f96658550e4af16nullin      ITestContext context, ITestResult testResult)
130428e899a6c1620c8d07cb04a92f96658550e4af16nullin    throws TestNGException {
13051e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust    List<Object> vResult = Lists.newArrayList();
13061e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust    int i = 0;
130728e899a6c1620c8d07cb04a92f96658550e4af16nullin    int numValues = parameterValues.length;
130828e899a6c1620c8d07cb04a92f96658550e4af16nullin    int numParams = method.getParameterTypes().length;
130928e899a6c1620c8d07cb04a92f96658550e4af16nullin
13108211ccc6e66d114d50826b44f06b8e1d42f7811aCédric Beust    if (numValues > numParams && ! method.isVarArgs()) {
13118211ccc6e66d114d50826b44f06b8e1d42f7811aCédric Beust      throw new TestNGException("The data provider is trying to pass " + numValues
13128211ccc6e66d114d50826b44f06b8e1d42f7811aCédric Beust          + " parameters but the method "
13138211ccc6e66d114d50826b44f06b8e1d42f7811aCédric Beust          + method.getDeclaringClass().getName() + "#" + method.getName()
13148211ccc6e66d114d50826b44f06b8e1d42f7811aCédric Beust          + " takes " + numParams);
131528e899a6c1620c8d07cb04a92f96658550e4af16nullin    }
131628e899a6c1620c8d07cb04a92f96658550e4af16nullin
131728e899a6c1620c8d07cb04a92f96658550e4af16nullin    // beyond this, numValues <= numParams
13181e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust    for (Class<?> cls : method.getParameterTypes()) {
1319aba3ac2f9fc3e370339b911598f62c7ffb6752aaCédric Beust      Annotation[] annotations = method.getParameterAnnotations()[i];
1320aba3ac2f9fc3e370339b911598f62c7ffb6752aaCédric Beust      boolean noInjection = false;
1321aba3ac2f9fc3e370339b911598f62c7ffb6752aaCédric Beust      for (Annotation a : annotations) {
1322aba3ac2f9fc3e370339b911598f62c7ffb6752aaCédric Beust        if (a instanceof NoInjection) {
1323aba3ac2f9fc3e370339b911598f62c7ffb6752aaCédric Beust          noInjection = true;
1324aba3ac2f9fc3e370339b911598f62c7ffb6752aaCédric Beust          break;
1325aba3ac2f9fc3e370339b911598f62c7ffb6752aaCédric Beust        }
1326aba3ac2f9fc3e370339b911598f62c7ffb6752aaCédric Beust      }
13271e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust      Object injected = Parameters.getInjectedParameter(cls, method, context, testResult);
1328aba3ac2f9fc3e370339b911598f62c7ffb6752aaCédric Beust      if (injected != null && ! noInjection) {
13291e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust        vResult.add(injected);
13301e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust      } else {
133128e899a6c1620c8d07cb04a92f96658550e4af16nullin        try {
1332e7405399f36ed7b9383424f5175980fe2698a403Cédric Beust          if (method.isVarArgs()) vResult.add(parameterValues);
1333e7405399f36ed7b9383424f5175980fe2698a403Cédric Beust          else vResult.add(parameterValues[i++]);
133428e899a6c1620c8d07cb04a92f96658550e4af16nullin        } catch (ArrayIndexOutOfBoundsException ex) {
13358211ccc6e66d114d50826b44f06b8e1d42f7811aCédric Beust          throw new TestNGException("The data provider is trying to pass " + numValues
13368211ccc6e66d114d50826b44f06b8e1d42f7811aCédric Beust              + " parameters but the method "
13378211ccc6e66d114d50826b44f06b8e1d42f7811aCédric Beust              + method.getDeclaringClass().getName() + "#" + method.getName()
13388211ccc6e66d114d50826b44f06b8e1d42f7811aCédric Beust              + " takes " + numParams
13398211ccc6e66d114d50826b44f06b8e1d42f7811aCédric Beust              + " and TestNG is unable in inject a suitable object", ex);
134028e899a6c1620c8d07cb04a92f96658550e4af16nullin        }
13411e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust      }
13421e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust    }
13431e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust    return vResult.toArray(new Object[vResult.size()]);
13441e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust  }
13451e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust
1346f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private ParameterBag handleParameters(ITestNGMethod testMethod,
1347f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Object instance,
1348f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Map<String, String> allParameterNames,
1349f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Map<String, String> parameters,
1350facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust      Object[] parameterValues,
1351f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      XmlSuite suite,
13528b9443a6ada20a1e9f3852b715f3e789a0f8d490Cédric Beust      ITestContext testContext,
1353da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust      Object fedInstance,
1354da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust      ITestResult testResult)
1355f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
1356f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    try {
1357c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust      return new ParameterBag(
1358c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust          Parameters.handleParameters(testMethod,
135989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin            allParameterNames,
136089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin            instance,
1361c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust            new Parameters.MethodParameters(parameters, parameterValues,
136289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                testMethod.getMethod(), testContext, testResult),
136389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin            suite,
1364c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust            m_annotationFinder,
136589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin            fedInstance),
1366eddb4a9423c14fee808a30e92ad77a16e88b320enullin          null /* TestResult */);
1367f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1368061a9ae01a09d45e337c69b64d1b5a81ebee3868Cédric Beust//    catch(TestNGException ex) {
1369061a9ae01a09d45e337c69b64d1b5a81ebee3868Cédric Beust//      throw ex;
1370061a9ae01a09d45e337c69b64d1b5a81ebee3868Cédric Beust//    }
1371f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    catch(Throwable cause) {
1372eddb4a9423c14fee808a30e92ad77a16e88b320enullin      return new ParameterBag(null /* ParameterHolder */,
1373f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          new TestResult(
137489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin              testMethod.getTestClass(),
137589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin              instance,
137689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin              testMethod,
137789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin              cause,
1378f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              System.currentTimeMillis(),
1379f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              System.currentTimeMillis()));
1380f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1381f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
138289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1383f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
138489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin   * Invokes a method that has a specified threadPoolSize.
1385f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
138689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin  private List<ITestResult> invokePooledTestMethods(ITestNGMethod testMethod,
138789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                    ITestNGMethod[] allTestMethods,
138889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                    XmlSuite suite,
138989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                    Map<String, String> parameters,
1390f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                                    ConfigurationGroupMethods groupMethods,
139189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                    ITestContext testContext)
1392f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
1393f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
1394f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Create the workers
1395f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
1396f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin    List<IWorker<ITestNGMethod>> workers = Lists.newArrayList();
139789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
13989d65d102f64e4fe2e629de8e87c8b92379a9349eCédric Beust    // Create one worker per invocationCount
1399f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for (int i = 0; i < testMethod.getInvocationCount(); i++) {
1400f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // we use clones for reporting purposes
1401f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      ITestNGMethod clonedMethod= testMethod.clone();
1402f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      clonedMethod.setInvocationCount(1);
1403f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      clonedMethod.setThreadPoolSize(1);
1404f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1405eb2b9ac857aad415986677a51513d47e91eb7c8dCédric Beust      MethodInstance mi = new MethodInstance(clonedMethod);
1406f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      workers.add(new SingleTestMethodWorker(this,
1407f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          mi,
140889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin          suite,
1409f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          parameters,
1410f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          allTestMethods,
1411f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          testContext));
1412f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1413f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1414f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return runWorkers(testMethod, workers, testMethod.getThreadPoolSize(), groupMethods, suite, parameters);
1415f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
141689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1417f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1418f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param testMethod
1419f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param result
1420f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param failureCount
1421bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust   * @param expectedExceptionsHolder
1422f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return
1423f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
142489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin  int handleInvocationResults(ITestNGMethod testMethod,
1425f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                      List<ITestResult> result,
1426f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                      List<Object> failedInstances,
142789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                      int failureCount,
1428bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust                                      ExpectedExceptionsHolder expectedExceptionsHolder,
14296216d78ae0757b7d57aa6e94cc041447d610724dCédric Beust                                      boolean triggerListeners,
14306216d78ae0757b7d57aa6e94cc041447d610724dCédric Beust                                      boolean collectResults)
14316216d78ae0757b7d57aa6e94cc041447d610724dCédric Beust  {
1432f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
1433f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Go through all the results and create a TestResult for each of them
1434f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
1435ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust    List<ITestResult> resultsToRetry = Lists.newArrayList();
1436f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1437f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for (int i = 0; i < result.size(); i++) {
1438f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      ITestResult testResult = result.get(i);
1439f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Throwable ite= testResult.getThrowable();
1440f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      int status= testResult.getStatus();
1441f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1442f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // Exception thrown?
14434c02d89d66fe0319dd20083e705addd6b5f3e8cdCédric Beust      if (ite != null) {
1444f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1445f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        //  Invocation caused an exception, see if the method was annotated with @ExpectedException
1446bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust        if (isExpectedException(ite, expectedExceptionsHolder)) {
1447bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust          if (messageRegExpMatches(expectedExceptionsHolder.messageRegExp, ite)) {
1448bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust            testResult.setStatus(ITestResult.SUCCESS);
1449bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust            status= ITestResult.SUCCESS;
1450bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust          }
1451bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust          else {
1452bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust            testResult.setThrowable(
1453bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust                new TestException("The exception was thrown with the wrong message:" +
145489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                    " expected \"" + expectedExceptionsHolder.messageRegExp + "\"" +
1455fa37eadd5874782d0020b1df413489b0514888b5Cédric Beust                    " but got \"" + ite.getMessage() + "\"", ite));
1456bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust            status= ITestResult.FAILURE;
1457bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust          }
14584c02d89d66fe0319dd20083e705addd6b5f3e8cdCédric Beust        } else if (ite != null && expectedExceptionsHolder != null) {
14594c02d89d66fe0319dd20083e705addd6b5f3e8cdCédric Beust          testResult.setThrowable(
14604c02d89d66fe0319dd20083e705addd6b5f3e8cdCédric Beust              new TestException("Expected exception "
14614c02d89d66fe0319dd20083e705addd6b5f3e8cdCédric Beust                 + expectedExceptionsHolder.expectedClasses[0].getName()
1462fa37eadd5874782d0020b1df413489b0514888b5Cédric Beust                 + " but got " + ite, ite));
14634c02d89d66fe0319dd20083e705addd6b5f3e8cdCédric Beust          status= ITestResult.FAILURE;
1464f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1465f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        else if (SkipException.class.isAssignableFrom(ite.getClass())){
1466f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          SkipException skipEx= (SkipException) ite;
1467f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          if(skipEx.isSkip()) {
14684c02d89d66fe0319dd20083e705addd6b5f3e8cdCédric Beust            status = ITestResult.SKIP;
1469f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
1470f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          else {
1471f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            handleException(ite, testMethod, testResult, failureCount++);
14724c02d89d66fe0319dd20083e705addd6b5f3e8cdCédric Beust            status = ITestResult.FAILURE;
1473f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
1474f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1475f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        else {
1476f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          handleException(ite, testMethod, testResult, failureCount++);
1477f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          status= testResult.getStatus();
1478f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1479f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1480f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1481f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // No exception thrown, make sure we weren't expecting one
1482bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust      else if(status != ITestResult.SKIP && expectedExceptionsHolder != null) {
1483bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust        Class<?>[] classes = expectedExceptionsHolder.expectedClasses;
1484bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust        if (classes != null && classes.length > 0) {
1485f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          testResult.setThrowable(
148627e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust              new TestException("Method " + testMethod + " should have thrown an exception of "
148727e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust                  + expectedExceptionsHolder.expectedClasses[0]));
1488f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          status= ITestResult.FAILURE;
1489f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1490f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1491f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1492f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      testResult.setStatus(status);
1493f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1494f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      boolean retry = false;
149589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1496f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if (testResult.getStatus() == ITestResult.FAILURE) {
1497f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        IRetryAnalyzer retryAnalyzer = testMethod.getRetryAnalyzer();
1498f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
14999ae4e70bde40b32777755f9294a5b1b06b420005Cédric Beust        if (retryAnalyzer != null && failedInstances != null) {
1500f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          retry = retryAnalyzer.retry(testResult);
1501f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1502f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1503f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if (retry) {
1504f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          resultsToRetry.add(testResult);
1505f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          if (failedInstances != null) {
15069ae4e70bde40b32777755f9294a5b1b06b420005Cédric Beust            failedInstances.add(testResult.getInstance());
1507f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
1508f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
150989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      }
151034ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust      if (collectResults) {
1511f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // Collect the results
1512f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if(ITestResult.SUCCESS == status) {
1513f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          m_notifier.addPassedTest(testMethod, testResult);
1514f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1515f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        else if(ITestResult.SKIP == status) {
1516f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          m_notifier.addSkippedTest(testMethod, testResult);
1517f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1518f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        else if(ITestResult.FAILURE == status) {
1519f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          m_notifier.addFailedTest(testMethod, testResult);
1520f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1521f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        else if(ITestResult.SUCCESS_PERCENTAGE_FAILURE == status) {
1522f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          m_notifier.addFailedButWithinSuccessPercentageTest(testMethod, testResult);
1523f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1524f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        else {
1525f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          assert false : "UNKNOWN STATUS:" + status;
1526f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
15277e735d9079026e11bc7cd06dab2b99d9ff9cd6c3Cédric Beust//        if (triggerListeners && status != ITestResult.SUCCESS) {
15287e735d9079026e11bc7cd06dab2b99d9ff9cd6c3Cédric Beust//          runTestListeners(testResult);
15297e735d9079026e11bc7cd06dab2b99d9ff9cd6c3Cédric Beust//        }
1530f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1531f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    } // for results
153289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1533f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return removeResultsToRetryFromResult(resultsToRetry, result, failureCount);
1534f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
153589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1536bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust  /**
1537bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust   *   message / regEx  .*      other
1538bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust   *   null             true    false
1539bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust   *   non-null         true    match
1540bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust   */
1541bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust  private boolean messageRegExpMatches(String messageRegExp, Throwable ite) {
1542bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust    if (".*".equals(messageRegExp)) {
1543bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust      return true;
1544bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust    } else {
15450f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      if (ite.getMessage() == null) {
15460f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        return false;
15470f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      } else {
15480f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        return Pattern.matches(messageRegExp, ite.getMessage());
15490f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      }
1550bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust    }
1551bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust  }
1552bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust
1553f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private int removeResultsToRetryFromResult(List<ITestResult> resultsToRetry,
1554f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      List<ITestResult> result, int failureCount) {
1555f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if (resultsToRetry != null) {
1556f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for (ITestResult res : resultsToRetry) {
1557f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        result.remove(res);
1558f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        failureCount--;
1559f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1560f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1561f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return failureCount;
1562f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
156389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1564f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1565f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * To reduce thread contention and also to correctly handle thread-confinement
1566f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * this method invokes the @BeforeGroups and @AfterGroups corresponding to the current @Test method.
1567f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
156889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin  private List<ITestResult> runWorkers(ITestNGMethod testMethod,
1569c4cadec5fb52419e211120aa93b6118a4ab756ecCédric Beust      List<IWorker<ITestNGMethod>> workers,
157089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      int threadPoolSize,
157189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      ConfigurationGroupMethods groupMethods,
157289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      XmlSuite suite,
1573f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Map<String, String> parameters)
1574f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
157589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin    // Invoke @BeforeGroups on the original method (reduce thread contention,
1576c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust    // and also solve thread confinement)
1577f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    ITestClass testClass= testMethod.getTestClass();
1578f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    Object[] instances = testClass.getInstances(true);
1579f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for(Object instance: instances) {
1580f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      invokeBeforeGroupsConfigurations(testClass, testMethod, groupMethods, suite, parameters, instance);
1581f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
158289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
158389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1584f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    long maxTimeOut= -1; // 10 seconds
1585f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1586f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin    for(IWorker<ITestNGMethod> tmw : workers) {
1587f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin      long mt= tmw.getTimeOut();
1588f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if(mt > maxTimeOut) {
1589f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        maxTimeOut= mt;
1590f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1591f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
159289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1593f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    ThreadUtil.execute(workers, threadPoolSize, maxTimeOut, true);
1594f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1595f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
1596f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Collect all the TestResults
1597f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
1598ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust    List<ITestResult> result = Lists.newArrayList();
1599f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin    for (IWorker<ITestNGMethod> tmw : workers) {
1600f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin      if (tmw instanceof TestMethodWorker) {
1601f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin        result.addAll(((TestMethodWorker)tmw).getTestResults());
1602f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin      }
1603f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
160489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1605f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for(Object instance: instances) {
1606f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      invokeAfterGroupsConfigurations(testClass, testMethod, groupMethods, suite, parameters, instance);
1607f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
160889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1609f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return result;
1610f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1611f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1612f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1613e934f66fb4fb247ebf5fec45770bc6820fbba29anullin   * Checks to see of the test method has certain dependencies that prevents
1614e934f66fb4fb247ebf5fec45770bc6820fbba29anullin   * TestNG from executing it
1615e934f66fb4fb247ebf5fec45770bc6820fbba29anullin   * @param testMethod test method being checked for
1616f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param testClass
1617f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return dependencies have been run successfully
1618f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
1619e934f66fb4fb247ebf5fec45770bc6820fbba29anullin  private boolean checkDependencies(ITestNGMethod testMethod,
1620a4e6892fbfa21c968737eaf4e4f1e4b0b7f9163eCédric Beust      ITestNGMethod[] allTestMethods)
1621f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
1622e934f66fb4fb247ebf5fec45770bc6820fbba29anullin    boolean result = true;
1623f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1624e934f66fb4fb247ebf5fec45770bc6820fbba29anullin    // If this method is marked alwaysRun, no need to check for its dependencies
1625f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if (testMethod.isAlwaysRun()) {
1626f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      return true;
1627f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
162889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1629f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Any missing group?
16300f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin    if (testMethod.getMissingGroup() != null
1631e934f66fb4fb247ebf5fec45770bc6820fbba29anullin          && !testMethod.ignoreMissingDependencies()) {
1632e934f66fb4fb247ebf5fec45770bc6820fbba29anullin      return false;
1633f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1634f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1635f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // If this method depends on groups, collect all the methods that
1636f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // belong to these groups and make sure they have been run successfully
1637e934f66fb4fb247ebf5fec45770bc6820fbba29anullin    if (dependsOnGroups(testMethod)) {
1638e934f66fb4fb247ebf5fec45770bc6820fbba29anullin      String[] groupsDependedUpon = testMethod.getGroupsDependedUpon();
1639f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1640f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // Get all the methods that belong to the group depended upon
16410f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      for (String element : groupsDependedUpon) {
164289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin        ITestNGMethod[] methods =
1643b1c182d51b05a40ac5350e562503a94d024a7c80nullin          MethodGroupsHelper.findMethodsThatBelongToGroup(testMethod,
1644f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              m_testContext.getAllTestMethods(),
16450f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin              element);
1646f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1647bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust        result = result && haveBeenRunSuccessfully(testMethod, methods);
1648f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1649f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    } // depends on groups
1650f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1651f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // If this method depends on other methods, make sure all these other
1652f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // methods have been run successfully
1653e934f66fb4fb247ebf5fec45770bc6820fbba29anullin    if (result && dependsOnMethods(testMethod)) {
165489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      ITestNGMethod[] methods =
1655b1c182d51b05a40ac5350e562503a94d024a7c80nullin        MethodHelper.findDependedUponMethods(testMethod, allTestMethods);
1656f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1657bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust      result = result && haveBeenRunSuccessfully(testMethod, methods);
1658f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1659f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1660f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return result;
1661f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1662f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1663f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1664bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust   * @return the test results that apply to one of the instances of the testMethod.
1665bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust   */
1666bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust  private Set<ITestResult> keepSameInstances(ITestNGMethod method, Set<ITestResult> results) {
1667bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust    Set<ITestResult> result = Sets.newHashSet();
1668bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust    for (ITestResult r : results) {
1669bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust      for (Object o : method.getInstances()) {
16709cb7e93d4f995f0003b27a1f28dc9d939b9b8a36Cédric Beust        // Keep this instance if 1) It's on a different class or 2) It's on the same class
16719cb7e93d4f995f0003b27a1f28dc9d939b9b8a36Cédric Beust        // and on the same instance
167260916e4ddae15723de42347024800d514b85de09Cédric Beust        Object instance = r.getInstance() != null
167360916e4ddae15723de42347024800d514b85de09Cédric Beust            ? r.getInstance() : r.getMethod().getInstances()[0];
167460916e4ddae15723de42347024800d514b85de09Cédric Beust        if (r.getTestClass() != method.getTestClass() || instance == o) result.add(r);
1675bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust      }
1676bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust    }
1677bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust    return result;
1678bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust  }
1679bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust
1680bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust  /**
1681f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return true if all the methods have been run successfully
1682f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
1683bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust  private boolean haveBeenRunSuccessfully(ITestNGMethod testMethod, ITestNGMethod[] methods) {
1684f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Make sure the method has been run successfully
16850f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin    for (ITestNGMethod method : methods) {
1686bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust      Set<ITestResult> results = keepSameInstances(testMethod, m_notifier.getPassedTests(method));
168760916e4ddae15723de42347024800d514b85de09Cédric Beust      Set<ITestResult> failedAndSkippedMethods = Sets.newHashSet();
168860916e4ddae15723de42347024800d514b85de09Cédric Beust      failedAndSkippedMethods.addAll(m_notifier.getFailedTests(method));
168960916e4ddae15723de42347024800d514b85de09Cédric Beust      failedAndSkippedMethods.addAll(m_notifier.getSkippedTests(method));
169060916e4ddae15723de42347024800d514b85de09Cédric Beust      Set<ITestResult> failedresults = keepSameInstances(testMethod, failedAndSkippedMethods);
169189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1692bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust      // If failed results were returned on the same instance, then these tests didn't pass
16930f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      if (failedresults != null && failedresults.size() > 0) {
16940f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        return false;
16950f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      }
169689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1697f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for (ITestResult result : results) {
1698f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if(!result.isSuccess()) {
1699f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          return false;
1700f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1701f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1702f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1703f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1704f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return true;
1705f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1706f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
170710a202a9e96a8067720d9e2a301ee6b67f5df5edCédric Beust//  private boolean containsInstance(Set<ITestResult> failedresults, Object[] instances) {
170810a202a9e96a8067720d9e2a301ee6b67f5df5edCédric Beust//    for (ITestResult tr : failedresults) {
170910a202a9e96a8067720d9e2a301ee6b67f5df5edCédric Beust//      for (Object o : instances) {
171010a202a9e96a8067720d9e2a301ee6b67f5df5edCédric Beust//        if (o == tr.getInstance()) {
171110a202a9e96a8067720d9e2a301ee6b67f5df5edCédric Beust//          return true;
171210a202a9e96a8067720d9e2a301ee6b67f5df5edCédric Beust//        }
171310a202a9e96a8067720d9e2a301ee6b67f5df5edCédric Beust//      }
171410a202a9e96a8067720d9e2a301ee6b67f5df5edCédric Beust//    }
171510a202a9e96a8067720d9e2a301ee6b67f5df5edCédric Beust//    return false;
171610a202a9e96a8067720d9e2a301ee6b67f5df5edCédric Beust//  }
1717bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust
1718f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1719f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * An exception was thrown by the test, determine if this method
1720f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * should be marked as a failure or as failure_but_within_successPercentage
1721f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
1722f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private void handleException(Throwable throwable,
1723f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                               ITestNGMethod testMethod,
1724f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                               ITestResult testResult,
1725f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                               int failureCount) {
1726f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    testResult.setThrowable(throwable);
1727f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    int successPercentage= testMethod.getSuccessPercentage();
1728f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    int invocationCount= testMethod.getInvocationCount();
172921dad3370294d6595fdddc3faf55792f60a913f1nullin    float numberOfTestsThatCanFail= ((100 - successPercentage) * invocationCount) / 100f;
1730f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1731f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if(failureCount < numberOfTestsThatCanFail) {
1732f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      testResult.setStatus(ITestResult.SUCCESS_PERCENTAGE_FAILURE);
1733f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1734f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    else {
1735f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      testResult.setStatus(ITestResult.FAILURE);
1736f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1737f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1738f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1739f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1740f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1741f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param ite The exception that was just thrown
1742f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param expectedExceptions The list of expected exceptions for this
1743f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * test method
1744f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return true if the exception that was just thrown is part of the
1745f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * expected exceptions
1746f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
1747bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust  private boolean isExpectedException(Throwable ite, ExpectedExceptionsHolder exceptionHolder) {
1748bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust    if (exceptionHolder == null) {
1749f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      return false;
1750f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
175127e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust
175227e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust    // TestException is the wrapper exception that TestNG will be throwing when an exception was
175327e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust    // expected but not thrown
175427e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust    if (ite.getClass() == TestException.class) {
175527e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust      return false;
175627e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust    }
175727e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust
1758bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust    Class<?>[] exceptions = exceptionHolder.expectedClasses;
1759f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    Class<?> realExceptionClass= ite.getClass();
1760f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
17610f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin    for (Class<?> exception : exceptions) {
17620f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      if (exception.isAssignableFrom(realExceptionClass)) {
1763f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        return true;
1764f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1765f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1766f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1767f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return false;
1768f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1769f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
17709d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust  static interface Predicate<K, T> {
17719d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust    boolean isTrue(K k, T v);
17729d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust  }
1773f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
17749d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust  static class CanRunFromClassPredicate implements Predicate <ITestNGMethod, IClass> {
17759d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust    @Override
17769d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust    public boolean isTrue(ITestNGMethod m, IClass v) {
17779d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust      return m.canRunFromClass(v);
1778f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1779f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1780f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
17819d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust  static class SameClassNamePredicate implements Predicate<ITestNGMethod, IClass> {
17829d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust    @Override
17839d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust    public boolean isTrue(ITestNGMethod m, IClass c) {
17849d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust      return c == null || m.getTestClass().getName().equals(c.getName());
1785f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
17869d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust  }
1787f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
17889d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust  /**
17899d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust   * @return Only the ITestNGMethods applicable for this testClass
17909d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust   */
17919d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust  private ITestNGMethod[] filterMethods(IClass testClass, ITestNGMethod[] methods,
17929d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust      Predicate<ITestNGMethod, IClass> predicate) {
1793ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust    List<ITestNGMethod> vResult= Lists.newArrayList();
1794f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1795f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for(ITestNGMethod tm : methods) {
17969d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust      if (predicate.isTrue(tm, testClass)) {
17979d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust        log(10, "Keeping method " + tm + " for class " + testClass);
1798f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        vResult.add(tm);
17999d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust      } else {
18009d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust        log(10, "Filtering out method " + tm + " for class " + testClass);
1801f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1802f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1803f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
18049d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust    ITestNGMethod[] result= vResult.toArray(new ITestNGMethod[vResult.size()]);
18059d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust
18069d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust    return result;
1807f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1808f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1809f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1810f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return true if this method depends on certain groups.
1811f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
1812f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private boolean dependsOnGroups(ITestNGMethod tm) {
1813e934f66fb4fb247ebf5fec45770bc6820fbba29anullin    String[] groups = tm.getGroupsDependedUpon();
1814e934f66fb4fb247ebf5fec45770bc6820fbba29anullin    boolean result = (null != groups) && (groups.length > 0);
1815f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return result;
1816f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1817f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1818f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1819f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return true if this method depends on certain groups.
1820f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
1821f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private boolean dependsOnMethods(ITestNGMethod tm) {
1822e934f66fb4fb247ebf5fec45770bc6820fbba29anullin    String[] methods = tm.getMethodsDependedUpon();
1823e934f66fb4fb247ebf5fec45770bc6820fbba29anullin    boolean result = (null != methods) && (methods.length > 0);
1824f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return result;
1825f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1826f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1827ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust  private void runConfigurationListeners(ITestResult tr, boolean before) {
1828ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust    if (before) {
1829ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust      for(IConfigurationListener icl: m_notifier.getConfigurationListeners()) {
1830eef09e0a0ec23bcea1995c0813ca6d29580c7869Cédric Beust        if (icl instanceof IConfigurationListener2) {
1831eef09e0a0ec23bcea1995c0813ca6d29580c7869Cédric Beust          ((IConfigurationListener2) icl).beforeConfiguration(tr);
1832eef09e0a0ec23bcea1995c0813ca6d29580c7869Cédric Beust        }
1833ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust      }
1834ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust    } else {
1835ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust      for(IConfigurationListener icl: m_notifier.getConfigurationListeners()) {
1836ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust        switch(tr.getStatus()) {
1837ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust          case ITestResult.SKIP:
1838ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust            icl.onConfigurationSkip(tr);
1839ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust            break;
1840ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust          case ITestResult.FAILURE:
1841ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust            icl.onConfigurationFailure(tr);
1842ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust            break;
1843ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust          case ITestResult.SUCCESS:
1844ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust            icl.onConfigurationSuccess(tr);
1845ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust            break;
1846ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust        }
1847f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1848f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1849f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
185089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1851c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust  void runTestListeners(ITestResult tr) {
1852f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    runTestListeners(tr, m_notifier.getTestListeners());
1853f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
185489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1855f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  // TODO: move this from here as it is directly called from TestNG
1856f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  public static void runTestListeners(ITestResult tr, List<ITestListener> listeners) {
1857f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for (ITestListener itl : listeners) {
1858f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      switch(tr.getStatus()) {
1859f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        case ITestResult.SKIP: {
1860f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          itl.onTestSkipped(tr);
1861f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          break;
1862f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1863f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        case ITestResult.SUCCESS_PERCENTAGE_FAILURE: {
1864f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          itl.onTestFailedButWithinSuccessPercentage(tr);
1865f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          break;
1866f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1867f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        case ITestResult.FAILURE: {
1868f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          itl.onTestFailure(tr);
1869f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          break;
1870f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1871f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        case ITestResult.SUCCESS: {
1872f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          itl.onTestSuccess(tr);
1873f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          break;
1874f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1875f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1876f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        case ITestResult.STARTED: {
1877f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          itl.onTestStart(tr);
1878f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          break;
1879f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1880f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1881f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        default: {
1882f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          assert false : "UNKNOWN STATUS:" + tr;
1883f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1884f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1885f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1886f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1887f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1888f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private void log(int level, String s) {
1889f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    Utils.log("Invoker " + Thread.currentThread().hashCode(), level, s);
1890f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
189189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1892eddb4a9423c14fee808a30e92ad77a16e88b320enullin  /**
1893eddb4a9423c14fee808a30e92ad77a16e88b320enullin   * This class holds a {@code ParameterHolder} and in case of an error, a non-null
1894eddb4a9423c14fee808a30e92ad77a16e88b320enullin   * {@code TestResult} containing the cause
1895eddb4a9423c14fee808a30e92ad77a16e88b320enullin   */
1896f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private static class ParameterBag {
1897c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust    final ParameterHolder parameterHolder;
1898eddb4a9423c14fee808a30e92ad77a16e88b320enullin    final List<ITestResult> errorResults = Lists.newArrayList();
189989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1900c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust    public ParameterBag(ParameterHolder params, TestResult tr) {
1901c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust      parameterHolder = params;
1902eddb4a9423c14fee808a30e92ad77a16e88b320enullin      if (tr != null) {
1903f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        errorResults.add(tr);
1904f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1905f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
190689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1907f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    public boolean hasErrors() {
1908f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      return !errorResults.isEmpty();
1909f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1910f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1911c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust
1912f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust}
1913