Invoker.java revision 2343cba1dccc30a50322215da78f14179e2a0271
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    }
1012084500c0b9f7e95d1accfe5ff2c48ee0747aac6toddq    instances.add(getMethodInvocationToken(method, 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(),
1696f53a2551bab7c2f5a85c6f5ede755512e490a4bBrandon Pedersen                                             System.currentTimeMillis(),
1706f53a2551bab7c2f5a85c6f5ede755512e490a4bBrandon Pedersen                                             m_testContext);
171f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1722d568355761a9632bf24a87984e241f8a079d724Cédric Beust      IConfigurationAnnotation configurationAnnotation= null;
173f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      try {
174f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        Object[] instances= tm.getInstances();
1750f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        if (instances == null || instances.length == 0) {
1760f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin          instances = new Object[] { instance };
1770f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        }
178f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        Class<?> objectClass= instances[0].getClass();
179f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        Method method= tm.getMethod();
180f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
181f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // Only run the configuration if
182f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // - the test is enabled and
183f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // - the Configuration method belongs to the same class or a parent
184f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if(MethodHelper.isEnabled(objectClass, m_annotationFinder)) {
185423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust          configurationAnnotation = AnnotationHelper.findConfiguration(m_annotationFinder, method);
186f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
187e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust          if (MethodHelper.isEnabled(configurationAnnotation)) {
1880501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust            boolean isClassConfiguration = isClassConfiguration(configurationAnnotation);
18989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin            boolean isSuiteConfiguration = isSuiteConfiguration(configurationAnnotation);
190e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            boolean alwaysRun= isAlwaysRun(configurationAnnotation);
19189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
192423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust            if (!confInvocationPassed(tm, currentTestMethod, testClass, instance) && !alwaysRun) {
193423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust              handleConfigurationSkip(tm, testResult, configurationAnnotation, currentTestMethod, instance, suite);
194e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust              continue;
195e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            }
19689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
197e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            log(3, "Invoking " + Utils.detailedMethodName(tm, true));
19889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
199facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust            Object[] parameters = Parameters.createConfigurationParameters(tm.getMethod(),
200facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust                params,
201facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust                parameterValues,
202facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust                currentTestMethod,
203facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust                m_annotationFinder,
204facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust                suite,
205da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust                m_testContext,
206da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust                testMethodResult);
207e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            testResult.setParameters(parameters);
20889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
209e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            Object[] newInstances= (null != instance) ? new Object[] { instance } : instances;
21089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
211ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust            runConfigurationListeners(testResult, true /* before */);
212ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust
213e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            invokeConfigurationMethod(newInstances, tm,
2140501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust              parameters, isClassConfiguration, isSuiteConfiguration, testResult);
21589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
216e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            // TODO: probably we should trigger the event for each instance???
217e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            testResult.setEndMillis(System.currentTimeMillis());
218ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust            runConfigurationListeners(testResult, false /* after */);
219e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust          }
220e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust          else {
221e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust            log(3,
222e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust                "Skipping "
223e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust                + Utils.detailedMethodName(tm, true)
224e0d94c7896da2777a41a10ed3efcf5231e76f907Cédric Beust                + " because it is not enabled");
225f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
226f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        } // if is enabled
227f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        else {
228f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          log(3,
229f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              "Skipping "
230f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              + Utils.detailedMethodName(tm, true)
231f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              + " because "
232f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              + objectClass.getName()
233f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              + " is not enabled");
234f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
235f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
236f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      catch(InvocationTargetException ex) {
237423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust        handleConfigurationFailure(ex, tm, testResult, configurationAnnotation, currentTestMethod, instance, suite);
238f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
239f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      catch(TestNGException ex) {
240f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // Don't wrap TestNGExceptions, it could be a missing parameter on a
241f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // @Configuration method
242423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust        handleConfigurationFailure(ex, tm, testResult, configurationAnnotation, currentTestMethod, instance, suite);
243f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
244f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      catch(Throwable ex) { // covers the non-wrapper exceptions
245423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust        handleConfigurationFailure(ex, tm, testResult, configurationAnnotation, currentTestMethod, instance, suite);
246f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
247f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    } // for methods
248f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
24989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
250f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
25162a82c6aa5725c9e9d600af5ee06a5852100208cnullin   * Marks the current <code>TestResult</code> as skipped and invokes the listeners.
252f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
25389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin  private void handleConfigurationSkip(ITestNGMethod tm,
25489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                       ITestResult testResult,
25589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                       IConfigurationAnnotation annotation,
25689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                       ITestNGMethod currentTestMethod,
257423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust                                       Object instance,
25862a82c6aa5725c9e9d600af5ee06a5852100208cnullin                                       XmlSuite suite) {
259423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust    recordConfigurationInvocationFailed(tm, testResult.getTestClass(), annotation, currentTestMethod, instance, suite);
260f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    testResult.setStatus(ITestResult.SKIP);
261ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust    runConfigurationListeners(testResult, false /* after */);
262f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
26389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
264f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
265f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * Is the current <code>IConfiguration</code> a class-level method.
266f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
2672d568355761a9632bf24a87984e241f8a079d724Cédric Beust  private  boolean isClassConfiguration(IConfigurationAnnotation configurationAnnotation) {
2680b2ac5eab08098da2c2b63d4a3f87ba72ad5d6a1nullin    if (null == configurationAnnotation) {
269f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      return false;
270f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
271f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
2720b2ac5eab08098da2c2b63d4a3f87ba72ad5d6a1nullin    boolean before = configurationAnnotation.getBeforeTestClass();
2730b2ac5eab08098da2c2b63d4a3f87ba72ad5d6a1nullin    boolean after = configurationAnnotation.getAfterTestClass();
274f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
2750b2ac5eab08098da2c2b63d4a3f87ba72ad5d6a1nullin    return before || after;
276f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
277f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
278f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
2790501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust   * Is the current <code>IConfiguration</code> a suite level method.
2800501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust   */
2810501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust  private  boolean isSuiteConfiguration(IConfigurationAnnotation configurationAnnotation) {
2820b2ac5eab08098da2c2b63d4a3f87ba72ad5d6a1nullin    if (null == configurationAnnotation) {
2830501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust      return false;
2840501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust    }
2850501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust
2860b2ac5eab08098da2c2b63d4a3f87ba72ad5d6a1nullin    boolean before = configurationAnnotation.getBeforeSuite();
2870b2ac5eab08098da2c2b63d4a3f87ba72ad5d6a1nullin    boolean after = configurationAnnotation.getAfterSuite();
2880501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust
2890b2ac5eab08098da2c2b63d4a3f87ba72ad5d6a1nullin    return before || after;
2900501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust  }
2910501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust
2920501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust  /**
293f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * Is the <code>IConfiguration</code> marked as alwaysRun.
294f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
2952d568355761a9632bf24a87984e241f8a079d724Cédric Beust  private boolean isAlwaysRun(IConfigurationAnnotation configurationAnnotation) {
296f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if(null == configurationAnnotation) {
297f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      return false;
298f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
29989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
300f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    boolean alwaysRun= false;
301f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if ((configurationAnnotation.getAfterSuite()
302f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        || configurationAnnotation.getAfterTest()
303f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        || configurationAnnotation.getAfterTestClass()
304f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        || configurationAnnotation.getAfterTestMethod())
305f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        && configurationAnnotation.getAlwaysRun())
306f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    {
307f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        alwaysRun= true;
308f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
30989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
310f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return alwaysRun;
311f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
31289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
313f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private void handleConfigurationFailure(Throwable ite,
314f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                          ITestNGMethod tm,
315f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                          ITestResult testResult,
3162d568355761a9632bf24a87984e241f8a079d724Cédric Beust                                          IConfigurationAnnotation annotation,
31762a82c6aa5725c9e9d600af5ee06a5852100208cnullin                                          ITestNGMethod currentTestMethod,
318423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust                                          Object instance,
31989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                          XmlSuite suite)
320f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
321f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    Throwable cause= ite.getCause() != null ? ite.getCause() : ite;
32289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
323f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if(SkipException.class.isAssignableFrom(cause.getClass())) {
324f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      SkipException skipEx= (SkipException) cause;
3250c3edfde6ca92fb2cfeb3072fa1c7cb08c1706c3DanFabulich      if(skipEx.isSkip()) {
326f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        testResult.setThrowable(skipEx);
327423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust        handleConfigurationSkip(tm, testResult, annotation, currentTestMethod, instance, suite);
328f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        return;
329f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
330f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
331161d9860588ad89389848d70eb0a2f6f0cb46d1bCédric Beust    Utils.log("", 3, "Failed to invoke configuration method "
332f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        + tm.getRealClass().getName() + "." + tm.getMethodName() + ":" + cause.getMessage());
333f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    handleException(cause, tm, testResult, 1);
334ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust    runConfigurationListeners(testResult, false /* after */);
335f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
33689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin    //
337f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // If in TestNG mode, need to take a look at the annotation to figure out
338f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // what kind of @Configuration method we're dealing with
339f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
340f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if (null != annotation) {
341423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust      recordConfigurationInvocationFailed(tm, testResult.getTestClass(), annotation, currentTestMethod, instance, suite);
342f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
343f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
344f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
345f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
346f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return All the classes that belong to the same <test> tag as @param cls
347f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
348f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private XmlClass[] findClassesInSameTest(Class<?> cls, XmlSuite suite) {
3490f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beust    Map<String, XmlClass> vResult= Maps.newHashMap();
350f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    String className= cls.getName();
351f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for(XmlTest test : suite.getTests()) {
352f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for(XmlClass testClass : test.getXmlClasses()) {
353f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if(testClass.getName().equals(className)) {
354f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
355f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          // Found it, add all the classes in this test in the result
356f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          for(XmlClass thisClass : test.getXmlClasses()) {
357f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            vResult.put(thisClass.getName(), thisClass);
358f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
359f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          // Note:  we need to iterate through the entire suite since the same
360f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          // class might appear in several <test> tags
361f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
362f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
363f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
364f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
365f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    XmlClass[] result= vResult.values().toArray(new XmlClass[vResult.size()]);
366f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
367f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return result;
368f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
369f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
370f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
371f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * Record internally the failure of a Configuration, so that we can determine
372f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * later if @Test should be skipped.
373f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
37489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin  private void recordConfigurationInvocationFailed(ITestNGMethod tm,
37589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                   IClass testClass,
37689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                   IConfigurationAnnotation annotation,
37789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                   ITestNGMethod currentTestMethod,
378423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust                                                   Object instance,
37962a82c6aa5725c9e9d600af5ee06a5852100208cnullin                                                   XmlSuite suite) {
38062a82c6aa5725c9e9d600af5ee06a5852100208cnullin    // If beforeTestClass or afterTestClass failed, mark either the config method's
38162a82c6aa5725c9e9d600af5ee06a5852100208cnullin    // entire class as failed, or the class under tests as failed, depending on
38262a82c6aa5725c9e9d600af5ee06a5852100208cnullin    // the configuration failure policy
38362a82c6aa5725c9e9d600af5ee06a5852100208cnullin    if (annotation.getBeforeTestClass() || annotation.getAfterTestClass()) {
38462a82c6aa5725c9e9d600af5ee06a5852100208cnullin      // tm is the configuration method, and currentTestMethod is null for BeforeClass
38562a82c6aa5725c9e9d600af5ee06a5852100208cnullin      // methods, so we need testClass
38662a82c6aa5725c9e9d600af5ee06a5852100208cnullin      if (m_continueOnFailedConfiguration) {
387423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust        setClassInvocationFailure(testClass.getRealClass(), instance);
38862a82c6aa5725c9e9d600af5ee06a5852100208cnullin      } else {
389423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust        setClassInvocationFailure(tm.getRealClass(), instance);
39062a82c6aa5725c9e9d600af5ee06a5852100208cnullin      }
39162a82c6aa5725c9e9d600af5ee06a5852100208cnullin    }
39289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
39362a82c6aa5725c9e9d600af5ee06a5852100208cnullin    // If before/afterTestMethod failed, mark either the config method's entire
39462a82c6aa5725c9e9d600af5ee06a5852100208cnullin    // class as failed, or just the current test method as failed, depending on
39562a82c6aa5725c9e9d600af5ee06a5852100208cnullin    // the configuration failure policy
39662a82c6aa5725c9e9d600af5ee06a5852100208cnullin    else if (annotation.getBeforeTestMethod() || annotation.getAfterTestMethod()) {
39762a82c6aa5725c9e9d600af5ee06a5852100208cnullin      if (m_continueOnFailedConfiguration) {
398423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust        setMethodInvocationFailure(currentTestMethod, instance);
39962a82c6aa5725c9e9d600af5ee06a5852100208cnullin      } else {
400423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust        setClassInvocationFailure(tm.getRealClass(), instance);
40162a82c6aa5725c9e9d600af5ee06a5852100208cnullin      }
402f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
403f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
404f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // If beforeSuite or afterSuite failed, mark *all* the classes as failed
405f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // for configurations.  At this point, the entire Suite is screwed
406f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    else if (annotation.getBeforeSuite() || annotation.getAfterSuite()) {
407f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      m_suiteState.failed();
408f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
409f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
410f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // beforeTest or afterTest:  mark all the classes in the same
411f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // <test> stanza as failed for configuration
412f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    else if (annotation.getBeforeTest() || annotation.getAfterTest()) {
413423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust      setClassInvocationFailure(tm.getRealClass(), instance);
414f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      XmlClass[] classes= findClassesInSameTest(tm.getRealClass(), suite);
415f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for(XmlClass xmlClass : classes) {
416423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust        setClassInvocationFailure(xmlClass.getSupportClass(), instance);
417f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
418f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
419f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    String[] beforeGroups= annotation.getBeforeGroups();
420f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if(null != beforeGroups && beforeGroups.length > 0) {
421f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for(String group: beforeGroups) {
422f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        m_beforegroupsFailures.put(group, Boolean.FALSE);
423f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
424f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
425f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
42689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
427f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
428f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return true if this class has successfully run all its @Configuration
429f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * method or false if at least one of these methods failed.
430f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
431423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust  private boolean confInvocationPassed(ITestNGMethod method, ITestNGMethod currentTestMethod, IClass testClass, Object instance) {
432f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    boolean result= true;
433f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
43462a82c6aa5725c9e9d600af5ee06a5852100208cnullin    // If continuing on config failure, check invocation results for the class
43562a82c6aa5725c9e9d600af5ee06a5852100208cnullin    // under test, otherwise use the method's declaring class
43689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin    Class<?> cls = m_continueOnFailedConfiguration ?
43762a82c6aa5725c9e9d600af5ee06a5852100208cnullin            testClass.getRealClass() : method.getMethod().getDeclaringClass();
43862a82c6aa5725c9e9d600af5ee06a5852100208cnullin
439f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if(m_suiteState.isFailed()) {
440f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      result= false;
441f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
442f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    else {
443423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust      if (m_classInvocationResults.containsKey(cls)) {
4440f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        if (! m_continueOnFailedConfiguration) {
4450f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin          result = !m_classInvocationResults.containsKey(cls);
4460f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        } else {
4470f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin          result = !m_classInvocationResults.get(cls).contains(instance);
4480f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        }
449f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
45062a82c6aa5725c9e9d600af5ee06a5852100208cnullin      // if method is BeforeClass, currentTestMethod will be null
45189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      else if (m_continueOnFailedConfiguration &&
45289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin              currentTestMethod != null &&
45362a82c6aa5725c9e9d600af5ee06a5852100208cnullin              m_methodInvocationResults.containsKey(currentTestMethod)) {
4542084500c0b9f7e95d1accfe5ff2c48ee0747aac6toddq        result = !m_methodInvocationResults.get(currentTestMethod).contains(getMethodInvocationToken(currentTestMethod, instance));
45562a82c6aa5725c9e9d600af5ee06a5852100208cnullin      }
456423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust      else if (! m_continueOnFailedConfiguration) {
457f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        for(Class<?> clazz: m_classInvocationResults.keySet()) {
4581e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust//          if (clazz == cls) {
459f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          if(clazz.isAssignableFrom(cls)) {
460f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            result= false;
461f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            break;
462f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
463f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
464f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
465f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
466f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
467f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // check if there are failed @BeforeGroups
468f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    String[] groups= method.getGroups();
469f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if(null != groups && groups.length > 0) {
470f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for(String group: groups) {
471f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if(m_beforegroupsFailures.containsKey(group)) {
472f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          result= false;
473f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          break;
474f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
475f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
476f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
477f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return result;
478f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
479f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
4802084500c0b9f7e95d1accfe5ff2c48ee0747aac6toddq   // Creates a token for tracking a unique invocation of a method on an instance.
4812084500c0b9f7e95d1accfe5ff2c48ee0747aac6toddq   // Is used when configFailurePolicy=continue.
4822084500c0b9f7e95d1accfe5ff2c48ee0747aac6toddq  private Object getMethodInvocationToken(ITestNGMethod method, Object instance) {
4832084500c0b9f7e95d1accfe5ff2c48ee0747aac6toddq    return String.format("%s+%d", instance.toString(), method.getCurrentInvocationCount());
4842084500c0b9f7e95d1accfe5ff2c48ee0747aac6toddq  }
4852084500c0b9f7e95d1accfe5ff2c48ee0747aac6toddq
486f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
487f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * Effectively invokes a configuration method on all passed in instances.
488d3c04c36b8f179fd5aa1b53711a5b909cde06d09nalin.makar@gmail.com   * TODO: Should change this method to be more like invokeMethod() so that we can
489d3c04c36b8f179fd5aa1b53711a5b909cde06d09nalin.makar@gmail.com   * handle calls to {@code IInvokedMethodListener} better.
49089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin   *
491f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param instances the instances to invoke the configuration method on
492f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param tm the configuration method
493f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param params the parameters needed for method invocation
494f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param isClass flag if the configuration method is a class level method // FIXME: this looks like a missusage
495f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param testResult
496f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @throws InvocationTargetException
497f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @throws IllegalAccessException
498f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
499f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private void invokeConfigurationMethod(Object[] instances,
500f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                         ITestNGMethod tm,
501f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                         Object[] params,
502f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                         boolean isClass,
5030501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust                                         boolean isSuite,
504f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                         ITestResult testResult)
50589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin    throws InvocationTargetException, IllegalAccessException
506f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
507f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Mark this method with the current thread id
508f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    tm.setId(ThreadUtil.currentThreadInfo());
509f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
510caaf31e9587ae83c6b6064fa41fb939d362b4e37Cédric Beust    // Only a @BeforeMethod/@AfterMethod needs to be run before each instance, all the other
511caaf31e9587ae83c6b6064fa41fb939d362b4e37Cédric Beust    // configuration methods only need to be run once
512caaf31e9587ae83c6b6064fa41fb939d362b4e37Cédric Beust    List<Object> actualInstances = Lists.newArrayList();
513caaf31e9587ae83c6b6064fa41fb939d362b4e37Cédric Beust    if (tm.isBeforeMethodConfiguration() || tm.isAfterMethodConfiguration()) {
514caaf31e9587ae83c6b6064fa41fb939d362b4e37Cédric Beust      actualInstances.addAll(Arrays.asList(instances));
515caaf31e9587ae83c6b6064fa41fb939d362b4e37Cédric Beust    } else {
516caaf31e9587ae83c6b6064fa41fb939d362b4e37Cédric Beust      actualInstances.add(instances[0]);
517caaf31e9587ae83c6b6064fa41fb939d362b4e37Cédric Beust    }
518caaf31e9587ae83c6b6064fa41fb939d362b4e37Cédric Beust    for(Object targetInstance : actualInstances) {
51992d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann      InvokedMethod invokedMethod= new InvokedMethod(targetInstance,
520f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                          tm,
521f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                          params,
522f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                          false, /* isTest */
523f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                          isClass, /* ??? */
524234c85874acc0cd3360639949fbd566255ab31edCédric Beust                                          System.currentTimeMillis(),
525234c85874acc0cd3360639949fbd566255ab31edCédric Beust                                          testResult);
526f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
52792d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann      runInvokedMethodListeners(BEFORE_INVOCATION, invokedMethod, testResult);
52892d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann      m_notifier.addInvokedMethod(invokedMethod);
529f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      try {
530f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        Reporter.setCurrentTestResult(testResult);
5310bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust        Method method = tm.getMethod();
532e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust
533e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust        //
534e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust        // If this method is a IHookable, invoke its run() method
535e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust        //
536e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust        IConfigurable configurableInstance =
537e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust          IConfigurable.class.isAssignableFrom(tm.getMethod().getDeclaringClass()) ?
538e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust          (IConfigurable) targetInstance : m_configuration.getConfigurable();
539e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust        if (configurableInstance != null) {
5400bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust          //
5410bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust          // If this method is a IConfigurable, invoke its run() method
5420bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust          //
543b1c182d51b05a40ac5350e562503a94d024a7c80nullin          MethodInvocationHelper.invokeConfigurable(targetInstance, params, configurableInstance, method,
544e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust              testResult);
5450bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust        }
5460bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust        else {
5470bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust          //
548830ff4bf3fbfae0d63cb762b9c0d9a184feb58a3Cédric Beust          // Not a IConfigurable, invoke directly
5490bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust          //
550830ff4bf3fbfae0d63cb762b9c0d9a184feb58a3Cédric Beust          if (MethodHelper.calculateTimeOut(tm) <= 0) {
551b1c182d51b05a40ac5350e562503a94d024a7c80nullin            MethodInvocationHelper.invokeMethod(method, targetInstance, params);
552830ff4bf3fbfae0d63cb762b9c0d9a184feb58a3Cédric Beust          }
553830ff4bf3fbfae0d63cb762b9c0d9a184feb58a3Cédric Beust          else {
554b1c182d51b05a40ac5350e562503a94d024a7c80nullin            MethodInvocationHelper.invokeWithTimeout(tm, targetInstance, params, testResult);
555830ff4bf3fbfae0d63cb762b9c0d9a184feb58a3Cédric Beust            if (!testResult.isSuccess()) {
556830ff4bf3fbfae0d63cb762b9c0d9a184feb58a3Cédric Beust              // A time out happened
557830ff4bf3fbfae0d63cb762b9c0d9a184feb58a3Cédric Beust              throwConfigurationFailure(testResult, testResult.getThrowable());
558830ff4bf3fbfae0d63cb762b9c0d9a184feb58a3Cédric Beust              throw testResult.getThrowable();
559830ff4bf3fbfae0d63cb762b9c0d9a184feb58a3Cédric Beust            }
560830ff4bf3fbfae0d63cb762b9c0d9a184feb58a3Cédric Beust          }
5610bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust        }
5620501e252894ab9e477ad7a62b8e4c88aed7bc697Cédric Beust        // Only run the method once if it's @BeforeSuite or @AfterSuite
5630f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        if (isSuite) {
5640f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin          break;
5650f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        }
566db66a3de4428040dd9f7e377a3b6835965c8b0cdCédric Beust      }
567d3c04c36b8f179fd5aa1b53711a5b909cde06d09nalin.makar@gmail.com      catch (InvocationTargetException ex) {
5680bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust       throwConfigurationFailure(testResult, ex);
5690bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust       throw ex;
570d3c04c36b8f179fd5aa1b53711a5b909cde06d09nalin.makar@gmail.com      }
571d3c04c36b8f179fd5aa1b53711a5b909cde06d09nalin.makar@gmail.com      catch (IllegalAccessException ex) {
5720bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust        throwConfigurationFailure(testResult, ex);
5730bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust        throw ex;
5740bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust      }
5750bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust      catch (NoSuchMethodException ex) {
5760bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust        throwConfigurationFailure(testResult, ex);
5770bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust        throw new TestNGException(ex);
5780bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust      }
5790bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust      catch (Throwable ex) {
5800bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust        throwConfigurationFailure(testResult, ex);
5810bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust        throw new TestNGException(ex);
5820bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust      }
5830bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust      finally {
584f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        Reporter.setCurrentTestResult(testResult);
58592d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann        runInvokedMethodListeners(AFTER_INVOCATION, invokedMethod, testResult);
58689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      }
587f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
588f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
589f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
5900bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust  private void throwConfigurationFailure(ITestResult testResult, Throwable ex)
5910bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust  {
5920bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust    testResult.setStatus(ITestResult.FAILURE);;
5930bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust    testResult.setThrowable(ex.getCause() == null ? ex : ex.getCause());
5940bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust  }
5950bc5acb68f6cace8b7f8b07e2eebc6f385c337e0Cédric Beust
59692d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann  private void runInvokedMethodListeners(InvokedMethodListenerMethod listenerMethod, IInvokedMethod invokedMethod,
597398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust      ITestResult testResult)
598398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust  {
59992d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann    if ( noListenersPresent() ) {
60092d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann      return;
601398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust    }
60292d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann
60392d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann    InvokedMethodListenerInvoker invoker = new InvokedMethodListenerInvoker(listenerMethod, testResult, m_testContext);
60492d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann    for (IInvokedMethodListener currentListener : m_invokedMethodListeners) {
60592d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann      invoker.invokeListener(currentListener, invokedMethod);
60692d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann    }
60792d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann  }
60892d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann
60992d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann  private boolean noListenersPresent() {
61092d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann    return (m_invokedMethodListeners == null) || (m_invokedMethodListeners.size() == 0);
611398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust  }
612398dbfd526cb7a568c29cc4a211d5cb8a7a158bcCédric Beust
613927a6d8a655520943e3a8a9ea9f09cbfe56f2ae6Cédric Beust  // pass both paramValues and paramIndex to be thread safe in case parallel=true + dataprovider.
614f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private ITestResult invokeMethod(Object[] instances,
615f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   int instanceIndex,
616f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   final ITestNGMethod tm,
617f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   Object[] parameterValues,
618927a6d8a655520943e3a8a9ea9f09cbfe56f2ae6Cédric Beust                                   int parametersIndex,
619f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   XmlSuite suite,
620f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   Map<String, String> params,
621f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   ITestClass testClass,
622f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   ITestNGMethod[] beforeMethods,
623f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   ITestNGMethod[] afterMethods,
624f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                   ConfigurationGroupMethods groupMethods) {
62594efdf8e6ac7332eadf8bfe5d1fe699caee5d051Cédric Beust    TestResult testResult = new TestResult();
62694efdf8e6ac7332eadf8bfe5d1fe699caee5d051Cédric Beust
627f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
628f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Invoke beforeGroups configurations
629f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
6303297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust    Object instance = instances[instanceIndex];
631f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    invokeBeforeGroupsConfigurations(testClass, tm, groupMethods, suite, params,
6323297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust        instance);
633f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
634f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
63545a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust    // Invoke beforeMethods only if
63645a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust    // - firstTimeOnly is not set
63745a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust    // - firstTimeOnly is set, and we are reaching at the first invocationCount
638f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
63989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin    invokeConfigurations(testClass, tm,
64045a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      filterConfigurationMethods(tm, beforeMethods, true /* beforeMethods */),
641facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust      suite, params, parameterValues,
6423297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust      instance, testResult);
64389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
644f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
645f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Create the ExtraOutput for this method
646f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
64738ef90d96ee65073c1090455e7caff2a85d654e2Cédric Beust    InvokedMethod invokedMethod = null;
648f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    try {
6493297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust      testResult.init(testClass, instance,
650f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                 tm,
651f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                 null,
652f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                 System.currentTimeMillis(),
6536f53a2551bab7c2f5a85c6f5ede755512e490a4bBrandon Pedersen                                 0,
6546f53a2551bab7c2f5a85c6f5ede755512e490a4bBrandon Pedersen                                 m_testContext);
655f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      testResult.setParameters(parameterValues);
656f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      testResult.setHost(m_testContext.getHost());
657f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      testResult.setStatus(ITestResult.STARTED);
658f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
6593297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust      invokedMethod= new InvokedMethod(instance,
660f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          tm,
661f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          parameterValues,
662e934f66fb4fb247ebf5fec45770bc6820fbba29anullin          true /* isTest */,
663e934f66fb4fb247ebf5fec45770bc6820fbba29anullin          false /* isConfiguration */,
664234c85874acc0cd3360639949fbd566255ab31edCédric Beust          System.currentTimeMillis(),
665234c85874acc0cd3360639949fbd566255ab31edCédric Beust          testResult);
666f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
667272431b36621155717086ce4a384855f3003fff1Ansgar Konermann      // Fix from ansgarkonermann
668272431b36621155717086ce4a384855f3003fff1Ansgar Konermann      // invokedMethod is used in the finally, which can be invoked if
669272431b36621155717086ce4a384855f3003fff1Ansgar Konermann      // any of the test listeners throws an exception, therefore,
670272431b36621155717086ce4a384855f3003fff1Ansgar Konermann      // invokedMethod must have a value before we get here
67159d29c5fddc09eb6dc132569b0f4c4026f033b1aAnsgar Konermann      runTestListeners(testResult);
67259d29c5fddc09eb6dc132569b0f4c4026f033b1aAnsgar Konermann
67392d93309b4eca03e639a5b027e484ac52f049ef1Ansgar Konermann      runInvokedMethodListeners(BEFORE_INVOCATION, invokedMethod, testResult);
67438ef90d96ee65073c1090455e7caff2a85d654e2Cédric Beust
675f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      m_notifier.addInvokedMethod(invokedMethod);
67689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
677f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Method thisMethod= tm.getMethod();
67889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
6793297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust      if(confInvocationPassed(tm, tm, testClass, instance)) {
680f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        log(3, "Invoking " + thisMethod.getDeclaringClass().getName() + "." +
681f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            thisMethod.getName());
682f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
683f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // If no timeOut, just invoke the method
684331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust        if (MethodHelper.calculateTimeOut(tm) <= 0) {
685711b9b624165b9185efea58f010a40275e19c972mendelson.paul          try {
686711b9b624165b9185efea58f010a40275e19c972mendelson.paul            Reporter.setCurrentTestResult(testResult);
687711b9b624165b9185efea58f010a40275e19c972mendelson.paul            //
688711b9b624165b9185efea58f010a40275e19c972mendelson.paul            // If this method is a IHookable, invoke its run() method
689711b9b624165b9185efea58f010a40275e19c972mendelson.paul            //
690e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust            IHookable hookableInstance =
691e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust              IHookable.class.isAssignableFrom(thisMethod.getDeclaringClass()) ?
692e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust              (IHookable) instance : m_configuration.getHookable();
693e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust            if (hookableInstance != null) {
694b1c182d51b05a40ac5350e562503a94d024a7c80nullin              MethodInvocationHelper.invokeHookable(instance,
695e14d0686c991db20dacf627becc3d162a9f35f90Cédric Beust                  parameterValues, hookableInstance, thisMethod, testResult);
696711b9b624165b9185efea58f010a40275e19c972mendelson.paul            }
697711b9b624165b9185efea58f010a40275e19c972mendelson.paul            //
698711b9b624165b9185efea58f010a40275e19c972mendelson.paul            // Not a IHookable, invoke directly
699711b9b624165b9185efea58f010a40275e19c972mendelson.paul            //
700711b9b624165b9185efea58f010a40275e19c972mendelson.paul            else {
701b1c182d51b05a40ac5350e562503a94d024a7c80nullin              MethodInvocationHelper.invokeMethod(thisMethod, instance,
702f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                  parameterValues);
70389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin            }
704711b9b624165b9185efea58f010a40275e19c972mendelson.paul            testResult.setStatus(ITestResult.SUCCESS);
705711b9b624165b9185efea58f010a40275e19c972mendelson.paul          }
706711b9b624165b9185efea58f010a40275e19c972mendelson.paul          finally {
707711b9b624165b9185efea58f010a40275e19c972mendelson.paul            Reporter.setCurrentTestResult(null);
708f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
709f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
710f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        else {
711331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust          //
712331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust          // Method with a timeout
713331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust          //
714f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          try {
715f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            Reporter.setCurrentTestResult(testResult);
716b1c182d51b05a40ac5350e562503a94d024a7c80nullin            MethodInvocationHelper.invokeWithTimeout(tm, instance, parameterValues, testResult);
717f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
718f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          finally {
719f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            Reporter.setCurrentTestResult(null);
720f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
721f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
722f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
723f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      else {
724f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        testResult.setStatus(ITestResult.SKIP);
725f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
726f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
727f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    catch(InvocationTargetException ite) {
728f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      testResult.setThrowable(ite.getCause());
729d3c04c36b8f179fd5aa1b53711a5b909cde06d09nalin.makar@gmail.com      testResult.setStatus(ITestResult.FAILURE);
730f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
731f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    catch(ThreadExecutionException tee) { // wrapper for TestNGRuntimeException
732f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Throwable cause= tee.getCause();
733f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if(TestNGRuntimeException.class.equals(cause.getClass())) {
734f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        testResult.setThrowable(cause.getCause());
735f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
736f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      else {
737f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        testResult.setThrowable(cause);
738f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
739d3c04c36b8f179fd5aa1b53711a5b909cde06d09nalin.makar@gmail.com      testResult.setStatus(ITestResult.FAILURE);
740f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
741f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    catch(Throwable thr) { // covers the non-wrapper exceptions
742f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      testResult.setThrowable(thr);
743d3c04c36b8f179fd5aa1b53711a5b909cde06d09nalin.makar@gmail.com      testResult.setStatus(ITestResult.FAILURE);
744f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
745f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    finally {
746bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust      ExpectedExceptionsHolder expectedExceptionClasses
747318a4e47ce813109c76fc8281c9db5f04448f3f1Cédric Beust          = MethodHelper.findExpectedExceptions(m_annotationFinder, tm.getMethod());
748ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust      List<ITestResult> results = Lists.newArrayList();
749318a4e47ce813109c76fc8281c9db5f04448f3f1Cédric Beust      results.add(testResult);
7506216d78ae0757b7d57aa6e94cc041447d610724dCédric Beust      handleInvocationResults(tm, results, null, 0, expectedExceptionClasses, false,
75134ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust          false /* collect results */);
75289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
753dd84c4f1673772d6b1febb72add6a2ae40f4e4ccCédric Beust      // If this method has a data provider and just failed, memorize the number
754dd84c4f1673772d6b1febb72add6a2ae40f4e4ccCédric Beust      // at which it failed.
7551ed096c7af783713cdeb4a3e9c0c4a02491d65fcCédric Beust      // Note: we're not exactly testing that this method has a data provider, just
7561ed096c7af783713cdeb4a3e9c0c4a02491d65fcCédric Beust      // that it has parameters, so might have to revisit this if bugs get reported
7571ed096c7af783713cdeb4a3e9c0c4a02491d65fcCédric Beust      // for the case where this method has parameters that don't come from a data
7581ed096c7af783713cdeb4a3e9c0c4a02491d65fcCédric Beust      // provider
759dd84c4f1673772d6b1febb72add6a2ae40f4e4ccCédric Beust      if (testResult.getThrowable() != null && parameterValues.length > 0) {
760927a6d8a655520943e3a8a9ea9f09cbfe56f2ae6Cédric Beust        tm.addFailedInvocationNumber(parametersIndex);
761dd84c4f1673772d6b1febb72add6a2ae40f4e4ccCédric Beust      }
762dd84c4f1673772d6b1febb72add6a2ae40f4e4ccCédric Beust
763f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
764f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // Increment the invocation count for this method
765f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
766f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      tm.incrementCurrentInvocationCount();
767f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
768f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if (testResult != null) {
769f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        testResult.setEndMillis(System.currentTimeMillis());
770f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
771bacea92cd4a97cc839df9533025400c343a4689fCédric Beust
7727ba4f0edf349cd33491ea94c9ccf88ba9e1fa117Cédric Beust      // Run invokedMethodListeners after updating TestResult
7737ba4f0edf349cd33491ea94c9ccf88ba9e1fa117Cédric Beust      runInvokedMethodListeners(AFTER_INVOCATION, invokedMethod, testResult);
7747ba4f0edf349cd33491ea94c9ccf88ba9e1fa117Cédric Beust      runTestListeners(testResult);
77534ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust      collectResults(tm, results, testResult);
776bacea92cd4a97cc839df9533025400c343a4689fCédric Beust
777f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
77845a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      // Invoke afterMethods only if
77945a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      // - lastTimeOnly is not set
78045a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      // - lastTimeOnly is set, and we are reaching the last invocationCount
781f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
78289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      invokeConfigurations(testClass, tm,
78345a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust          filterConfigurationMethods(tm, afterMethods, false /* beforeMethods */),
784facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust          suite, params, parameterValues,
7853297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust          instance,
786da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust          testResult);
78789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
788f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
78945a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      // Invoke afterGroups configurations
790f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
791f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      invokeAfterGroupsConfigurations(testClass, tm, groupMethods, suite,
7923297414dee4e2372259dd538dd359e0b65e9d305Cédric Beust          params, instance);
793f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
79494efdf8e6ac7332eadf8bfe5d1fe699caee5d051Cédric Beust
795f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return testResult;
796f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
79789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
79834ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust  private void collectResults(ITestNGMethod testMethod, List<ITestResult> results, TestResult testResult) {
79934ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust    for (int i = 0; i < results.size(); i++) {
80034ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust      // Collect the results
80134ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust      int status = results.get(i).getStatus();
80234ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust      if(ITestResult.SUCCESS == status) {
80334ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust        m_notifier.addPassedTest(testMethod, testResult);
80434ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust      }
80534ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust      else if(ITestResult.SKIP == status) {
80634ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust        m_notifier.addSkippedTest(testMethod, testResult);
80734ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust      }
80834ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust      else if(ITestResult.FAILURE == status) {
80934ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust        m_notifier.addFailedTest(testMethod, testResult);
81034ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust      }
81134ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust      else if(ITestResult.SUCCESS_PERCENTAGE_FAILURE == status) {
81234ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust        m_notifier.addFailedButWithinSuccessPercentageTest(testMethod, testResult);
81334ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust      }
81434ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust      else {
81534ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust        assert false : "UNKNOWN STATUS:" + status;
81634ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust      }
81734ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust    }
81834ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust  }
81934ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust
820f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
82145a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust   * The array of methods contains @BeforeMethods if isBefore if true, @AfterMethods
82245a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust   * otherwise.  This function removes all the methods that should not be run at this
82345a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust   * point because they are either firstTimeOnly or lastTimeOnly and we haven't reached
82445a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust   * the current invocationCount yet
82545a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust   */
82645a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust  private ITestNGMethod[] filterConfigurationMethods(ITestNGMethod tm,
82745a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      ITestNGMethod[] methods, boolean isBefore)
82845a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust  {
829ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust    List<ITestNGMethod> result = Lists.newArrayList();
83045a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust    for (ITestNGMethod m : methods) {
83145a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      ConfigurationMethod cm = (ConfigurationMethod) m;
83245a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      if (isBefore) {
83345a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust        if (! cm.isFirstTimeOnly() ||
83445a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust            (cm.isFirstTimeOnly() && tm.getCurrentInvocationCount() == 0))
83545a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust        {
83645a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust          result.add(m);
83745a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust        }
83845a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      }
83945a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      else {
840d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust        int current = tm.getCurrentInvocationCount();
841d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust        boolean isLast = false;
8422fc881781da9eb64b913650c8bb856d1f97c64cdCédric Beust        // If we have parameters, set the boolean if we are about to run
8432fc881781da9eb64b913650c8bb856d1f97c64cdCédric Beust        // the last invocation
844d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust        if (tm.getParameterInvocationCount() > 0) {
845d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust          isLast = current == tm.getParameterInvocationCount();
846d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust        }
8472fc881781da9eb64b913650c8bb856d1f97c64cdCédric Beust        // If we have invocationCount > 1, set the boolean if we are about to
8482fc881781da9eb64b913650c8bb856d1f97c64cdCédric Beust        // run the last invocation
849d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust        else if (tm.getInvocationCount() > 1) {
850d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust          isLast = current == tm.getInvocationCount();
851d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust        }
852d7e500014dc797345bc2e4f9ceb176fa225b8a37Cédric Beust        if (! cm.isLastTimeOnly() || (cm.isLastTimeOnly() && isLast)) {
85345a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust          result.add(m);
85445a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust        }
85545a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust      }
85645a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust    }
85745a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust
85845a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust    return result.toArray(new ITestNGMethod[result.size()]);
85945a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust  }
86045a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust
86145a161fb7f6ba0937ec480fef1a803524bc07214Cédric Beust  /**
86289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin   * {@link #invokeTestMethods()} eventually converge here to invoke a single @Test method.
863f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * <p/>
864f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * This method is responsible for actually invoking the method. It decides if the invocation
865f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * must be done:
866f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * <ul>
86789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin   * <li>through an <code>IHookable</code></li>
868f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * <li>directly (through reflection)</li>
869f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * <li>in a separate thread (in case it needs to timeout)
870f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * </ul>
87189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin   *
872f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * <p/>
873f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * This method is also reponsible for invoking @BeforeGroup, @BeforeMethod, @AfterMethod, @AfterGroup
874f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * if it is the case for the passed in @Test method.
875f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
87621dad3370294d6595fdddc3faf55792f60a913f1nullin  protected List<ITestResult> invokeTestMethod(Object[] instances,
877f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             final ITestNGMethod tm,
878f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             Object[] parameterValues,
879927a6d8a655520943e3a8a9ea9f09cbfe56f2ae6Cédric Beust                                             int parametersIndex,
880f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             XmlSuite suite,
881f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             Map<String, String> params,
882f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             ITestClass testClass,
883f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             ITestNGMethod[] beforeMethods,
884f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             ITestNGMethod[] afterMethods,
885f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             ConfigurationGroupMethods groupMethods)
886f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
887ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust    List<ITestResult> results = Lists.newArrayList();
888f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
889f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Mark this method with the current thread id
890f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    tm.setId(ThreadUtil.currentThreadInfo());
891f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
892f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for(int i= 0; i < instances.length; i++) {
893927a6d8a655520943e3a8a9ea9f09cbfe56f2ae6Cédric Beust      results.add(invokeMethod(instances, i, tm, parameterValues, parametersIndex, suite, params,
89494efdf8e6ac7332eadf8bfe5d1fe699caee5d051Cédric Beust          testClass, beforeMethods, afterMethods, groupMethods));
895f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
896f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
897f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return results;
898f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
899f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
900f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
901f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * Filter all the beforeGroups methods and invoke only those that apply
902f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * to the current test method
903f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
90489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin  private void invokeBeforeGroupsConfigurations(ITestClass testClass,
90589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                ITestNGMethod currentTestMethod,
90689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                ConfigurationGroupMethods groupMethods,
90789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                XmlSuite suite,
90889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                Map<String, String> params,
90989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                Object instance)
910f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
911f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    synchronized(groupMethods) {
912ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust      List<ITestNGMethod> filteredMethods = Lists.newArrayList();
913f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      String[] groups = currentTestMethod.getGroups();
914f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Map<String, List<ITestNGMethod>> beforeGroupMap = groupMethods.getBeforeGroupsMap();
91589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
916f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for (String group : groups) {
917f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        List<ITestNGMethod> methods = beforeGroupMap.get(group);
918f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if (methods != null) {
919f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          filteredMethods.addAll(methods);
920f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
921f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
92289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
923f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      ITestNGMethod[] beforeMethodsArray = filteredMethods.toArray(new ITestNGMethod[filteredMethods.size()]);
924f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
925f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // Invoke the right groups methods
926f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
927f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if(beforeMethodsArray.length > 0) {
928f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // don't pass the IClass or the instance as the method may be external
929f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // the invocation must be similar to @BeforeTest/@BeforeSuite
93089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin        invokeConfigurations(null, beforeMethodsArray, suite, params,
931facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust            null, /* no parameter values */
932facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust            null);
933f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
93489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
935f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
936f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // Remove them so they don't get run again
937f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      //
938f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      groupMethods.removeBeforeGroups(groups);
939f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
940f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
941f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
94289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin  private void invokeAfterGroupsConfigurations(ITestClass testClass,
943f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                               ITestNGMethod currentTestMethod,
944f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                               ConfigurationGroupMethods groupMethods,
94589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                               XmlSuite suite,
94689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                               Map<String, String> params,
94789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                               Object instance)
948f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
949f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Skip this if the current method doesn't belong to any group
950f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // (only a method that belongs to a group can trigger the invocation
951f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // of afterGroups methods)
9520f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin    if (currentTestMethod.getGroups().length == 0) {
9530f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      return;
9540f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin    }
95589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
956f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // See if the currentMethod is the last method in any of the groups
957f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // it belongs to
9580f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beust    Map<String, String> filteredGroups = Maps.newHashMap();
959f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    String[] groups = currentTestMethod.getGroups();
960f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    synchronized(groupMethods) {
961f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for (String group : groups) {
962f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if (groupMethods.isLastMethodForGroup(group, currentTestMethod)) {
963f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          filteredGroups.put(group, group);
964f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
965f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
96689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
9670f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      if(filteredGroups.isEmpty()) {
9680f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        return;
9690f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      }
97089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
971f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // The list of afterMethods to run
9720f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beust      Map<ITestNGMethod, ITestNGMethod> afterMethods = Maps.newHashMap();
97389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
974f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // Now filteredGroups contains all the groups for which we need to run the afterGroups
975f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // method.  Find all the methods that correspond to these groups and invoke them.
976f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Map<String, List<ITestNGMethod>> map = groupMethods.getAfterGroupsMap();
977f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for (String g : filteredGroups.values()) {
978f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        List<ITestNGMethod> methods = map.get(g);
979f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // Note:  should put them in a map if we want to make sure the same afterGroups
980f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // doesn't get run twice
981f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if (methods != null) {
982f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          for (ITestNGMethod m : methods) {
983f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            afterMethods.put(m, m);
984f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
985f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
986f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
98789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
988f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // Got our afterMethods, invoke them
989f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      ITestNGMethod[] afterMethodsArray = afterMethods.keySet().toArray(new ITestNGMethod[afterMethods.size()]);
990f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // don't pass the IClass or the instance as the method may be external
991f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // the invocation must be similar to @BeforeTest/@BeforeSuite
99289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      invokeConfigurations(null, afterMethodsArray, suite, params,
993facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust          null, /* no parameter values */
994facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust          null);
995f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
996f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // Remove the groups so they don't get run again
99789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      groupMethods.removeAfterGroups(filteredGroups.keySet());
998f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
999f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1000f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1001f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private Object[] getParametersFromIndex(Iterator<Object[]> parametersValues, int index) {
1002f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    while (parametersValues.hasNext()) {
1003f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Object[] parameters = parametersValues.next();
1004f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1005f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if (index == 0) {
1006f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        return parameters;
1007f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1008f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      index--;
1009f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1010f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return null;
1011f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
101289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1013c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust  int retryFailed(Object[] instances,
1014f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           int instanceIndex,
1015f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           final ITestNGMethod tm,
1016f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           XmlSuite suite,
1017f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           ITestClass testClass,
1018f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           ITestNGMethod[] beforeMethods,
1019f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           ITestNGMethod[] afterMethods,
1020f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           ConfigurationGroupMethods groupMethods,
1021f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           List<ITestResult> result,
1022f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           int failureCount,
1023bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust                           ExpectedExceptionsHolder expectedExceptionHolder,
1024f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           ITestContext testContext,
1025f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           Map<String, String> parameters,
1026f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                           int parametersIndex) {
102792206009b23ecbbf29e5a0d20f6b095a552afcb8Cédric Beust    List<Object> failedInstances;
1028f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
102992206009b23ecbbf29e5a0d20f6b095a552afcb8Cédric Beust    do {
1030ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust      failedInstances = Lists.newArrayList();
10310f6db64c011bc71dcdb432d7d27730b04f5ef2c1Cédric Beust      Map<String, String> allParameters = Maps.newHashMap();
1032f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      /**
1033f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust       * TODO: This recreates all the parameters every time when we only need
1034f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust       * one specific set. Should optimize it by only recreating the set needed.
1035f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust       */
1036db04b1679d3367e54e61d7e6f8c225354e90081cCédric Beust      ParameterBag bag = createParameters(tm, parameters,
1037da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust          allParameters, null, suite, testContext, null /* fedInstance */, null /* testResult */);
1038c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust      Object[] parameterValues =
1039c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust          getParametersFromIndex(bag.parameterHolder.parameters, parametersIndex);
1040f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
104189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      result.add(invokeMethod(instances, instanceIndex, tm, parameterValues,parametersIndex, suite,
104294efdf8e6ac7332eadf8bfe5d1fe699caee5d051Cédric Beust          allParameters, testClass, beforeMethods, afterMethods, groupMethods));
1043f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      failureCount = handleInvocationResults(tm, result, failedInstances,
1044bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust          failureCount, expectedExceptionHolder, true, true /* collect results */);
1045f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1046f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    while (!failedInstances.isEmpty());
1047f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return failureCount;
1048f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
104989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1050db04b1679d3367e54e61d7e6f8c225354e90081cCédric Beust  private ParameterBag createParameters(ITestNGMethod testMethod,
1051f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                        Map<String, String> parameters,
1052f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                        Map<String, String> allParameterNames,
1053facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust                                        Object[] parameterValues,
1054f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                        XmlSuite suite,
10558b9443a6ada20a1e9f3852b715f3e789a0f8d490Cédric Beust                                        ITestContext testContext,
1056da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust                                        Object fedInstance,
1057da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust                                        ITestResult testResult)
10588778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust  {
10598778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust    Object instance;
10608778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust    if (fedInstance != null) {
10618778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust      instance = fedInstance;
10628778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust    }
10638778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust    else {
10647955b9d255852b83f9c96277dece4d6807cb69f5Cédric Beust      instance = testMethod.getInstance();
10658778efa4afcae00d4f8c645cc7ac5fcb32a71dd3Cédric Beust    }
106689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
106789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin    ParameterBag bag= handleParameters(testMethod,
1068da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust        instance, allParameterNames, parameters, parameterValues, suite, testContext, fedInstance,
1069da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust        testResult);
1070f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1071f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return bag;
1072f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
107389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1074f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1075eddb4a9423c14fee808a30e92ad77a16e88b320enullin   * Invoke all the test methods. Note the plural: the method passed in
1076f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * parameter might be invoked several times if the test class it belongs
1077f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * to has more than one instance (i.e., if an @Factory method has been
1078f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * declared somewhere that returns several instances of this TestClass).
1079f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * If no @Factory method was specified, testMethod will only be invoked
1080f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * once.
1081f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * <p/>
1082f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * Note that this method also takes care of invoking the beforeTestMethod
1083f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * and afterTestMethod, if any.
108489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin   *
108589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin   * Note (alex): this method can be refactored to use a SingleTestMethodWorker that
108689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin   * directly invokes
1087f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * {@link #invokeTestMethod(Object[], ITestNGMethod, Object[], XmlSuite, Map, ITestClass, ITestNGMethod[], ITestNGMethod[], ConfigurationGroupMethods)}
1088f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * and this would simplify the implementation (see how DataTestMethodWorker is used)
1089f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
1090423a12bc8666e263237e0ce8abcfb096eb72b55aCédric Beust  @Override
1091f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  public List<ITestResult> invokeTestMethods(ITestNGMethod testMethod,
1092f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             ITestNGMethod[] allTestMethods,
1093f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             int testMethodIndex,
1094f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             XmlSuite suite,
1095f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             Map<String, String> parameters,
1096f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             ConfigurationGroupMethods groupMethods,
1097f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             Object[] instances,
1098f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                             ITestContext testContext)
1099f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
1100f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Potential bug here if the test method was declared on a parent class
110189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin    assert null != testMethod.getTestClass()
1102f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    : "COULDN'T FIND TESTCLASS FOR " + testMethod.getMethod().getDeclaringClass();
110389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1104ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust    List<ITestResult> result = Lists.newArrayList();
110589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1106eddb4a9423c14fee808a30e92ad77a16e88b320enullin    if (!MethodHelper.isEnabled(testMethod.getMethod(), m_annotationFinder)) {
1107eddb4a9423c14fee808a30e92ad77a16e88b320enullin      /*
1108eddb4a9423c14fee808a30e92ad77a16e88b320enullin       * return if the method is not enabled. No need to do any more calculations
1109eddb4a9423c14fee808a30e92ad77a16e88b320enullin       */
1110eddb4a9423c14fee808a30e92ad77a16e88b320enullin      return result;
1111eddb4a9423c14fee808a30e92ad77a16e88b320enullin    }
1112eddb4a9423c14fee808a30e92ad77a16e88b320enullin
1113f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    ITestClass testClass= testMethod.getTestClass();
11140b2ac5eab08098da2c2b63d4a3f87ba72ad5d6a1nullin    long start = System.currentTimeMillis();
1115f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
11169150cdf3bacb4715cee345cd153d4f0ab3dbd198nullin    // For invocationCount > 1 and threadPoolSize > 1 the method will be invoked on a thread pool
1117331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust    long timeOutInvocationCount = testMethod.getInvocationTimeOut();
1118eddb4a9423c14fee808a30e92ad77a16e88b320enullin    //FIXME: Is this correct?
1119331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust    boolean onlyOne = testMethod.getThreadPoolSize() > 1 ||
1120331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust      timeOutInvocationCount > 0;
112189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1122331487029766f0e6623b8cd8078ec75aaec7de75Cédric Beust    int invocationCount = onlyOne ? 1 : testMethod.getInvocationCount();
1123f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    int failureCount = 0;
1124f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
112589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin    ExpectedExceptionsHolder expectedExceptionHolder =
1126f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        MethodHelper.findExpectedExceptions(m_annotationFinder, testMethod.getMethod());
1127f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    while(invocationCount-- > 0) {
1128e934f66fb4fb247ebf5fec45770bc6820fbba29anullin      boolean okToProceed = checkDependencies(testMethod, allTestMethods);
1129f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1130eddb4a9423c14fee808a30e92ad77a16e88b320enullin      if (!okToProceed) {
1131f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        //
1132eddb4a9423c14fee808a30e92ad77a16e88b320enullin        // Not okToProceed. Test is being skipped
1133f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        //
1134eddb4a9423c14fee808a30e92ad77a16e88b320enullin        ITestResult testResult = new TestResult(testClass, null /* instance */,
1135f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                               testMethod,
1136eddb4a9423c14fee808a30e92ad77a16e88b320enullin                                               null /* cause */,
1137f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                               start,
11386f53a2551bab7c2f5a85c6f5ede755512e490a4bBrandon Pedersen                                               System.currentTimeMillis(),
11396f53a2551bab7c2f5a85c6f5ede755512e490a4bBrandon Pedersen                                               m_testContext);
1140f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        String missingGroup = testMethod.getMissingGroup();
1141f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if (missingGroup != null) {
114289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin          testResult.setThrowable(new Throwable("Method " + testMethod
1143f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              + " depends on nonexistent group \"" + missingGroup + "\""));
1144f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1145f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1146f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        testResult.setStatus(ITestResult.SKIP);
1147a4e6892fbfa21c968737eaf4e4f1e4b0b7f9163eCédric Beust        result.add(testResult);
1148676b37b4af4a4eeeb0d858f0ff577c0a1d549b83Cédric Beust        m_notifier.addSkippedTest(testMethod, testResult);
1149f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        runTestListeners(testResult);
1150eddb4a9423c14fee808a30e92ad77a16e88b320enullin        return result;
1151eddb4a9423c14fee808a30e92ad77a16e88b320enullin      }
1152eddb4a9423c14fee808a30e92ad77a16e88b320enullin
1153eddb4a9423c14fee808a30e92ad77a16e88b320enullin      //
1154eddb4a9423c14fee808a30e92ad77a16e88b320enullin      // If threadPoolSize specified, run this method in its own pool thread.
1155eddb4a9423c14fee808a30e92ad77a16e88b320enullin      //
1156eddb4a9423c14fee808a30e92ad77a16e88b320enullin      if (testMethod.getThreadPoolSize() > 1 && testMethod.getInvocationCount() > 1) {
1157eddb4a9423c14fee808a30e92ad77a16e88b320enullin          return invokePooledTestMethods(testMethod, allTestMethods, suite,
1158eddb4a9423c14fee808a30e92ad77a16e88b320enullin              parameters, groupMethods, testContext);
1159eddb4a9423c14fee808a30e92ad77a16e88b320enullin      }
1160eddb4a9423c14fee808a30e92ad77a16e88b320enullin      //
1161eddb4a9423c14fee808a30e92ad77a16e88b320enullin      // No threads, regular invocation
1162eddb4a9423c14fee808a30e92ad77a16e88b320enullin      //
1163eddb4a9423c14fee808a30e92ad77a16e88b320enullin      else {
11649d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust        ITestNGMethod[] beforeMethods = filterMethods(testClass, testClass.getBeforeTestMethods(),
11659d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust            CAN_RUN_FROM_CLASS);
11669d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust        ITestNGMethod[] afterMethods = filterMethods(testClass, testClass.getAfterTestMethods(),
11679d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust            CAN_RUN_FROM_CLASS);
1168eddb4a9423c14fee808a30e92ad77a16e88b320enullin
1169eddb4a9423c14fee808a30e92ad77a16e88b320enullin        Map<String, String> allParameterNames = Maps.newHashMap();
1170db04b1679d3367e54e61d7e6f8c225354e90081cCédric Beust        ParameterBag bag = createParameters(testMethod,
1171eddb4a9423c14fee808a30e92ad77a16e88b320enullin            parameters, allParameterNames, null, suite, testContext, instances[0],
1172eddb4a9423c14fee808a30e92ad77a16e88b320enullin            null);
1173eddb4a9423c14fee808a30e92ad77a16e88b320enullin
1174eddb4a9423c14fee808a30e92ad77a16e88b320enullin        if (bag.hasErrors()) {
1175eddb4a9423c14fee808a30e92ad77a16e88b320enullin          failureCount = handleInvocationResults(testMethod,
1176eddb4a9423c14fee808a30e92ad77a16e88b320enullin              bag.errorResults, null, failureCount, expectedExceptionHolder, true,
1177eddb4a9423c14fee808a30e92ad77a16e88b320enullin              true /* collect results */);
1178fe08327fabe1654f4f509edcf28c3296ad054fc5Cédric Beust          ITestResult tr = registerSkippedTestResult(testMethod, instances[0], start,
1179fe08327fabe1654f4f509edcf28c3296ad054fc5Cédric Beust              bag.errorResults.get(0).getThrowable());
1180061a9ae01a09d45e337c69b64d1b5a81ebee3868Cédric Beust          result.add(tr);
1181eddb4a9423c14fee808a30e92ad77a16e88b320enullin          continue;
1182eddb4a9423c14fee808a30e92ad77a16e88b320enullin        }
1183eddb4a9423c14fee808a30e92ad77a16e88b320enullin
1184eddb4a9423c14fee808a30e92ad77a16e88b320enullin        Iterator<Object[]> allParameterValues = bag.parameterHolder.parameters;
1185eddb4a9423c14fee808a30e92ad77a16e88b320enullin        int parametersIndex = 0;
1186eddb4a9423c14fee808a30e92ad77a16e88b320enullin
1187eddb4a9423c14fee808a30e92ad77a16e88b320enullin        try {
1188eddb4a9423c14fee808a30e92ad77a16e88b320enullin          List<TestMethodWithDataProviderMethodWorker> workers = Lists.newArrayList();
1189eddb4a9423c14fee808a30e92ad77a16e88b320enullin
1190eddb4a9423c14fee808a30e92ad77a16e88b320enullin          if (bag.parameterHolder.origin == ParameterOrigin.ORIGIN_DATA_PROVIDER &&
1191eddb4a9423c14fee808a30e92ad77a16e88b320enullin              bag.parameterHolder.dataProviderHolder.annotation.isParallel()) {
1192eddb4a9423c14fee808a30e92ad77a16e88b320enullin            while (allParameterValues.hasNext()) {
1193eddb4a9423c14fee808a30e92ad77a16e88b320enullin              Object[] parameterValues = injectParameters(allParameterValues.next(),
1194eddb4a9423c14fee808a30e92ad77a16e88b320enullin                  testMethod.getMethod(), testContext, null /* test result */);
1195eddb4a9423c14fee808a30e92ad77a16e88b320enullin              TestMethodWithDataProviderMethodWorker w =
1196eddb4a9423c14fee808a30e92ad77a16e88b320enullin                new TestMethodWithDataProviderMethodWorker(this,
1197eddb4a9423c14fee808a30e92ad77a16e88b320enullin                    testMethod, parametersIndex,
1198eddb4a9423c14fee808a30e92ad77a16e88b320enullin                    parameterValues, instances, suite, parameters, testClass,
1199eddb4a9423c14fee808a30e92ad77a16e88b320enullin                    beforeMethods, afterMethods, groupMethods,
1200eddb4a9423c14fee808a30e92ad77a16e88b320enullin                    expectedExceptionHolder, testContext, m_skipFailedInvocationCounts,
1201eddb4a9423c14fee808a30e92ad77a16e88b320enullin                    invocationCount, failureCount, m_notifier);
1202eddb4a9423c14fee808a30e92ad77a16e88b320enullin              workers.add(w);
1203eddb4a9423c14fee808a30e92ad77a16e88b320enullin              // testng387: increment the param index in the bag.
1204eddb4a9423c14fee808a30e92ad77a16e88b320enullin              parametersIndex++;
1205eddb4a9423c14fee808a30e92ad77a16e88b320enullin            }
1206eddb4a9423c14fee808a30e92ad77a16e88b320enullin            PoolService ps = PoolService.getInstance();
1207eddb4a9423c14fee808a30e92ad77a16e88b320enullin            List<ITestResult> r = ps.submitTasksAndWait(testMethod, workers);
1208eddb4a9423c14fee808a30e92ad77a16e88b320enullin            result.addAll(r);
1209eddb4a9423c14fee808a30e92ad77a16e88b320enullin
1210eddb4a9423c14fee808a30e92ad77a16e88b320enullin          } else {
1211eddb4a9423c14fee808a30e92ad77a16e88b320enullin            while (allParameterValues.hasNext()) {
1212eddb4a9423c14fee808a30e92ad77a16e88b320enullin              Object[] parameterValues = injectParameters(allParameterValues.next(),
1213eddb4a9423c14fee808a30e92ad77a16e88b320enullin                  testMethod.getMethod(), testContext, null /* test result */);
1214eddb4a9423c14fee808a30e92ad77a16e88b320enullin
1215eddb4a9423c14fee808a30e92ad77a16e88b320enullin              List<ITestResult> tmpResults = Lists.newArrayList();
1216eddb4a9423c14fee808a30e92ad77a16e88b320enullin
1217eddb4a9423c14fee808a30e92ad77a16e88b320enullin              try {
1218eddb4a9423c14fee808a30e92ad77a16e88b320enullin                tmpResults.addAll(invokeTestMethod(instances,
1219eddb4a9423c14fee808a30e92ad77a16e88b320enullin                                                   testMethod,
1220eddb4a9423c14fee808a30e92ad77a16e88b320enullin                                                   parameterValues,
1221eddb4a9423c14fee808a30e92ad77a16e88b320enullin                                                   parametersIndex,
1222eddb4a9423c14fee808a30e92ad77a16e88b320enullin                                                   suite,
1223eddb4a9423c14fee808a30e92ad77a16e88b320enullin                                                   parameters,
1224eddb4a9423c14fee808a30e92ad77a16e88b320enullin                                                   testClass,
1225eddb4a9423c14fee808a30e92ad77a16e88b320enullin                                                   beforeMethods,
1226eddb4a9423c14fee808a30e92ad77a16e88b320enullin                                                   afterMethods,
1227eddb4a9423c14fee808a30e92ad77a16e88b320enullin                                                   groupMethods));
1228eddb4a9423c14fee808a30e92ad77a16e88b320enullin              }
1229eddb4a9423c14fee808a30e92ad77a16e88b320enullin              finally {
1230eddb4a9423c14fee808a30e92ad77a16e88b320enullin                List<Object> failedInstances = Lists.newArrayList();
1231eddb4a9423c14fee808a30e92ad77a16e88b320enullin
1232eddb4a9423c14fee808a30e92ad77a16e88b320enullin                failureCount = handleInvocationResults(testMethod, tmpResults,
1233eddb4a9423c14fee808a30e92ad77a16e88b320enullin                    failedInstances, failureCount, expectedExceptionHolder, true,
1234eddb4a9423c14fee808a30e92ad77a16e88b320enullin                    false /* don't collect results */);
1235eddb4a9423c14fee808a30e92ad77a16e88b320enullin                if (failedInstances.isEmpty()) {
1236eddb4a9423c14fee808a30e92ad77a16e88b320enullin                  result.addAll(tmpResults);
1237eddb4a9423c14fee808a30e92ad77a16e88b320enullin                } else {
1238eddb4a9423c14fee808a30e92ad77a16e88b320enullin                  for (int i = 0; i < failedInstances.size(); i++) {
1239eddb4a9423c14fee808a30e92ad77a16e88b320enullin                    List<ITestResult> retryResults = Lists.newArrayList();
1240eddb4a9423c14fee808a30e92ad77a16e88b320enullin
1241eddb4a9423c14fee808a30e92ad77a16e88b320enullin                    failureCount =
1242eddb4a9423c14fee808a30e92ad77a16e88b320enullin                     retryFailed(failedInstances.toArray(),
1243eddb4a9423c14fee808a30e92ad77a16e88b320enullin                     i, testMethod, suite, testClass, beforeMethods,
1244eddb4a9423c14fee808a30e92ad77a16e88b320enullin                     afterMethods, groupMethods, retryResults,
1245eddb4a9423c14fee808a30e92ad77a16e88b320enullin                     failureCount, expectedExceptionHolder,
1246eddb4a9423c14fee808a30e92ad77a16e88b320enullin                     testContext, parameters, parametersIndex);
1247eddb4a9423c14fee808a30e92ad77a16e88b320enullin                  result.addAll(retryResults);
1248eddb4a9423c14fee808a30e92ad77a16e88b320enullin                  }
1249eddb4a9423c14fee808a30e92ad77a16e88b320enullin                }
1250eddb4a9423c14fee808a30e92ad77a16e88b320enullin
1251eddb4a9423c14fee808a30e92ad77a16e88b320enullin                //
1252eddb4a9423c14fee808a30e92ad77a16e88b320enullin                // If we have a failure, skip all the
1253eddb4a9423c14fee808a30e92ad77a16e88b320enullin                // other invocationCounts
1254eddb4a9423c14fee808a30e92ad77a16e88b320enullin                //
1255eddb4a9423c14fee808a30e92ad77a16e88b320enullin                if (failureCount > 0
1256eddb4a9423c14fee808a30e92ad77a16e88b320enullin                      && (m_skipFailedInvocationCounts
1257eddb4a9423c14fee808a30e92ad77a16e88b320enullin                            || testMethod.skipFailedInvocations())) {
1258eddb4a9423c14fee808a30e92ad77a16e88b320enullin                  while (invocationCount-- > 0) {
1259fe08327fabe1654f4f509edcf28c3296ad054fc5Cédric Beust                    result.add(registerSkippedTestResult(testMethod, instances[0], start, null));
1260eddb4a9423c14fee808a30e92ad77a16e88b320enullin                  }
1261eddb4a9423c14fee808a30e92ad77a16e88b320enullin                  break;
1262eddb4a9423c14fee808a30e92ad77a16e88b320enullin                }
1263eddb4a9423c14fee808a30e92ad77a16e88b320enullin              }// end finally
1264eddb4a9423c14fee808a30e92ad77a16e88b320enullin              parametersIndex++;
1265eddb4a9423c14fee808a30e92ad77a16e88b320enullin            }
1266eddb4a9423c14fee808a30e92ad77a16e88b320enullin          }
1267eddb4a9423c14fee808a30e92ad77a16e88b320enullin        }
1268eddb4a9423c14fee808a30e92ad77a16e88b320enullin        catch (Throwable cause) {
1269eddb4a9423c14fee808a30e92ad77a16e88b320enullin          ITestResult r =
1270eddb4a9423c14fee808a30e92ad77a16e88b320enullin              new TestResult(testMethod.getTestClass(),
1271eddb4a9423c14fee808a30e92ad77a16e88b320enullin                instances[0],
1272eddb4a9423c14fee808a30e92ad77a16e88b320enullin                testMethod,
1273eddb4a9423c14fee808a30e92ad77a16e88b320enullin                cause,
1274eddb4a9423c14fee808a30e92ad77a16e88b320enullin                start,
12756f53a2551bab7c2f5a85c6f5ede755512e490a4bBrandon Pedersen                System.currentTimeMillis(),
12766f53a2551bab7c2f5a85c6f5ede755512e490a4bBrandon Pedersen                m_testContext);
1277eddb4a9423c14fee808a30e92ad77a16e88b320enullin            r.setStatus(TestResult.FAILURE);
1278eddb4a9423c14fee808a30e92ad77a16e88b320enullin            result.add(r);
1279eddb4a9423c14fee808a30e92ad77a16e88b320enullin            runTestListeners(r);
1280eddb4a9423c14fee808a30e92ad77a16e88b320enullin            m_notifier.addFailedTest(testMethod, r);
1281eddb4a9423c14fee808a30e92ad77a16e88b320enullin        } // catch
1282f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1283f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
128489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1285f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return result;
128689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1287f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  } // invokeTestMethod
1288f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1289252c45802df7624a4fafbce810e05d22048f437bCédric Beust  private ITestResult registerSkippedTestResult(ITestNGMethod testMethod, Object instance,
1290fe08327fabe1654f4f509edcf28c3296ad054fc5Cédric Beust      long start, Throwable throwable) {
129189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin    ITestResult result =
1292252c45802df7624a4fafbce810e05d22048f437bCédric Beust      new TestResult(testMethod.getTestClass(),
1293252c45802df7624a4fafbce810e05d22048f437bCédric Beust        instance,
1294252c45802df7624a4fafbce810e05d22048f437bCédric Beust        testMethod,
1295fe08327fabe1654f4f509edcf28c3296ad054fc5Cédric Beust        throwable,
1296252c45802df7624a4fafbce810e05d22048f437bCédric Beust        start,
12976f53a2551bab7c2f5a85c6f5ede755512e490a4bBrandon Pedersen        System.currentTimeMillis(),
12986f53a2551bab7c2f5a85c6f5ede755512e490a4bBrandon Pedersen        m_testContext);
1299252c45802df7624a4fafbce810e05d22048f437bCédric Beust    result.setStatus(TestResult.SKIP);
1300252c45802df7624a4fafbce810e05d22048f437bCédric Beust    runTestListeners(result);
1301252c45802df7624a4fafbce810e05d22048f437bCédric Beust
1302252c45802df7624a4fafbce810e05d22048f437bCédric Beust    return result;
1303252c45802df7624a4fafbce810e05d22048f437bCédric Beust  }
1304252c45802df7624a4fafbce810e05d22048f437bCédric Beust
130528e899a6c1620c8d07cb04a92f96658550e4af16nullin  /**
130628e899a6c1620c8d07cb04a92f96658550e4af16nullin   * Gets an array of parameter values returned by data provider or the ones that
130728e899a6c1620c8d07cb04a92f96658550e4af16nullin   * are injected based on parameter type. The method also checks for {@code NoInjection}
130828e899a6c1620c8d07cb04a92f96658550e4af16nullin   * annotation
130928e899a6c1620c8d07cb04a92f96658550e4af16nullin   * @param parameterValues parameter values from a data provider
131028e899a6c1620c8d07cb04a92f96658550e4af16nullin   * @param method method to be invoked
131128e899a6c1620c8d07cb04a92f96658550e4af16nullin   * @param context test context
131228e899a6c1620c8d07cb04a92f96658550e4af16nullin   * @param testResult test result
131328e899a6c1620c8d07cb04a92f96658550e4af16nullin   * @return
131428e899a6c1620c8d07cb04a92f96658550e4af16nullin   */
13151e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust  private Object[] injectParameters(Object[] parameterValues, Method method,
131628e899a6c1620c8d07cb04a92f96658550e4af16nullin      ITestContext context, ITestResult testResult)
131728e899a6c1620c8d07cb04a92f96658550e4af16nullin    throws TestNGException {
13181e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust    List<Object> vResult = Lists.newArrayList();
13191e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust    int i = 0;
132028e899a6c1620c8d07cb04a92f96658550e4af16nullin    int numValues = parameterValues.length;
132128e899a6c1620c8d07cb04a92f96658550e4af16nullin    int numParams = method.getParameterTypes().length;
132228e899a6c1620c8d07cb04a92f96658550e4af16nullin
13238211ccc6e66d114d50826b44f06b8e1d42f7811aCédric Beust    if (numValues > numParams && ! method.isVarArgs()) {
13248211ccc6e66d114d50826b44f06b8e1d42f7811aCédric Beust      throw new TestNGException("The data provider is trying to pass " + numValues
13258211ccc6e66d114d50826b44f06b8e1d42f7811aCédric Beust          + " parameters but the method "
13268211ccc6e66d114d50826b44f06b8e1d42f7811aCédric Beust          + method.getDeclaringClass().getName() + "#" + method.getName()
13278211ccc6e66d114d50826b44f06b8e1d42f7811aCédric Beust          + " takes " + numParams);
132828e899a6c1620c8d07cb04a92f96658550e4af16nullin    }
132928e899a6c1620c8d07cb04a92f96658550e4af16nullin
133028e899a6c1620c8d07cb04a92f96658550e4af16nullin    // beyond this, numValues <= numParams
13311e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust    for (Class<?> cls : method.getParameterTypes()) {
1332aba3ac2f9fc3e370339b911598f62c7ffb6752aaCédric Beust      Annotation[] annotations = method.getParameterAnnotations()[i];
1333aba3ac2f9fc3e370339b911598f62c7ffb6752aaCédric Beust      boolean noInjection = false;
1334aba3ac2f9fc3e370339b911598f62c7ffb6752aaCédric Beust      for (Annotation a : annotations) {
1335aba3ac2f9fc3e370339b911598f62c7ffb6752aaCédric Beust        if (a instanceof NoInjection) {
1336aba3ac2f9fc3e370339b911598f62c7ffb6752aaCédric Beust          noInjection = true;
1337aba3ac2f9fc3e370339b911598f62c7ffb6752aaCédric Beust          break;
1338aba3ac2f9fc3e370339b911598f62c7ffb6752aaCédric Beust        }
1339aba3ac2f9fc3e370339b911598f62c7ffb6752aaCédric Beust      }
13401e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust      Object injected = Parameters.getInjectedParameter(cls, method, context, testResult);
1341aba3ac2f9fc3e370339b911598f62c7ffb6752aaCédric Beust      if (injected != null && ! noInjection) {
13421e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust        vResult.add(injected);
13431e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust      } else {
134428e899a6c1620c8d07cb04a92f96658550e4af16nullin        try {
1345e7405399f36ed7b9383424f5175980fe2698a403Cédric Beust          if (method.isVarArgs()) vResult.add(parameterValues);
1346e7405399f36ed7b9383424f5175980fe2698a403Cédric Beust          else vResult.add(parameterValues[i++]);
134728e899a6c1620c8d07cb04a92f96658550e4af16nullin        } catch (ArrayIndexOutOfBoundsException ex) {
13488211ccc6e66d114d50826b44f06b8e1d42f7811aCédric Beust          throw new TestNGException("The data provider is trying to pass " + numValues
13498211ccc6e66d114d50826b44f06b8e1d42f7811aCédric Beust              + " parameters but the method "
13508211ccc6e66d114d50826b44f06b8e1d42f7811aCédric Beust              + method.getDeclaringClass().getName() + "#" + method.getName()
13518211ccc6e66d114d50826b44f06b8e1d42f7811aCédric Beust              + " takes " + numParams
13528211ccc6e66d114d50826b44f06b8e1d42f7811aCédric Beust              + " and TestNG is unable in inject a suitable object", ex);
135328e899a6c1620c8d07cb04a92f96658550e4af16nullin        }
13541e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust      }
13551e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust    }
13561e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust    return vResult.toArray(new Object[vResult.size()]);
13571e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust  }
13581e15cc3fecfaea9149afe8124d2fd95f4356c193Cédric Beust
1359f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private ParameterBag handleParameters(ITestNGMethod testMethod,
1360f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Object instance,
1361f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Map<String, String> allParameterNames,
1362f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Map<String, String> parameters,
1363facba56b6ead0cb76ba78ac1cfeae1bbe851ad9cCédric Beust      Object[] parameterValues,
1364f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      XmlSuite suite,
13658b9443a6ada20a1e9f3852b715f3e789a0f8d490Cédric Beust      ITestContext testContext,
1366da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust      Object fedInstance,
1367da4f4527ccc23d7a7d777627332b6c7332266a16Cédric Beust      ITestResult testResult)
1368f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
1369f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    try {
1370c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust      return new ParameterBag(
1371c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust          Parameters.handleParameters(testMethod,
137289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin            allParameterNames,
137389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin            instance,
137466aec6c16d8782f01933c0b45e1c5b3976e04dd6Cédric Beust            new Parameters.MethodParameters(parameters,
137566aec6c16d8782f01933c0b45e1c5b3976e04dd6Cédric Beust                testMethod.findMethodParameters(testContext.getCurrentXmlTest()),
137666aec6c16d8782f01933c0b45e1c5b3976e04dd6Cédric Beust                parameterValues,
137789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                testMethod.getMethod(), testContext, testResult),
137889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin            suite,
1379c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust            m_annotationFinder,
138089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin            fedInstance),
1381eddb4a9423c14fee808a30e92ad77a16e88b320enullin          null /* TestResult */);
1382f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1383061a9ae01a09d45e337c69b64d1b5a81ebee3868Cédric Beust//    catch(TestNGException ex) {
1384061a9ae01a09d45e337c69b64d1b5a81ebee3868Cédric Beust//      throw ex;
1385061a9ae01a09d45e337c69b64d1b5a81ebee3868Cédric Beust//    }
1386f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    catch(Throwable cause) {
1387eddb4a9423c14fee808a30e92ad77a16e88b320enullin      return new ParameterBag(null /* ParameterHolder */,
1388f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          new TestResult(
138989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin              testMethod.getTestClass(),
139089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin              instance,
139189fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin              testMethod,
139289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin              cause,
1393f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              System.currentTimeMillis(),
13946f53a2551bab7c2f5a85c6f5ede755512e490a4bBrandon Pedersen              System.currentTimeMillis(),
13956f53a2551bab7c2f5a85c6f5ede755512e490a4bBrandon Pedersen              m_testContext));
1396f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1397f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
139889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1399f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
140089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin   * Invokes a method that has a specified threadPoolSize.
1401f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
140289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin  private List<ITestResult> invokePooledTestMethods(ITestNGMethod testMethod,
140389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                    ITestNGMethod[] allTestMethods,
140489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                    XmlSuite suite,
140589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                    Map<String, String> parameters,
1406f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                                    ConfigurationGroupMethods groupMethods,
140789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                                    ITestContext testContext)
1408f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
1409f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
1410f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Create the workers
1411f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
1412f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin    List<IWorker<ITestNGMethod>> workers = Lists.newArrayList();
141389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
14149d65d102f64e4fe2e629de8e87c8b92379a9349eCédric Beust    // Create one worker per invocationCount
1415f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for (int i = 0; i < testMethod.getInvocationCount(); i++) {
1416f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // we use clones for reporting purposes
1417f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      ITestNGMethod clonedMethod= testMethod.clone();
1418f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      clonedMethod.setInvocationCount(1);
1419f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      clonedMethod.setThreadPoolSize(1);
1420f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1421eb2b9ac857aad415986677a51513d47e91eb7c8dCédric Beust      MethodInstance mi = new MethodInstance(clonedMethod);
1422f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      workers.add(new SingleTestMethodWorker(this,
1423f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          mi,
142489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin          suite,
1425f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          parameters,
1426f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          allTestMethods,
1427f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          testContext));
1428f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1429f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1430f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return runWorkers(testMethod, workers, testMethod.getThreadPoolSize(), groupMethods, suite, parameters);
1431f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
143289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1433f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1434f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param testMethod
1435f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param result
1436f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param failureCount
1437bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust   * @param expectedExceptionsHolder
1438f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return
1439f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
144089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin  int handleInvocationResults(ITestNGMethod testMethod,
1441f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                      List<ITestResult> result,
1442f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                                      List<Object> failedInstances,
144389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                                      int failureCount,
1444bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust                                      ExpectedExceptionsHolder expectedExceptionsHolder,
14456216d78ae0757b7d57aa6e94cc041447d610724dCédric Beust                                      boolean triggerListeners,
14466216d78ae0757b7d57aa6e94cc041447d610724dCédric Beust                                      boolean collectResults)
14476216d78ae0757b7d57aa6e94cc041447d610724dCédric Beust  {
1448f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
1449f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Go through all the results and create a TestResult for each of them
1450f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
1451ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust    List<ITestResult> resultsToRetry = Lists.newArrayList();
1452f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1453f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for (int i = 0; i < result.size(); i++) {
1454f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      ITestResult testResult = result.get(i);
1455f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Throwable ite= testResult.getThrowable();
1456f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      int status= testResult.getStatus();
1457f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1458f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // Exception thrown?
14594c02d89d66fe0319dd20083e705addd6b5f3e8cdCédric Beust      if (ite != null) {
1460f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1461f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        //  Invocation caused an exception, see if the method was annotated with @ExpectedException
1462bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust        if (isExpectedException(ite, expectedExceptionsHolder)) {
1463bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust          if (messageRegExpMatches(expectedExceptionsHolder.messageRegExp, ite)) {
1464bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust            testResult.setStatus(ITestResult.SUCCESS);
1465bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust            status= ITestResult.SUCCESS;
1466bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust          }
1467bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust          else {
1468bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust            testResult.setThrowable(
1469bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust                new TestException("The exception was thrown with the wrong message:" +
147089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin                    " expected \"" + expectedExceptionsHolder.messageRegExp + "\"" +
1471fa37eadd5874782d0020b1df413489b0514888b5Cédric Beust                    " but got \"" + ite.getMessage() + "\"", ite));
1472bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust            status= ITestResult.FAILURE;
1473bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust          }
14742343cba1dccc30a50322215da78f14179e2a0271Cédric Beust        } else if (SkipException.class.isAssignableFrom(ite.getClass())){
1475f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          SkipException skipEx= (SkipException) ite;
1476f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          if(skipEx.isSkip()) {
14774c02d89d66fe0319dd20083e705addd6b5f3e8cdCédric Beust            status = ITestResult.SKIP;
1478f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
1479f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          else {
1480f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust            handleException(ite, testMethod, testResult, failureCount++);
14814c02d89d66fe0319dd20083e705addd6b5f3e8cdCédric Beust            status = ITestResult.FAILURE;
1482f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
14832343cba1dccc30a50322215da78f14179e2a0271Cédric Beust        } else if (ite != null && expectedExceptionsHolder != null) {
14842343cba1dccc30a50322215da78f14179e2a0271Cédric Beust          testResult.setThrowable(
14852343cba1dccc30a50322215da78f14179e2a0271Cédric Beust              new TestException("Expected exception "
14862343cba1dccc30a50322215da78f14179e2a0271Cédric Beust                 + expectedExceptionsHolder.expectedClasses[0].getName()
14872343cba1dccc30a50322215da78f14179e2a0271Cédric Beust                 + " but got " + ite, ite));
14882343cba1dccc30a50322215da78f14179e2a0271Cédric Beust          status= ITestResult.FAILURE;
14892343cba1dccc30a50322215da78f14179e2a0271Cédric Beust        } else {
1490f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          handleException(ite, testMethod, testResult, failureCount++);
1491f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          status= testResult.getStatus();
1492f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1493f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1494f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1495f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // No exception thrown, make sure we weren't expecting one
1496bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust      else if(status != ITestResult.SKIP && expectedExceptionsHolder != null) {
1497bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust        Class<?>[] classes = expectedExceptionsHolder.expectedClasses;
1498bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust        if (classes != null && classes.length > 0) {
1499f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          testResult.setThrowable(
150027e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust              new TestException("Method " + testMethod + " should have thrown an exception of "
150127e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust                  + expectedExceptionsHolder.expectedClasses[0]));
1502f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          status= ITestResult.FAILURE;
1503f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1504f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1505f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1506f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      testResult.setStatus(status);
1507f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1508f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      boolean retry = false;
150989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1510f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if (testResult.getStatus() == ITestResult.FAILURE) {
1511f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        IRetryAnalyzer retryAnalyzer = testMethod.getRetryAnalyzer();
1512f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
15139ae4e70bde40b32777755f9294a5b1b06b420005Cédric Beust        if (retryAnalyzer != null && failedInstances != null) {
1514f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          retry = retryAnalyzer.retry(testResult);
1515f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1516f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1517f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if (retry) {
1518f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          resultsToRetry.add(testResult);
1519f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          if (failedInstances != null) {
15209ae4e70bde40b32777755f9294a5b1b06b420005Cédric Beust            failedInstances.add(testResult.getInstance());
1521f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          }
1522f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
152389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      }
152434ce5b443d17bd8cfeb7fd591755bf50258ddd69Cédric Beust      if (collectResults) {
1525f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        // Collect the results
1526f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if(ITestResult.SUCCESS == status) {
1527f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          m_notifier.addPassedTest(testMethod, testResult);
1528f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1529f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        else if(ITestResult.SKIP == status) {
1530f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          m_notifier.addSkippedTest(testMethod, testResult);
1531f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1532f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        else if(ITestResult.FAILURE == status) {
1533f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          m_notifier.addFailedTest(testMethod, testResult);
1534f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1535f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        else if(ITestResult.SUCCESS_PERCENTAGE_FAILURE == status) {
1536f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          m_notifier.addFailedButWithinSuccessPercentageTest(testMethod, testResult);
1537f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1538f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        else {
1539f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          assert false : "UNKNOWN STATUS:" + status;
1540f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
15417e735d9079026e11bc7cd06dab2b99d9ff9cd6c3Cédric Beust//        if (triggerListeners && status != ITestResult.SUCCESS) {
15427e735d9079026e11bc7cd06dab2b99d9ff9cd6c3Cédric Beust//          runTestListeners(testResult);
15437e735d9079026e11bc7cd06dab2b99d9ff9cd6c3Cédric Beust//        }
1544f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1545f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    } // for results
154689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1547f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return removeResultsToRetryFromResult(resultsToRetry, result, failureCount);
1548f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
154989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1550bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust  /**
1551bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust   *   message / regEx  .*      other
1552bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust   *   null             true    false
1553bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust   *   non-null         true    match
1554bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust   */
1555bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust  private boolean messageRegExpMatches(String messageRegExp, Throwable ite) {
1556bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust    if (".*".equals(messageRegExp)) {
1557bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust      return true;
1558bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust    } else {
15590f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      if (ite.getMessage() == null) {
15600f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        return false;
15610f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      } else {
15620f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        return Pattern.matches(messageRegExp, ite.getMessage());
15630f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      }
1564bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust    }
1565bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust  }
1566bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust
1567f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private int removeResultsToRetryFromResult(List<ITestResult> resultsToRetry,
1568f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      List<ITestResult> result, int failureCount) {
1569f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if (resultsToRetry != null) {
1570f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for (ITestResult res : resultsToRetry) {
1571f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        result.remove(res);
1572f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        failureCount--;
1573f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1574f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1575f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return failureCount;
1576f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
157789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1578f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1579f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * To reduce thread contention and also to correctly handle thread-confinement
1580f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * this method invokes the @BeforeGroups and @AfterGroups corresponding to the current @Test method.
1581f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
158289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin  private List<ITestResult> runWorkers(ITestNGMethod testMethod,
1583c4cadec5fb52419e211120aa93b6118a4ab756ecCédric Beust      List<IWorker<ITestNGMethod>> workers,
158489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      int threadPoolSize,
158589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      ConfigurationGroupMethods groupMethods,
158689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      XmlSuite suite,
1587f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      Map<String, String> parameters)
1588f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
158989fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin    // Invoke @BeforeGroups on the original method (reduce thread contention,
1590c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust    // and also solve thread confinement)
1591f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    ITestClass testClass= testMethod.getTestClass();
1592f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    Object[] instances = testClass.getInstances(true);
1593f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for(Object instance: instances) {
1594f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      invokeBeforeGroupsConfigurations(testClass, testMethod, groupMethods, suite, parameters, instance);
1595f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
159689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
159789fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1598f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    long maxTimeOut= -1; // 10 seconds
1599f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1600f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin    for(IWorker<ITestNGMethod> tmw : workers) {
1601f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin      long mt= tmw.getTimeOut();
1602f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      if(mt > maxTimeOut) {
1603f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        maxTimeOut= mt;
1604f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1605f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
160689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1607f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    ThreadUtil.execute(workers, threadPoolSize, maxTimeOut, true);
1608f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1609f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
1610f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Collect all the TestResults
1611f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    //
1612ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust    List<ITestResult> result = Lists.newArrayList();
1613f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin    for (IWorker<ITestNGMethod> tmw : workers) {
1614f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin      if (tmw instanceof TestMethodWorker) {
1615f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin        result.addAll(((TestMethodWorker)tmw).getTestResults());
1616f035a01bd8ac47425984d6b9e07a733f3abb3c37nullin      }
1617f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
161889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1619f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for(Object instance: instances) {
1620f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      invokeAfterGroupsConfigurations(testClass, testMethod, groupMethods, suite, parameters, instance);
1621f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
162289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1623f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return result;
1624f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1625f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1626f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1627e934f66fb4fb247ebf5fec45770bc6820fbba29anullin   * Checks to see of the test method has certain dependencies that prevents
1628e934f66fb4fb247ebf5fec45770bc6820fbba29anullin   * TestNG from executing it
1629e934f66fb4fb247ebf5fec45770bc6820fbba29anullin   * @param testMethod test method being checked for
1630f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param testClass
1631f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return dependencies have been run successfully
1632f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
1633e934f66fb4fb247ebf5fec45770bc6820fbba29anullin  private boolean checkDependencies(ITestNGMethod testMethod,
1634a4e6892fbfa21c968737eaf4e4f1e4b0b7f9163eCédric Beust      ITestNGMethod[] allTestMethods)
1635f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  {
1636e934f66fb4fb247ebf5fec45770bc6820fbba29anullin    boolean result = true;
1637f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1638e934f66fb4fb247ebf5fec45770bc6820fbba29anullin    // If this method is marked alwaysRun, no need to check for its dependencies
1639f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if (testMethod.isAlwaysRun()) {
1640f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      return true;
1641f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
164289fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1643f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Any missing group?
16440f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin    if (testMethod.getMissingGroup() != null
1645e934f66fb4fb247ebf5fec45770bc6820fbba29anullin          && !testMethod.ignoreMissingDependencies()) {
1646e934f66fb4fb247ebf5fec45770bc6820fbba29anullin      return false;
1647f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1648f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1649f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // If this method depends on groups, collect all the methods that
1650f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // belong to these groups and make sure they have been run successfully
1651e934f66fb4fb247ebf5fec45770bc6820fbba29anullin    if (dependsOnGroups(testMethod)) {
1652e934f66fb4fb247ebf5fec45770bc6820fbba29anullin      String[] groupsDependedUpon = testMethod.getGroupsDependedUpon();
1653f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1654f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      // Get all the methods that belong to the group depended upon
16550f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      for (String element : groupsDependedUpon) {
165689fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin        ITestNGMethod[] methods =
1657b1c182d51b05a40ac5350e562503a94d024a7c80nullin          MethodGroupsHelper.findMethodsThatBelongToGroup(testMethod,
1658f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust              m_testContext.getAllTestMethods(),
16590f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin              element);
1660f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1661bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust        result = result && haveBeenRunSuccessfully(testMethod, methods);
1662f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1663f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    } // depends on groups
1664f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1665f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // If this method depends on other methods, make sure all these other
1666f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // methods have been run successfully
1667e934f66fb4fb247ebf5fec45770bc6820fbba29anullin    if (result && dependsOnMethods(testMethod)) {
166889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin      ITestNGMethod[] methods =
1669b1c182d51b05a40ac5350e562503a94d024a7c80nullin        MethodHelper.findDependedUponMethods(testMethod, allTestMethods);
1670f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1671bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust      result = result && haveBeenRunSuccessfully(testMethod, methods);
1672f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1673f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1674f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return result;
1675f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1676f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1677f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1678bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust   * @return the test results that apply to one of the instances of the testMethod.
1679bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust   */
1680bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust  private Set<ITestResult> keepSameInstances(ITestNGMethod method, Set<ITestResult> results) {
1681bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust    Set<ITestResult> result = Sets.newHashSet();
1682bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust    for (ITestResult r : results) {
1683bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust      for (Object o : method.getInstances()) {
16849cb7e93d4f995f0003b27a1f28dc9d939b9b8a36Cédric Beust        // Keep this instance if 1) It's on a different class or 2) It's on the same class
16859cb7e93d4f995f0003b27a1f28dc9d939b9b8a36Cédric Beust        // and on the same instance
168660916e4ddae15723de42347024800d514b85de09Cédric Beust        Object instance = r.getInstance() != null
168760916e4ddae15723de42347024800d514b85de09Cédric Beust            ? r.getInstance() : r.getMethod().getInstances()[0];
168860916e4ddae15723de42347024800d514b85de09Cédric Beust        if (r.getTestClass() != method.getTestClass() || instance == o) result.add(r);
1689bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust      }
1690bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust    }
1691bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust    return result;
1692bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust  }
1693bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust
1694bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust  /**
1695f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return true if all the methods have been run successfully
1696f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
1697bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust  private boolean haveBeenRunSuccessfully(ITestNGMethod testMethod, ITestNGMethod[] methods) {
1698f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    // Make sure the method has been run successfully
16990f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin    for (ITestNGMethod method : methods) {
1700bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust      Set<ITestResult> results = keepSameInstances(testMethod, m_notifier.getPassedTests(method));
170160916e4ddae15723de42347024800d514b85de09Cédric Beust      Set<ITestResult> failedAndSkippedMethods = Sets.newHashSet();
170260916e4ddae15723de42347024800d514b85de09Cédric Beust      failedAndSkippedMethods.addAll(m_notifier.getFailedTests(method));
170360916e4ddae15723de42347024800d514b85de09Cédric Beust      failedAndSkippedMethods.addAll(m_notifier.getSkippedTests(method));
170460916e4ddae15723de42347024800d514b85de09Cédric Beust      Set<ITestResult> failedresults = keepSameInstances(testMethod, failedAndSkippedMethods);
170589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1706bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust      // If failed results were returned on the same instance, then these tests didn't pass
17070f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      if (failedresults != null && failedresults.size() > 0) {
17080f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin        return false;
17090f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      }
171089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1711f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      for (ITestResult result : results) {
1712f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        if(!result.isSuccess()) {
1713f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          return false;
1714f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1715f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1716f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1717f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1718f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return true;
1719f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1720f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
172110a202a9e96a8067720d9e2a301ee6b67f5df5edCédric Beust//  private boolean containsInstance(Set<ITestResult> failedresults, Object[] instances) {
172210a202a9e96a8067720d9e2a301ee6b67f5df5edCédric Beust//    for (ITestResult tr : failedresults) {
172310a202a9e96a8067720d9e2a301ee6b67f5df5edCédric Beust//      for (Object o : instances) {
172410a202a9e96a8067720d9e2a301ee6b67f5df5edCédric Beust//        if (o == tr.getInstance()) {
172510a202a9e96a8067720d9e2a301ee6b67f5df5edCédric Beust//          return true;
172610a202a9e96a8067720d9e2a301ee6b67f5df5edCédric Beust//        }
172710a202a9e96a8067720d9e2a301ee6b67f5df5edCédric Beust//      }
172810a202a9e96a8067720d9e2a301ee6b67f5df5edCédric Beust//    }
172910a202a9e96a8067720d9e2a301ee6b67f5df5edCédric Beust//    return false;
173010a202a9e96a8067720d9e2a301ee6b67f5df5edCédric Beust//  }
1731bcb654d600d516d1bfce826220fef65e7d262e33Cédric Beust
1732f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1733f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * An exception was thrown by the test, determine if this method
1734f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * should be marked as a failure or as failure_but_within_successPercentage
1735f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
1736f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private void handleException(Throwable throwable,
1737f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                               ITestNGMethod testMethod,
1738f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                               ITestResult testResult,
1739f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust                               int failureCount) {
1740f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    testResult.setThrowable(throwable);
1741f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    int successPercentage= testMethod.getSuccessPercentage();
1742f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    int invocationCount= testMethod.getInvocationCount();
174321dad3370294d6595fdddc3faf55792f60a913f1nullin    float numberOfTestsThatCanFail= ((100 - successPercentage) * invocationCount) / 100f;
1744f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1745f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    if(failureCount < numberOfTestsThatCanFail) {
1746f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      testResult.setStatus(ITestResult.SUCCESS_PERCENTAGE_FAILURE);
1747f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1748f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    else {
1749f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      testResult.setStatus(ITestResult.FAILURE);
1750f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1751f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1752f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1753f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1754f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1755f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param ite The exception that was just thrown
1756f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @param expectedExceptions The list of expected exceptions for this
1757f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * test method
1758f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return true if the exception that was just thrown is part of the
1759f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * expected exceptions
1760f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
1761bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust  private boolean isExpectedException(Throwable ite, ExpectedExceptionsHolder exceptionHolder) {
1762bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust    if (exceptionHolder == null) {
1763f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      return false;
1764f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
176527e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust
176627e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust    // TestException is the wrapper exception that TestNG will be throwing when an exception was
176727e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust    // expected but not thrown
176827e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust    if (ite.getClass() == TestException.class) {
176927e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust      return false;
177027e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust    }
177127e81a62e0a5000406cc759197c7e24deb0847d1Cédric Beust
1772bfb18c26a3435a04aab4c2f573c03c8664b3b44bCédric Beust    Class<?>[] exceptions = exceptionHolder.expectedClasses;
1773f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    Class<?> realExceptionClass= ite.getClass();
1774f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
17750f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin    for (Class<?> exception : exceptions) {
17760f7e671c94aeedee2fbc796b3318d44b0297b6cdnullin      if (exception.isAssignableFrom(realExceptionClass)) {
1777f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        return true;
1778f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1779f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1780f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1781f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return false;
1782f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1783f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
17849d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust  static interface Predicate<K, T> {
17859d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust    boolean isTrue(K k, T v);
17869d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust  }
1787f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
17889d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust  static class CanRunFromClassPredicate implements Predicate <ITestNGMethod, IClass> {
17899d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust    @Override
17909d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust    public boolean isTrue(ITestNGMethod m, IClass v) {
17919d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust      return m.canRunFromClass(v);
1792f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1793f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1794f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
17959d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust  static class SameClassNamePredicate implements Predicate<ITestNGMethod, IClass> {
17969d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust    @Override
17979d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust    public boolean isTrue(ITestNGMethod m, IClass c) {
17989d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust      return c == null || m.getTestClass().getName().equals(c.getName());
1799f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
18009d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust  }
1801f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
18029d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust  /**
18039d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust   * @return Only the ITestNGMethods applicable for this testClass
18049d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust   */
18059d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust  private ITestNGMethod[] filterMethods(IClass testClass, ITestNGMethod[] methods,
18069d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust      Predicate<ITestNGMethod, IClass> predicate) {
1807ed0917f31f0b66158bc786cd018fd95175f76f29Cédric Beust    List<ITestNGMethod> vResult= Lists.newArrayList();
1808f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1809f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for(ITestNGMethod tm : methods) {
18109d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust      if (predicate.isTrue(tm, testClass)) {
18119d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust        log(10, "Keeping method " + tm + " for class " + testClass);
1812f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        vResult.add(tm);
18139d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust      } else {
18149d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust        log(10, "Filtering out method " + tm + " for class " + testClass);
1815f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1816f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1817f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
18189d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust    ITestNGMethod[] result= vResult.toArray(new ITestNGMethod[vResult.size()]);
18199d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust
18209d4f222d9afb9d19ad55dc77b39d9a36a28e7ea3Cédric Beust    return result;
1821f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1822f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1823f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1824f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return true if this method depends on certain groups.
1825f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
1826f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private boolean dependsOnGroups(ITestNGMethod tm) {
1827e934f66fb4fb247ebf5fec45770bc6820fbba29anullin    String[] groups = tm.getGroupsDependedUpon();
1828e934f66fb4fb247ebf5fec45770bc6820fbba29anullin    boolean result = (null != groups) && (groups.length > 0);
1829f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return result;
1830f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1831f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1832f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  /**
1833f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   * @return true if this method depends on certain groups.
1834f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust   */
1835f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private boolean dependsOnMethods(ITestNGMethod tm) {
1836e934f66fb4fb247ebf5fec45770bc6820fbba29anullin    String[] methods = tm.getMethodsDependedUpon();
1837e934f66fb4fb247ebf5fec45770bc6820fbba29anullin    boolean result = (null != methods) && (methods.length > 0);
1838f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    return result;
1839f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1840f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1841ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust  private void runConfigurationListeners(ITestResult tr, boolean before) {
1842ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust    if (before) {
1843ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust      for(IConfigurationListener icl: m_notifier.getConfigurationListeners()) {
1844eef09e0a0ec23bcea1995c0813ca6d29580c7869Cédric Beust        if (icl instanceof IConfigurationListener2) {
1845eef09e0a0ec23bcea1995c0813ca6d29580c7869Cédric Beust          ((IConfigurationListener2) icl).beforeConfiguration(tr);
1846eef09e0a0ec23bcea1995c0813ca6d29580c7869Cédric Beust        }
1847ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust      }
1848ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust    } else {
1849ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust      for(IConfigurationListener icl: m_notifier.getConfigurationListeners()) {
1850ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust        switch(tr.getStatus()) {
1851ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust          case ITestResult.SKIP:
1852ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust            icl.onConfigurationSkip(tr);
1853ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust            break;
1854ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust          case ITestResult.FAILURE:
1855ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust            icl.onConfigurationFailure(tr);
1856ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust            break;
1857ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust          case ITestResult.SUCCESS:
1858ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust            icl.onConfigurationSuccess(tr);
1859ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust            break;
1860ee8e37d41d7e14252ee649f13768022fee714afbCédric Beust        }
1861f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1862f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1863f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
186489fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1865c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust  void runTestListeners(ITestResult tr) {
1866f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    runTestListeners(tr, m_notifier.getTestListeners());
1867f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
186889fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1869f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  // TODO: move this from here as it is directly called from TestNG
1870f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  public static void runTestListeners(ITestResult tr, List<ITestListener> listeners) {
1871f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    for (ITestListener itl : listeners) {
1872f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      switch(tr.getStatus()) {
1873f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        case ITestResult.SKIP: {
1874f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          itl.onTestSkipped(tr);
1875f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          break;
1876f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1877f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        case ITestResult.SUCCESS_PERCENTAGE_FAILURE: {
1878f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          itl.onTestFailedButWithinSuccessPercentage(tr);
1879f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          break;
1880f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1881f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        case ITestResult.FAILURE: {
1882f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          itl.onTestFailure(tr);
1883f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          break;
1884f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1885f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        case ITestResult.SUCCESS: {
1886f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          itl.onTestSuccess(tr);
1887f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          break;
1888f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1889f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1890f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        case ITestResult.STARTED: {
1891f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          itl.onTestStart(tr);
1892f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          break;
1893f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1894f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1895f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        default: {
1896f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust          assert false : "UNKNOWN STATUS:" + tr;
1897f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        }
1898f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1899f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1900f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1901f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust
1902f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private void log(int level, String s) {
1903f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    Utils.log("Invoker " + Thread.currentThread().hashCode(), level, s);
1904f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
190589fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1906eddb4a9423c14fee808a30e92ad77a16e88b320enullin  /**
1907eddb4a9423c14fee808a30e92ad77a16e88b320enullin   * This class holds a {@code ParameterHolder} and in case of an error, a non-null
1908eddb4a9423c14fee808a30e92ad77a16e88b320enullin   * {@code TestResult} containing the cause
1909eddb4a9423c14fee808a30e92ad77a16e88b320enullin   */
1910f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  private static class ParameterBag {
1911c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust    final ParameterHolder parameterHolder;
1912eddb4a9423c14fee808a30e92ad77a16e88b320enullin    final List<ITestResult> errorResults = Lists.newArrayList();
191389fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1914c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust    public ParameterBag(ParameterHolder params, TestResult tr) {
1915c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust      parameterHolder = params;
1916eddb4a9423c14fee808a30e92ad77a16e88b320enullin      if (tr != null) {
1917f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust        errorResults.add(tr);
1918f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      }
1919f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
192089fa9de5273ba0e09ed99e5e116ecd9910c9c374nullin
1921f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    public boolean hasErrors() {
1922f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust      return !errorResults.isEmpty();
1923f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust    }
1924f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust  }
1925c90ac0f51ccdf22d9430a8264ddd2d4966b36f81Cédric Beust
1926f17a79b6a57f282e5cc0fbe741e73309e217976eCédric Beust}
1927