package org.testng.internal;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Pattern;

import org.testng.IClass;
import org.testng.IRetryAnalyzer;
import org.testng.ITestClass;
import org.testng.ITestNGMethod;
import org.testng.annotations.ITestOrConfiguration;
import org.testng.collections.Lists;
import org.testng.collections.Maps;
import org.testng.collections.Sets;
import org.testng.internal.annotations.IAnnotationFinder;
import org.testng.xml.XmlClass;
import org.testng.xml.XmlInclude;
import org.testng.xml.XmlTest;

Superclass to represent both @Test and @Configuration methods.
/** * Superclass to represent both @Test and @Configuration methods. */
public abstract class BaseTestMethod implements ITestNGMethod { private static final Pattern SPACE_SEPARATOR_PATTERN = Pattern.compile(" +");
The test class on which the test method was found. Note that this is not necessarily the declaring class.
/** * The test class on which the test method was found. Note that this is not * necessarily the declaring class. */
protected ITestClass m_testClass; protected final Class<?> m_methodClass; protected final ConstructorOrMethod m_method; private String m_signature; protected String m_id = ""; protected long m_date = -1; protected final IAnnotationFinder m_annotationFinder; protected String[] m_groups = {}; protected String[] m_groupsDependedUpon = {}; protected String[] m_methodsDependedUpon = {}; protected String[] m_beforeGroups = {}; protected String[] m_afterGroups = {}; private boolean m_isAlwaysRun; private boolean m_enabled; private final String m_methodName; // If a depended group is not found private String m_missingGroup; private String m_description = null; protected AtomicInteger m_currentInvocationCount = new AtomicInteger(0); private int m_parameterInvocationCount = 1; private Callable<Boolean> m_moreInvocationChecker; private IRetryAnalyzer m_retryAnalyzer = null; private boolean m_skipFailedInvocations = true; private long m_invocationTimeOut = 0L; private List<Integer> m_invocationNumbers = Lists.newArrayList(); private final Collection<Integer> m_failedInvocationNumbers = new ConcurrentLinkedQueue<>(); private long m_timeOut = 0; private boolean m_ignoreMissingDependencies; private int m_priority; private XmlTest m_xmlTest; private Object m_instance;
Constructs a BaseTestMethod TODO cquezel JavaDoc.
Params:
  • method –
  • annotationFinder –
  • instance –
/** * Constructs a <code>BaseTestMethod</code> TODO cquezel JavaDoc. * * @param method * @param annotationFinder * @param instance */
public BaseTestMethod(String methodName, Method method, IAnnotationFinder annotationFinder, Object instance) { this(methodName, new ConstructorOrMethod(method), annotationFinder, instance); } public BaseTestMethod(String methodName, ConstructorOrMethod com, IAnnotationFinder annotationFinder, Object instance) { m_methodClass = com.getDeclaringClass(); m_method = com; m_methodName = methodName; m_annotationFinder = annotationFinder; m_instance = instance; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public boolean isAlwaysRun() { return m_isAlwaysRun; }
TODO cquezel JavaDoc.
Params:
  • alwaysRun –
/** * TODO cquezel JavaDoc. * * @param alwaysRun */
protected void setAlwaysRun(boolean alwaysRun) { m_isAlwaysRun = alwaysRun; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public Class<?> getRealClass() { return m_methodClass; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public ITestClass getTestClass() { return m_testClass; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public void setTestClass(ITestClass tc) { assert null != tc; if (! tc.getRealClass().equals(m_method.getDeclaringClass())) { assert m_method.getDeclaringClass().isAssignableFrom(tc.getRealClass()) : "\nMISMATCH : " + tc.getRealClass() + " " + m_method.getDeclaringClass(); } m_testClass = tc; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public Method getMethod() { return m_method.getMethod(); }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public String getMethodName() { return m_methodName; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public Object[] getInstances() { return new Object[] { getInstance() }; } @Override public Object getInstance() { return m_instance; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public long[] getInstanceHashCodes() { return m_testClass.getInstanceHashCodes(); }
{@inheritDoc}
Returns:the addition of groups defined on the class and on this method.
/** * {@inheritDoc} * @return the addition of groups defined on the class and on this method. */
@Override public String[] getGroups() { return m_groups; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public String[] getGroupsDependedUpon() { return m_groupsDependedUpon; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public String[] getMethodsDependedUpon() { return m_methodsDependedUpon; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public boolean isTest() { return false; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public boolean isBeforeSuiteConfiguration() { return false; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public boolean isAfterSuiteConfiguration() { return false; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public boolean isBeforeTestConfiguration() { return false; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public boolean isAfterTestConfiguration() { return false; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public boolean isBeforeGroupsConfiguration() { return false; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public boolean isAfterGroupsConfiguration() { return false; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public boolean isBeforeClassConfiguration() { return false; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public boolean isAfterClassConfiguration() { return false; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public boolean isBeforeMethodConfiguration() { return false; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public boolean isAfterMethodConfiguration() { return false; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public long getTimeOut() { long result = m_timeOut != 0 ? m_timeOut : (m_xmlTest != null ? m_xmlTest.getTimeOut(0) : 0); return result; } @Override public void setTimeOut(long timeOut) { m_timeOut = timeOut; }
{@inheritDoc}
Returns:the number of times this method needs to be invoked.
/** * {@inheritDoc} * @return the number of times this method needs to be invoked. */
@Override public int getInvocationCount() { return 1; }
No-op.
/** * No-op. */
@Override public void setInvocationCount(int counter) { }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public int getTotalInvocationCount() { return 0; }
{@inheritDoc} Default value for successPercentage.
/** * {@inheritDoc} Default value for successPercentage. */
@Override public int getSuccessPercentage() { return 100; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public String getId() { return m_id; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public void setId(String id) { m_id = id; }
{@inheritDoc}
Returns:Returns the date.
/** * {@inheritDoc} * @return Returns the date. */
@Override public long getDate() { return m_date; }
{@inheritDoc}
Params:
  • date – The date to set.
/** * {@inheritDoc} * @param date The date to set. */
@Override public void setDate(long date) { m_date = date; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public boolean canRunFromClass(IClass testClass) { return m_methodClass.isAssignableFrom(testClass.getRealClass()); }
{@inheritDoc} Compares two BaseTestMethod using the test class then the associated Java Method.
/** * {@inheritDoc} Compares two BaseTestMethod using the test class then the associated * Java Method. */
@Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } BaseTestMethod other = (BaseTestMethod) obj; boolean isEqual = m_testClass == null ? other.m_testClass == null : other.m_testClass != null && m_testClass.getRealClass().equals(other.m_testClass.getRealClass()) && m_instance == other.getInstance(); return isEqual && getConstructorOrMethod().equals(other.getConstructorOrMethod()); }
{@inheritDoc} This implementation returns the associated Java Method's hash code.
Returns:the associated Java Method's hash code.
/** * {@inheritDoc} This implementation returns the associated Java Method's hash code. * @return the associated Java Method's hash code. */
@Override public int hashCode() { return m_method.hashCode(); } protected void initGroups(Class<? extends ITestOrConfiguration> annotationClass) { // // Init groups // { ITestOrConfiguration annotation = getAnnotationFinder().findAnnotation(getConstructorOrMethod(), annotationClass); ITestOrConfiguration classAnnotation = getAnnotationFinder().findAnnotation(getConstructorOrMethod().getDeclaringClass(), annotationClass); setGroups(getStringArray(null != annotation ? annotation.getGroups() : null, null != classAnnotation ? classAnnotation.getGroups() : null)); } // // Init groups depended upon // initRestOfGroupDependencies(annotationClass); } protected void initBeforeAfterGroups(Class<? extends ITestOrConfiguration> annotationClass, String[] groups) { String[] groupsAtMethodLevel = calculateGroupsTouseConsideringValuesAndGroupValues(annotationClass, groups); //@BeforeGroups and @AfterGroups annotation cannot be used at Class level. So its always null String[] groupsAtClassLevel = null; setGroups(getStringArray(groupsAtMethodLevel, groupsAtClassLevel)); initRestOfGroupDependencies(annotationClass); } private String[] calculateGroupsTouseConsideringValuesAndGroupValues(Class<? extends ITestOrConfiguration> annotationClass, String[] groups) { if (groups == null || groups.length == 0) { ITestOrConfiguration annotation = getAnnotationFinder().findAnnotation(getConstructorOrMethod(), annotationClass); groups = null != annotation ? annotation.getGroups() : null; } return groups; } private void initRestOfGroupDependencies(Class<? extends ITestOrConfiguration> annotationClass) { // // Init groups depended upon // ITestOrConfiguration annotation = getAnnotationFinder().findAnnotation(getConstructorOrMethod(), annotationClass); ITestOrConfiguration classAnnotation = getAnnotationFinder().findAnnotation(getConstructorOrMethod().getDeclaringClass(), annotationClass); Map<String, Set<String>> xgd = calculateXmlGroupDependencies(m_xmlTest); List<String> xmlGroupDependencies = Lists.newArrayList(); for (String g : getGroups()) { Set<String> gdu = xgd.get(g); if (gdu != null) { xmlGroupDependencies.addAll(gdu); } } setGroupsDependedUpon( getStringArray(null != annotation ? annotation.getDependsOnGroups() : null, null != classAnnotation ? classAnnotation.getDependsOnGroups() : null), xmlGroupDependencies); String[] methodsDependedUpon = getStringArray(null != annotation ? annotation.getDependsOnMethods() : null, null != classAnnotation ? classAnnotation.getDependsOnMethods() : null); // Qualify these methods if they don't have a package for (int i = 0; i < methodsDependedUpon.length; i++) { String m = methodsDependedUpon[i]; if (!m.contains(".")) { m = MethodHelper.calculateMethodCanonicalName(m_methodClass, methodsDependedUpon[i]); methodsDependedUpon[i] = m != null ? m : methodsDependedUpon[i]; } } setMethodsDependedUpon(methodsDependedUpon); } private static Map<String, Set<String>> calculateXmlGroupDependencies(XmlTest xmlTest) { Map<String, Set<String>> result = Maps.newHashMap(); if (xmlTest == null) { return result; } for (Map.Entry<String, String> e : xmlTest.getXmlDependencyGroups().entrySet()) { String name = e.getKey(); String dependsOn = e.getValue(); Set<String> set = result.get(name); if (set == null) { set = Sets.newHashSet(); result.put(name, set); } set.addAll(Arrays.asList(SPACE_SEPARATOR_PATTERN.split(dependsOn))); } return result; } protected IAnnotationFinder getAnnotationFinder() { return m_annotationFinder; } protected IClass getIClass() { return m_testClass; } private String computeSignature() { String classLong = m_method.getDeclaringClass().getName(); String cls = classLong.substring(classLong.lastIndexOf(".") + 1); StringBuilder result = new StringBuilder(cls).append(".").append(m_method.getName()).append("("); int i = 0; for (Class<?> p : m_method.getParameterTypes()) { if (i++ > 0) { result.append(", "); } result.append(p.getName()); } result.append(")"); result.append("[pri:").append(getPriority()).append(", instance:").append(m_instance).append("]"); return result.toString(); } public String getSimpleName() { return m_method.getDeclaringClass().getSimpleName() + "." + m_method.getName(); } protected String getSignature() { if (m_signature == null) { m_signature = computeSignature(); } return m_signature; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public String toString() { return getSignature(); } protected String[] getStringArray(String[] methodArray, String[] classArray) { final Set<String> vResult = Sets.newHashSet(); if (null != methodArray) { Collections.addAll(vResult, methodArray); } if (null != classArray) { Collections.addAll(vResult, classArray); } return vResult.toArray(new String[vResult.size()]); } protected void setGroups(String[] groups) { m_groups = groups; } protected void setGroupsDependedUpon(String[] groups, Collection<String> xmlGroupDependencies) { List<String> l = Lists.newArrayList(); l.addAll(Arrays.asList(groups)); l.addAll(xmlGroupDependencies); m_groupsDependedUpon = l.toArray(new String[l.size()]); } protected void setMethodsDependedUpon(String[] methods) { m_methodsDependedUpon = methods; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public void addMethodDependedUpon(String method) { String[] newMethods = new String[m_methodsDependedUpon.length + 1]; newMethods[0] = method; System.arraycopy(m_methodsDependedUpon, 0, newMethods, 1, m_methodsDependedUpon.length); m_methodsDependedUpon = newMethods; } private static void ppp(String s) { System.out.println("[BaseTestMethod] " + s); }
Compares two ITestNGMethod by date.
/** Compares two ITestNGMethod by date. */
public static final Comparator<?> DATE_COMPARATOR = new Comparator<Object>() { @Override public int compare(Object o1, Object o2) { try { ITestNGMethod m1 = (ITestNGMethod) o1; ITestNGMethod m2 = (ITestNGMethod) o2; return (int) (m1.getDate() - m2.getDate()); } catch(Exception ex) { return 0; // TODO CQ document this logic } } };
{@inheritDoc}
/** * {@inheritDoc} */
@Override public String getMissingGroup() { return m_missingGroup; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public void setMissingGroup(String group) { m_missingGroup = group; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public int getThreadPoolSize() { return 0; }
No-op.
/** * No-op. */
@Override public void setThreadPoolSize(int threadPoolSize) { } @Override public void setDescription(String description) { m_description = description; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public String getDescription() { return m_description; } public void setEnabled(boolean enabled) { m_enabled = enabled; } @Override public boolean getEnabled() { return m_enabled; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public String[] getBeforeGroups() { return m_beforeGroups; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public String[] getAfterGroups() { return m_afterGroups; } @Override public void incrementCurrentInvocationCount() { m_currentInvocationCount.incrementAndGet(); } @Override public int getCurrentInvocationCount() { return m_currentInvocationCount.get(); } @Override public void setParameterInvocationCount(int n) { m_parameterInvocationCount = n; } @Override public int getParameterInvocationCount() { return m_parameterInvocationCount; } @Override public void setMoreInvocationChecker(Callable<Boolean> moreInvocationChecker) { m_moreInvocationChecker = moreInvocationChecker; } @Override public boolean hasMoreInvocation() { if (m_moreInvocationChecker != null) { try { return m_moreInvocationChecker.call(); } catch (Exception e) { // Should never append throw new RuntimeException(e); } } return getCurrentInvocationCount() < getInvocationCount() * getParameterInvocationCount(); } @Override public abstract ITestNGMethod clone(); @Override public IRetryAnalyzer getRetryAnalyzer() { return m_retryAnalyzer; } @Override public void setRetryAnalyzer(IRetryAnalyzer retryAnalyzer) { m_retryAnalyzer = retryAnalyzer; } @Override public boolean skipFailedInvocations() { return m_skipFailedInvocations; } @Override public void setSkipFailedInvocations(boolean s) { m_skipFailedInvocations = s; } public void setInvocationTimeOut(long timeOut) { m_invocationTimeOut = timeOut; } @Override public long getInvocationTimeOut() { return m_invocationTimeOut; } @Override public boolean ignoreMissingDependencies() { return m_ignoreMissingDependencies; } @Override public void setIgnoreMissingDependencies(boolean i) { m_ignoreMissingDependencies = i; } @Override public List<Integer> getInvocationNumbers() { return m_invocationNumbers; } @Override public void setInvocationNumbers(List<Integer> numbers) { m_invocationNumbers = numbers; } @Override public List<Integer> getFailedInvocationNumbers() { return new ArrayList<>(m_failedInvocationNumbers); } @Override public void addFailedInvocationNumber(int number) { m_failedInvocationNumbers.add(number); } @Override public int getPriority() { return m_priority; } @Override public void setPriority(int priority) { m_priority = priority; } @Override public XmlTest getXmlTest() { return m_xmlTest; } public void setXmlTest(XmlTest xmlTest) { m_xmlTest = xmlTest; } @Override public ConstructorOrMethod getConstructorOrMethod() { return m_method; } @Override public Map<String, String> findMethodParameters(XmlTest test) { // Get the test+suite parameters Map<String, String> result = test.getAllParameters(); for (XmlClass xmlClass: test.getXmlClasses()) { if (xmlClass.getName().equals(getTestClass().getName())) { result.putAll(xmlClass.getLocalParameters()); for (XmlInclude include : xmlClass.getIncludedMethods()) { if (include.getName().equals(getMethodName())) { result.putAll(include.getLocalParameters()); break; } } } } return result; } @Override public String getQualifiedName() { return getRealClass().getName() + "." + getMethodName(); } }