Home | History | Annotate | Download | only in internal
      1 package org.testng.internal;
      2 
      3 import java.lang.reflect.Method;
      4 import java.util.Arrays;
      5 import java.util.Collection;
      6 import java.util.Collections;
      7 import java.util.Comparator;
      8 import java.util.List;
      9 import java.util.Map;
     10 import java.util.Set;
     11 import java.util.concurrent.atomic.AtomicInteger;
     12 import java.util.regex.Pattern;
     13 
     14 import org.testng.IClass;
     15 import org.testng.IRetryAnalyzer;
     16 import org.testng.ITestClass;
     17 import org.testng.ITestNGMethod;
     18 import org.testng.annotations.ITestOrConfiguration;
     19 import org.testng.collections.Lists;
     20 import org.testng.collections.Maps;
     21 import org.testng.collections.Sets;
     22 import org.testng.internal.annotations.IAnnotationFinder;
     23 import org.testng.xml.XmlClass;
     24 import org.testng.xml.XmlInclude;
     25 import org.testng.xml.XmlTest;
     26 
     27 /**
     28  * Superclass to represent both @Test and @Configuration methods.
     29  */
     30 public abstract class BaseTestMethod implements ITestNGMethod {
     31   private static final long serialVersionUID = -2666032602580652173L;
     32   private static final Pattern SPACE_SEPARATOR_PATTERN = Pattern.compile(" +");
     33 
     34   /**
     35    * The test class on which the test method was found. Note that this is not
     36    * necessarily the declaring class.
     37    */
     38   protected ITestClass m_testClass;
     39 
     40   protected final transient Class<?> m_methodClass;
     41   protected final transient ConstructorOrMethod m_method;
     42   private transient String m_signature;
     43   protected String m_id = "";
     44   protected long m_date = -1;
     45   protected final transient IAnnotationFinder m_annotationFinder;
     46   protected String[] m_groups = {};
     47   protected String[] m_groupsDependedUpon = {};
     48   protected String[] m_methodsDependedUpon = {};
     49   protected String[] m_beforeGroups = {};
     50   protected String[] m_afterGroups = {};
     51   private boolean m_isAlwaysRun;
     52   private boolean m_enabled;
     53 
     54   private final String m_methodName;
     55   // If a depended group is not found
     56   private String m_missingGroup;
     57   private String m_description = null;
     58   protected AtomicInteger m_currentInvocationCount = new AtomicInteger(0);
     59   private int m_parameterInvocationCount = 1;
     60   private IRetryAnalyzer m_retryAnalyzer = null;
     61   private boolean m_skipFailedInvocations = true;
     62   private long m_invocationTimeOut = 0L;
     63 
     64   private List<Integer> m_invocationNumbers = Lists.newArrayList();
     65   private final List<Integer> m_failedInvocationNumbers = Collections.synchronizedList(Lists.<Integer>newArrayList());
     66   private long m_timeOut = 0;
     67 
     68   private boolean m_ignoreMissingDependencies;
     69   private int m_priority;
     70 
     71   private XmlTest m_xmlTest;
     72   private Object m_instance;
     73 
     74   /**
     75    * Constructs a <code>BaseTestMethod</code> TODO cquezel JavaDoc.
     76    *
     77    * @param method
     78    * @param annotationFinder
     79    * @param instance
     80    */
     81   public BaseTestMethod(String methodName, Method method, IAnnotationFinder annotationFinder, Object instance) {
     82     this(methodName, new ConstructorOrMethod(method), annotationFinder, instance);
     83   }
     84 
     85   public BaseTestMethod(String methodName, ConstructorOrMethod com, IAnnotationFinder annotationFinder,
     86       Object instance) {
     87     m_methodClass = com.getDeclaringClass();
     88     m_method = com;
     89     m_methodName = methodName;
     90     m_annotationFinder = annotationFinder;
     91     m_instance = instance;
     92   }
     93 
     94   /**
     95    * {@inheritDoc}
     96    */
     97   @Override
     98   public boolean isAlwaysRun() {
     99     return m_isAlwaysRun;
    100   }
    101 
    102   /**
    103    * TODO cquezel JavaDoc.
    104    *
    105    * @param alwaysRun
    106    */
    107   protected void setAlwaysRun(boolean alwaysRun) {
    108     m_isAlwaysRun = alwaysRun;
    109   }
    110 
    111   /**
    112    * {@inheritDoc}
    113    */
    114   @Override
    115   public Class<?> getRealClass() {
    116     return m_methodClass;
    117   }
    118 
    119   /**
    120    * {@inheritDoc}
    121    */
    122   @Override
    123   public ITestClass getTestClass() {
    124     return m_testClass;
    125   }
    126 
    127   /**
    128    * {@inheritDoc}
    129    */
    130   @Override
    131   public void setTestClass(ITestClass tc) {
    132     assert null != tc;
    133     if (! tc.getRealClass().equals(m_method.getDeclaringClass())) {
    134       assert m_method.getDeclaringClass().isAssignableFrom(tc.getRealClass()) :
    135         "\nMISMATCH : " + tc.getRealClass() + " " + m_method.getDeclaringClass();
    136     }
    137     m_testClass = tc;
    138   }
    139 
    140   @Override
    141   public int compareTo(Object o) {
    142     int result = -2;
    143     Class<?> thisClass = getRealClass();
    144     Class<?> otherClass = ((ITestNGMethod) o).getRealClass();
    145     if (this == o) {
    146       result = 0;
    147     } else if (thisClass.isAssignableFrom(otherClass)) {
    148       result = -1;
    149     } else if (otherClass.isAssignableFrom(thisClass)) {
    150       result = 1;
    151     } else if (equals(o)) {
    152       result = 0;
    153     }
    154 
    155     return result;
    156   }
    157 
    158   /**
    159    * {@inheritDoc}
    160    */
    161   @Override
    162   public Method getMethod() {
    163     return m_method.getMethod();
    164   }
    165 
    166   /**
    167    * {@inheritDoc}
    168    */
    169   @Override
    170   public String getMethodName() {
    171     return m_methodName;
    172   }
    173 
    174   /**
    175    * {@inheritDoc}
    176    */
    177   @Override
    178   public Object[] getInstances() {
    179     return new Object[] { getInstance() };
    180   }
    181 
    182   @Override
    183   public Object getInstance() {
    184     return m_instance;
    185   }
    186 
    187   /**
    188    * {@inheritDoc}
    189    */
    190   @Override
    191   public long[] getInstanceHashCodes() {
    192     return m_testClass.getInstanceHashCodes();
    193   }
    194 
    195   /**
    196    * {@inheritDoc}
    197    * @return the addition of groups defined on the class and on this method.
    198    */
    199   @Override
    200   public String[] getGroups() {
    201     return m_groups;
    202   }
    203 
    204   /**
    205    * {@inheritDoc}
    206    */
    207   @Override
    208   public String[] getGroupsDependedUpon() {
    209     return m_groupsDependedUpon;
    210   }
    211 
    212   /**
    213    * {@inheritDoc}
    214    */
    215   @Override
    216   public String[] getMethodsDependedUpon() {
    217     return m_methodsDependedUpon;
    218   }
    219 
    220   /**
    221    * {@inheritDoc}
    222    */
    223   @Override
    224   public boolean isTest() {
    225     return false;
    226   }
    227 
    228   /**
    229    * {@inheritDoc}
    230    */
    231   @Override
    232   public boolean isBeforeSuiteConfiguration() {
    233     return false;
    234   }
    235 
    236   /**
    237    * {@inheritDoc}
    238    */
    239   @Override
    240   public boolean isAfterSuiteConfiguration() {
    241     return false;
    242   }
    243 
    244   /**
    245    * {@inheritDoc}
    246    */
    247   @Override
    248   public boolean isBeforeTestConfiguration() {
    249     return false;
    250   }
    251 
    252   /**
    253    * {@inheritDoc}
    254    */
    255   @Override
    256   public boolean isAfterTestConfiguration() {
    257     return false;
    258   }
    259 
    260   /**
    261    * {@inheritDoc}
    262    */
    263   @Override
    264   public boolean isBeforeGroupsConfiguration() {
    265     return false;
    266   }
    267 
    268   /**
    269    * {@inheritDoc}
    270    */
    271   @Override
    272   public boolean isAfterGroupsConfiguration() {
    273     return false;
    274   }
    275 
    276   /**
    277    * {@inheritDoc}
    278    */
    279   @Override
    280   public boolean isBeforeClassConfiguration() {
    281     return false;
    282   }
    283 
    284   /**
    285    * {@inheritDoc}
    286    */
    287   @Override
    288   public boolean isAfterClassConfiguration() {
    289     return false;
    290   }
    291 
    292   /**
    293    * {@inheritDoc}
    294    */
    295   @Override
    296   public boolean isBeforeMethodConfiguration() {
    297     return false;
    298   }
    299 
    300   /**
    301    * {@inheritDoc}
    302    */
    303   @Override
    304   public boolean isAfterMethodConfiguration() {
    305     return false;
    306   }
    307 
    308   /**
    309    * {@inheritDoc}
    310    */
    311   @Override
    312   public long getTimeOut() {
    313     long result = m_timeOut != 0 ? m_timeOut : (m_xmlTest != null ? m_xmlTest.getTimeOut(0) : 0);
    314     return result;
    315   }
    316 
    317   @Override
    318   public void setTimeOut(long timeOut) {
    319     m_timeOut = timeOut;
    320   }
    321 
    322   /**
    323    * {@inheritDoc}
    324    * @return the number of times this method needs to be invoked.
    325    */
    326   @Override
    327   public int getInvocationCount() {
    328     return 1;
    329   }
    330 
    331   /**
    332    * No-op.
    333    */
    334   @Override
    335   public void setInvocationCount(int counter) {
    336   }
    337 
    338   /**
    339    * {@inheritDoc}
    340    * @return the number of times this method or one of its clones must be invoked.
    341    */
    342   @Override
    343   public int getTotalInvocationCount() {
    344     return 1;
    345   }
    346 
    347   /**
    348    * {@inheritDoc} Default value for successPercentage.
    349    */
    350   @Override
    351   public int getSuccessPercentage() {
    352     return 100;
    353   }
    354 
    355   /**
    356    * {@inheritDoc}
    357    */
    358   @Override
    359   public String getId() {
    360     return m_id;
    361   }
    362 
    363   /**
    364    * {@inheritDoc}
    365    */
    366   @Override
    367   public void setId(String id) {
    368     m_id = id;
    369   }
    370 
    371 
    372   /**
    373    * {@inheritDoc}
    374    * @return Returns the date.
    375    */
    376   @Override
    377   public long getDate() {
    378     return m_date;
    379   }
    380 
    381   /**
    382    * {@inheritDoc}
    383    * @param date The date to set.
    384    */
    385   @Override
    386   public void setDate(long date) {
    387     m_date = date;
    388   }
    389 
    390   /**
    391    * {@inheritDoc}
    392    */
    393   @Override
    394   public boolean canRunFromClass(IClass testClass) {
    395     return m_methodClass.isAssignableFrom(testClass.getRealClass());
    396   }
    397 
    398   /**
    399    * {@inheritDoc} Compares two BaseTestMethod using the test class then the associated
    400    * Java Method.
    401    */
    402   @Override
    403   public boolean equals(Object obj) {
    404     if (this == obj) {
    405       return true;
    406     }
    407     if (obj == null) {
    408       return false;
    409     }
    410     if (getClass() != obj.getClass()) {
    411       return false;
    412     }
    413 
    414     BaseTestMethod other = (BaseTestMethod) obj;
    415 
    416     boolean isEqual = m_testClass == null ? other.m_testClass == null
    417         : other.m_testClass != null &&
    418           m_testClass.getRealClass().equals(other.m_testClass.getRealClass())
    419           && m_instance == other.getInstance();
    420 
    421     return isEqual && getConstructorOrMethod().equals(other.getConstructorOrMethod());
    422   }
    423 
    424   /**
    425    * {@inheritDoc} This implementation returns the associated Java Method's hash code.
    426    * @return the associated Java Method's hash code.
    427    */
    428   @Override
    429   public int hashCode() {
    430     return m_method.hashCode();
    431   }
    432 
    433   protected void initGroups(Class<? extends ITestOrConfiguration> annotationClass) {
    434     //
    435     // Init groups
    436     //
    437     {
    438       ITestOrConfiguration annotation = getAnnotationFinder().findAnnotation(getMethod(), annotationClass);
    439       ITestOrConfiguration classAnnotation = getAnnotationFinder().findAnnotation(getMethod().getDeclaringClass(), annotationClass);
    440 
    441       setGroups(getStringArray(null != annotation ? annotation.getGroups() : null,
    442           null != classAnnotation ? classAnnotation.getGroups() : null));
    443     }
    444 
    445     //
    446     // Init groups depended upon
    447     //
    448     {
    449       ITestOrConfiguration annotation = getAnnotationFinder().findAnnotation(getMethod(), annotationClass);
    450       ITestOrConfiguration classAnnotation = getAnnotationFinder().findAnnotation(getMethod().getDeclaringClass(), annotationClass);
    451 
    452       Map<String, Set<String>> xgd = calculateXmlGroupDependencies(m_xmlTest);
    453       List<String> xmlGroupDependencies = Lists.newArrayList();
    454       for (String g : getGroups()) {
    455         Set<String> gdu = xgd.get(g);
    456         if (gdu != null) {
    457           xmlGroupDependencies.addAll(gdu);
    458         }
    459       }
    460       setGroupsDependedUpon(
    461           getStringArray(null != annotation ? annotation.getDependsOnGroups() : null,
    462           null != classAnnotation ? classAnnotation.getDependsOnGroups() : null),
    463           xmlGroupDependencies);
    464 
    465       String[] methodsDependedUpon =
    466         getStringArray(null != annotation ? annotation.getDependsOnMethods() : null,
    467         null != classAnnotation ? classAnnotation.getDependsOnMethods() : null);
    468       // Qualify these methods if they don't have a package
    469       for (int i = 0; i < methodsDependedUpon.length; i++) {
    470         String m = methodsDependedUpon[i];
    471         if (!m.contains(".")) {
    472           m = MethodHelper.calculateMethodCanonicalName(m_methodClass, methodsDependedUpon[i]);
    473           methodsDependedUpon[i] = m != null ? m : methodsDependedUpon[i];
    474         }
    475       }
    476       setMethodsDependedUpon(methodsDependedUpon);
    477     }
    478   }
    479 
    480 
    481   private static Map<String, Set<String>> calculateXmlGroupDependencies(XmlTest xmlTest) {
    482     Map<String, Set<String>> result = Maps.newHashMap();
    483     if (xmlTest == null) {
    484       return result;
    485     }
    486 
    487     for (Map.Entry<String, String> e : xmlTest.getXmlDependencyGroups().entrySet()) {
    488       String name = e.getKey();
    489       String dependsOn = e.getValue();
    490       Set<String> set = result.get(name);
    491       if (set == null) {
    492         set = Sets.newHashSet();
    493         result.put(name, set);
    494       }
    495       set.addAll(Arrays.asList(SPACE_SEPARATOR_PATTERN.split(dependsOn)));
    496     }
    497 
    498     return result;
    499   }
    500 
    501   protected IAnnotationFinder getAnnotationFinder() {
    502     return m_annotationFinder;
    503   }
    504 
    505   protected IClass getIClass() {
    506     return m_testClass;
    507   }
    508 
    509   private String computeSignature() {
    510     String classLong = m_method.getDeclaringClass().getName();
    511     String cls = classLong.substring(classLong.lastIndexOf(".") + 1);
    512     StringBuilder result = new StringBuilder(cls).append(".").append(m_method.getName()).append("(");
    513     int i = 0;
    514     for (Class<?> p : m_method.getParameterTypes()) {
    515       if (i++ > 0) {
    516         result.append(", ");
    517       }
    518       result.append(p.getName());
    519     }
    520     result.append(")");
    521     result.append("[pri:").append(getPriority()).append(", instance:").append(m_instance).append("]");
    522 
    523     return result.toString();
    524   }
    525 
    526   protected String getSignature() {
    527     if (m_signature == null) {
    528       m_signature = computeSignature();
    529     }
    530     return m_signature;
    531   }
    532 
    533   /**
    534    * {@inheritDoc}
    535    */
    536   @Override
    537   public String toString() {
    538     return getSignature();
    539   }
    540 
    541   protected String[] getStringArray(String[] methodArray, String[] classArray) {
    542     final Set<String> vResult = Sets.newHashSet();
    543     if (null != methodArray) {
    544       Collections.addAll(vResult, methodArray);
    545     }
    546     if (null != classArray) {
    547       Collections.addAll(vResult, classArray);
    548     }
    549     return vResult.toArray(new String[vResult.size()]);
    550   }
    551 
    552   protected void setGroups(String[] groups) {
    553     m_groups = groups;
    554   }
    555 
    556   protected void setGroupsDependedUpon(String[] groups, Collection<String> xmlGroupDependencies) {
    557     List<String> l = Lists.newArrayList();
    558     l.addAll(Arrays.asList(groups));
    559     l.addAll(xmlGroupDependencies);
    560     m_groupsDependedUpon = l.toArray(new String[l.size()]);
    561   }
    562 
    563   protected void setMethodsDependedUpon(String[] methods) {
    564     m_methodsDependedUpon = methods;
    565   }
    566 
    567   /**
    568    * {@inheritDoc}
    569    */
    570   @Override
    571   public void addMethodDependedUpon(String method) {
    572     String[] newMethods = new String[m_methodsDependedUpon.length + 1];
    573     newMethods[0] = method;
    574     System.arraycopy(m_methodsDependedUpon, 0, newMethods, 1, m_methodsDependedUpon.length);
    575     m_methodsDependedUpon = newMethods;
    576   }
    577 
    578   private static void ppp(String s) {
    579     System.out.println("[BaseTestMethod] " + s);
    580   }
    581 
    582   /** Compares two ITestNGMethod by date. */
    583   public static final Comparator<?> DATE_COMPARATOR = new Comparator<Object>() {
    584     @Override
    585     public int compare(Object o1, Object o2) {
    586       try {
    587         ITestNGMethod m1 = (ITestNGMethod) o1;
    588         ITestNGMethod m2 = (ITestNGMethod) o2;
    589         return (int) (m1.getDate() - m2.getDate());
    590       }
    591       catch(Exception ex) {
    592         return 0; // TODO CQ document this logic
    593       }
    594     }
    595   };
    596 
    597   /**
    598    * {@inheritDoc}
    599    */
    600   @Override
    601   public String getMissingGroup() {
    602     return m_missingGroup;
    603   }
    604 
    605   /**
    606    * {@inheritDoc}
    607    */
    608   @Override
    609   public void setMissingGroup(String group) {
    610     m_missingGroup = group;
    611   }
    612 
    613   /**
    614    * {@inheritDoc}
    615    */
    616   @Override
    617   public int getThreadPoolSize() {
    618     return 0;
    619   }
    620 
    621   /**
    622    * No-op.
    623    */
    624   @Override
    625   public void setThreadPoolSize(int threadPoolSize) {
    626   }
    627 
    628   @Override
    629   public void setDescription(String description) {
    630     m_description = description;
    631   }
    632 
    633   /**
    634    * {@inheritDoc}
    635    */
    636   @Override
    637   public String getDescription() {
    638     return m_description;
    639   }
    640 
    641   public void setEnabled(boolean enabled) {
    642     m_enabled = enabled;
    643   }
    644 
    645   @Override
    646   public boolean getEnabled() {
    647     return m_enabled;
    648   }
    649 
    650   /**
    651    * {@inheritDoc}
    652    */
    653   @Override
    654   public String[] getBeforeGroups() {
    655     return m_beforeGroups;
    656   }
    657 
    658   /**
    659    * {@inheritDoc}
    660    */
    661   @Override
    662   public String[] getAfterGroups() {
    663     return m_afterGroups;
    664   }
    665 
    666   @Override
    667   public void incrementCurrentInvocationCount() {
    668     m_currentInvocationCount.incrementAndGet();
    669   }
    670 
    671   @Override
    672   public int getCurrentInvocationCount() {
    673     return m_currentInvocationCount.get();
    674   }
    675 
    676   @Override
    677   public void setParameterInvocationCount(int n) {
    678     m_parameterInvocationCount = n;
    679   }
    680 
    681   @Override
    682   public int getParameterInvocationCount() {
    683     return m_parameterInvocationCount;
    684   }
    685 
    686   @Override
    687   public abstract ITestNGMethod clone();
    688 
    689   @Override
    690   public IRetryAnalyzer getRetryAnalyzer() {
    691     return m_retryAnalyzer;
    692   }
    693 
    694   @Override
    695   public void setRetryAnalyzer(IRetryAnalyzer retryAnalyzer) {
    696     m_retryAnalyzer = retryAnalyzer;
    697   }
    698 
    699   @Override
    700   public boolean skipFailedInvocations() {
    701     return m_skipFailedInvocations;
    702   }
    703 
    704   @Override
    705   public void setSkipFailedInvocations(boolean s) {
    706     m_skipFailedInvocations = s;
    707   }
    708 
    709   public void setInvocationTimeOut(long timeOut) {
    710     m_invocationTimeOut = timeOut;
    711   }
    712 
    713   @Override
    714   public long getInvocationTimeOut() {
    715     return m_invocationTimeOut;
    716   }
    717 
    718   @Override
    719   public boolean ignoreMissingDependencies() {
    720     return m_ignoreMissingDependencies;
    721   }
    722 
    723   @Override
    724   public void setIgnoreMissingDependencies(boolean i) {
    725     m_ignoreMissingDependencies = i;
    726   }
    727 
    728   @Override
    729   public List<Integer> getInvocationNumbers() {
    730     return m_invocationNumbers;
    731   }
    732 
    733   @Override
    734   public void setInvocationNumbers(List<Integer> numbers) {
    735     m_invocationNumbers = numbers;
    736   }
    737 
    738   @Override
    739   public List<Integer> getFailedInvocationNumbers() {
    740     return m_failedInvocationNumbers;
    741   }
    742 
    743   @Override
    744   public void addFailedInvocationNumber(int number) {
    745     m_failedInvocationNumbers.add(number);
    746   }
    747 
    748   @Override
    749   public int getPriority() {
    750     return m_priority;
    751   }
    752 
    753   @Override
    754   public void setPriority(int priority) {
    755     m_priority = priority;
    756   }
    757 
    758   @Override
    759   public XmlTest getXmlTest() {
    760     return m_xmlTest;
    761   }
    762 
    763   public void setXmlTest(XmlTest xmlTest) {
    764     m_xmlTest = xmlTest;
    765   }
    766 
    767   @Override
    768   public ConstructorOrMethod getConstructorOrMethod() {
    769     return m_method;
    770   }
    771 
    772   @Override
    773   public Map<String, String> findMethodParameters(XmlTest test) {
    774     // Get the test+suite parameters
    775     Map<String, String> result = test.getAllParameters();
    776     for (XmlClass xmlClass: test.getXmlClasses()) {
    777       if (xmlClass.getName().equals(getTestClass().getName())) {
    778         result.putAll(xmlClass.getLocalParameters());
    779         for (XmlInclude include : xmlClass.getIncludedMethods()) {
    780           if (include.getName().equals(getMethodName())) {
    781             result.putAll(include.getLocalParameters());
    782             break;
    783           }
    784         }
    785       }
    786     }
    787 
    788     return result;
    789   }
    790 }
    791