1 package org.testng.xml;
2 
3 import java.io.Serializable;
4 import java.util.Collection;
5 import java.util.HashSet;
6 import java.util.List;
7 import java.util.Map;
8 import java.util.Properties;
9 import java.util.Set;
10 
11 import org.testng.ITestObjectFactory;
12 import org.testng.TestNG;
13 import org.testng.collections.Lists;
14 import org.testng.collections.Maps;
15 import org.testng.reporters.XMLStringBuffer;
16 import org.testng.xml.dom.OnElement;
17 import org.testng.xml.dom.OnElementList;
18 import org.testng.xml.dom.Tag;
19 
20 import static org.testng.collections.CollectionUtils.hasElements;
21 import static org.testng.internal.Utils.isStringNotEmpty;
22 
23 /**
24  * This class describes the tag <suite> in testng.xml.
25  *
26  * @author <a href = "mailto:cedric&#64;beust.com">Cedric Beust</a>
27  * @author <a href = 'mailto:the_mindstorm[at]evolva[dot]ro'>Alexandru Popescu</a>
28  */
29 public class XmlSuite implements Serializable, Cloneable {
30   /** Parallel modes */
31   public enum ParallelMode {
32     TESTS, METHODS, CLASSES, INSTANCES, NONE, TRUE, FALSE;
33 
getValidParallel(String parallel)34     public static XmlSuite.ParallelMode getValidParallel(String parallel) {
35       if (parallel == null) {
36         return null;
37       }
38       try {
39         return XmlSuite.ParallelMode.valueOf(parallel.toUpperCase());
40       } catch (IllegalArgumentException e) {
41         return null;
42       }
43     }
44 
45     @Override
toString()46     public String toString() {
47       return name().toLowerCase();
48     }
49   }
50 
51   /** Configuration failure policy options */
52   public static final String SKIP = "skip";
53   public static final String CONTINUE = "continue";
54 
55   private String m_test;
56 
57   /** The default suite name TODO CQ is this OK as a default name. */
58   private static final String DEFAULT_SUITE_NAME = "Default Suite";
59 
60   /** The suite name (defaults to DEFAULT_SUITE_NAME) */
61   private String m_name = DEFAULT_SUITE_NAME;
62 
63   /** The suite verbose flag. (0 to 10)*/
64   public static final Integer DEFAULT_VERBOSE = 1;
65   private Integer m_verbose = null;
66 
67   public static final ParallelMode DEFAULT_PARALLEL = ParallelMode.FALSE;
68   private ParallelMode m_parallel = DEFAULT_PARALLEL;
69 
70   private String m_parentModule = "";
71   private String m_guiceStage = "";
72 
73   /** Whether to SKIP or CONTINUE to re-attempt failed configuration methods. */
74   public static final String DEFAULT_CONFIG_FAILURE_POLICY = SKIP;
75   private String m_configFailurePolicy = DEFAULT_CONFIG_FAILURE_POLICY;
76 
77   /** JUnit compatibility flag. */
78   public static final Boolean DEFAULT_JUNIT = Boolean.FALSE;
79   private Boolean m_isJUnit = DEFAULT_JUNIT;
80 
81   /** mixed mode flag. */
82   public static final Boolean DEFAULT_MIXED = Boolean.FALSE;
83   private Boolean m_isMixed = DEFAULT_MIXED;
84 
85   public static final Boolean DEFAULT_SKIP_FAILED_INVOCATION_COUNTS = Boolean.FALSE;
86   private Boolean m_skipFailedInvocationCounts = DEFAULT_SKIP_FAILED_INVOCATION_COUNTS;
87 
88   /** The thread count. */
89   public static final Integer DEFAULT_THREAD_COUNT = 5;
90   private int m_threadCount = DEFAULT_THREAD_COUNT;
91 
92   /** Thread count for the data provider pool */
93   public static final Integer DEFAULT_DATA_PROVIDER_THREAD_COUNT = 10;
94   private int m_dataProviderThreadCount = DEFAULT_DATA_PROVIDER_THREAD_COUNT;
95 
96   /** By default, a method failing will cause all instances of that class to skip */
97   public static final Boolean DEFAULT_GROUP_BY_INSTANCES = false;
98   private Boolean m_groupByInstances = DEFAULT_GROUP_BY_INSTANCES;
99 
100   public static final Boolean DEFAULT_ALLOW_RETURN_VALUES = Boolean.FALSE;
101   private Boolean m_allowReturnValues = DEFAULT_ALLOW_RETURN_VALUES;
102 
103   /** The packages containing test classes. */
104   private List<XmlPackage> m_xmlPackages = Lists.newArrayList();
105 
106   /** BeanShell expression. */
107   private String m_expression = null;
108 
109   /** Suite level method selectors. */
110   private List<XmlMethodSelector> m_methodSelectors = Lists.newArrayList();
111 
112   /** Tests in suite. */
113   private List<XmlTest> m_tests = Lists.newArrayList();
114 
115   /** Suite level parameters. */
116   private Map<String, String> m_parameters = Maps.newHashMap();
117 
118   /** Name of the XML file */
119   private String m_fileName;
120 
121   /** Time out for methods/tests */
122   private String m_timeOut;
123 
124   /** List of child XML suite specified using <suite-file> tags */
125   private List<XmlSuite> m_childSuites = Lists.newArrayList();
126 
127   /** Parent XML Suite if this suite was specified in another suite using <suite-file> tag */
128   private XmlSuite m_parentSuite;
129 
130   private List<String> m_suiteFiles = Lists.newArrayList();
131 
132   private ITestObjectFactory m_objectFactory;
133 
134   private List<String> m_listeners = Lists.newArrayList();
135 
136   private static final long serialVersionUID = 4999962288272750226L;
137 
138   public static final String DEFAULT_PRESERVE_ORDER = "true";
139   private String m_preserveOrder = DEFAULT_PRESERVE_ORDER;
140 
141   private List<String> m_includedGroups = Lists.newArrayList();
142   private List<String> m_excludedGroups = Lists.newArrayList();
143   private XmlMethodSelectors m_xmlMethodSelectors;
144 
145   /**
146    * @return the fileName
147    */
getFileName()148   public String getFileName() {
149     return m_fileName;
150   }
151 
152   /**
153    * @param fileName the fileName to set
154    */
setFileName(String fileName)155   public void setFileName(String fileName) {
156     m_fileName = fileName;
157   }
158 
159   /**
160    * Returns the parallel mode.
161    * @return the parallel mode.
162    */
getParallel()163   public ParallelMode getParallel() {
164     return m_parallel;
165   }
166 
167 
getParentModule()168   public String getParentModule() {
169     return m_parentModule;
170   }
171 
getGuiceStage()172   public String getGuiceStage() {
173     return m_guiceStage;
174   }
175 
getObjectFactory()176   public ITestObjectFactory getObjectFactory() {
177     return m_objectFactory;
178   }
179 
setObjectFactory(ITestObjectFactory objectFactory)180   public void setObjectFactory(ITestObjectFactory objectFactory) {
181     m_objectFactory = objectFactory;
182   }
183 
184   /**
185    * @deprecated Use #setParallel(XmlSuite.ParallelMode) instead
186    */
187   @Deprecated
setParallel(String parallel)188   public void setParallel(String parallel) {
189     if (parallel == null) {
190       setParallel((ParallelMode)null);
191     } else {
192       setParallel(XmlSuite.ParallelMode.getValidParallel(parallel));
193     }
194   }
195 
196   /**
197    * Sets the parallel mode
198    * @param parallel the parallel mode
199    */
setParallel(ParallelMode parallel)200   public void setParallel(ParallelMode parallel) {
201     if (parallel == null) {
202       m_parallel = DEFAULT_PARALLEL;
203     } else {
204       m_parallel = parallel;
205     }
206   }
207 
setParentModule(String parentModule)208   public void setParentModule(String parentModule) {
209     m_parentModule = parentModule;
210   }
211 
setGuiceStage(String guiceStage)212   public void setGuiceStage(String guiceStage) {
213     m_guiceStage = guiceStage;
214   }
215 
216   /**
217    * Sets the configuration failure policy.
218    * @param configFailurePolicy the config failure policy
219    */
setConfigFailurePolicy(String configFailurePolicy)220   public void setConfigFailurePolicy(String configFailurePolicy) {
221     m_configFailurePolicy = configFailurePolicy;
222   }
223 
224   /**
225    * Returns the configuration failure policy.
226    * @return the configuration failure policy
227    */
getConfigFailurePolicy()228   public String getConfigFailurePolicy() {
229     return m_configFailurePolicy;
230   }
231 
232 
233   /**
234    * Returns the verbose.
235    * @return the verbose.
236    */
getVerbose()237   public Integer getVerbose() {
238     return m_verbose != null ? m_verbose : TestNG.DEFAULT_VERBOSE;
239   }
240 
241   /**
242    * Set the verbose.
243    * @param verbose The verbose to set.
244    */
setVerbose(Integer verbose)245   public void setVerbose(Integer verbose) {
246     m_verbose = verbose;
247   }
248 
249   /**
250    * Returns the name.
251    * @return the name.
252    */
getName()253   public String getName() {
254     return m_name;
255   }
256 
257   /**
258    * Sets the name.
259    * @param name The name to set.
260    */
setName(String name)261   public void setName(String name) {
262     m_name = name;
263   }
264 
265   /**
266    * Returns the test.
267    * @return the test.
268    */
getTest()269   public String getTest() {
270     return m_test;
271   }
272 
273   /**
274    * Returns the tests.
275    * @return the tests.
276    */
getTests()277   public List<XmlTest> getTests() {
278     return m_tests;
279   }
280 
281   // For YAML
setTests(List<XmlTest> tests)282   public void setTests(List<XmlTest> tests) {
283     m_tests = tests;
284   }
285 
286   /**
287    * Returns the method selectors.
288    *
289    * @return the method selectors.
290    */
getMethodSelectors()291   public List<XmlMethodSelector> getMethodSelectors() {
292     if (m_xmlMethodSelectors != null) {
293       return m_xmlMethodSelectors.getMethodSelectors();
294     } else {
295       // deprecated
296       return m_methodSelectors;
297     }
298   }
299 
300   /**
301    * Sets the method selectors.
302    *
303    * @param methodSelectors the method selectors.
304    */
setMethodSelectors(List<XmlMethodSelector> methodSelectors)305   public void setMethodSelectors(List<XmlMethodSelector> methodSelectors) {
306     m_methodSelectors = Lists.newArrayList(methodSelectors);
307   }
308 
309   /**
310    * Updates the list of parameters that apply to this XML suite. This method
311    * should be invoked any time there is a change in the state of this suite that
312    * would affect the parameter list.<br>
313    * NOTE: Currently being invoked after a parent suite is added or if parameters
314    * for this suite are updated.
315    */
updateParameters()316   private void updateParameters() {
317     /*
318      * Whatever parameters are set by user or via XML, should be updated
319      * using parameters from parent suite, if it exists. Parameters from this
320      * suite override the same named parameters from parent suite.
321      */
322     if (m_parentSuite != null) {
323       Set<String> keySet = m_parentSuite.getParameters().keySet();
324       for (String name : keySet) {
325         if (!m_parameters.containsKey(name)) {
326            m_parameters.put(name, m_parentSuite.getParameter(name));
327         }
328       }
329     }
330   }
331 
332   /**
333    * Sets parameters.
334    * @param parameters the parameters.
335    */
setParameters(Map<String, String> parameters)336   public void setParameters(Map<String, String> parameters) {
337     m_parameters = parameters;
338     updateParameters();
339   }
340 
341   /**
342    * Gets the parameters that apply to tests in this suite.<br>
343    * Set of parameters for a suite is appended with parameters from parent suite.
344    * Also, parameters from this suite override the same named parameters from
345    * parent suite.
346    */
getParameters()347   public Map<String, String> getParameters() {
348     return m_parameters;
349   }
350 
351   /**
352    * @return The parameters defined in this suite and all its XmlTests.
353    */
getAllParameters()354   public Map<String, String> getAllParameters() {
355     Map<String, String> result = Maps.newHashMap();
356     for (Map.Entry<String, String> entry : m_parameters.entrySet()) {
357       result.put(entry.getKey(), entry.getValue());
358     }
359 
360     for (XmlTest test : getTests()) {
361       Map<String, String> tp = test.getLocalParameters();
362       for (Map.Entry<String, String> entry : tp.entrySet()) {
363         result.put(entry.getKey(), entry.getValue());
364       }
365     }
366 
367     return result;
368   }
369 
370   /**
371    * Returns the parameter defined in this suite only.
372    * @param name the parameter name.
373    * @return The parameter defined in this suite only.
374    */
getParameter(String name)375   public String getParameter(String name) {
376     return m_parameters.get(name);
377   }
378 
379   /**
380    * @return The threadCount.
381    */
getThreadCount()382   public int getThreadCount() {
383     return m_threadCount;
384   }
385 
386   /**
387    * Set the thread count.
388    * @param threadCount The thread count to set.
389    */
setThreadCount(int threadCount)390   public void setThreadCount(int threadCount) {
391     m_threadCount = threadCount;
392   }
393 
394   /**
395    * @return The JUnit compatibility flag.
396    */
isJUnit()397   public Boolean isJUnit() {
398     return m_isJUnit;
399   }
400 
401   /**
402    * Sets the JUnit compatibility flag.
403    *
404    * @param isJUnit the JUnit compatibility flag.
405    */
setJUnit(Boolean isJUnit)406   public void setJUnit(Boolean isJUnit) {
407     m_isJUnit = isJUnit;
408   }
409 
410   // For YAML
setJunit(Boolean j)411   public void setJunit(Boolean j) {
412     setJUnit(j);
413   }
414 
skipFailedInvocationCounts()415   public Boolean skipFailedInvocationCounts() {
416     return m_skipFailedInvocationCounts;
417   }
418 
setSkipFailedInvocationCounts(boolean skip)419   public void setSkipFailedInvocationCounts(boolean skip) {
420     m_skipFailedInvocationCounts = skip;
421   }
422 
423   /**
424    * Sets the XML packages.
425    *
426    * @param packages the XML packages.
427    */
setXmlPackages(List<XmlPackage> packages)428   public void setXmlPackages(List<XmlPackage> packages) {
429     m_xmlPackages = Lists.newArrayList(packages);
430   }
431 
432   /**
433    * Returns the XML packages.
434    *
435    * @return the XML packages.
436    */
getXmlPackages()437   public List<XmlPackage> getXmlPackages() {
438     return m_xmlPackages;
439   }
440 
441 
442   // For YAML
getPackages()443   public List<XmlPackage> getPackages() {
444     return getXmlPackages();
445   }
446 
447   @Tag(name = "method-selectors")
setMethodSelectors(XmlMethodSelectors xms)448   public void setMethodSelectors(XmlMethodSelectors xms) {
449     m_xmlMethodSelectors = xms;
450   }
451 
452   // For YAML
setPackages(List<XmlPackage> packages)453   public void setPackages(List<XmlPackage> packages) {
454     setXmlPackages(packages);
455   }
456 
457   /**
458    * @return A String representation of this XML suite.
459    */
toXml()460   public String toXml() {
461     XMLStringBuffer xsb = new XMLStringBuffer();
462     xsb.setDocType("suite SYSTEM \"" + Parser.TESTNG_DTD_URL + '\"');
463     Properties p = new Properties();
464     p.setProperty("name", getName());
465     if (getVerbose() != null) {
466       XmlUtils.setProperty(p, "verbose", getVerbose().toString(), DEFAULT_VERBOSE.toString());
467     }
468     final ParallelMode parallel= getParallel();
469     if(parallel != null && !DEFAULT_PARALLEL.equals(parallel)) {
470       p.setProperty("parallel", parallel.toString());
471     }
472     XmlUtils.setProperty(p, "group-by-instances", String.valueOf(getGroupByInstances()),
473         DEFAULT_GROUP_BY_INSTANCES.toString());
474     XmlUtils.setProperty(p, "configfailurepolicy", getConfigFailurePolicy(),
475         DEFAULT_CONFIG_FAILURE_POLICY);
476     XmlUtils.setProperty(p, "thread-count", String.valueOf(getThreadCount()),
477         DEFAULT_THREAD_COUNT.toString());
478     XmlUtils.setProperty(p, "data-provider-thread-count", String.valueOf(getDataProviderThreadCount()),
479         DEFAULT_DATA_PROVIDER_THREAD_COUNT.toString());
480     if (! DEFAULT_JUNIT.equals(m_isJUnit)) {
481       p.setProperty("junit", m_isJUnit != null ? m_isJUnit.toString() : "false"); // TESTNG-141
482     }
483     XmlUtils.setProperty(p, "skipfailedinvocationcounts", m_skipFailedInvocationCounts.toString(),
484         DEFAULT_SKIP_FAILED_INVOCATION_COUNTS.toString());
485     if(null != m_objectFactory) {
486       p.setProperty("object-factory", m_objectFactory.getClass().getName());
487     }
488     if (isStringNotEmpty(m_parentModule)) {
489       p.setProperty("parent-module", getParentModule());
490     }
491     if (isStringNotEmpty(m_guiceStage)) {
492       p.setProperty("guice-stage", getGuiceStage());
493     }
494     XmlUtils.setProperty(p, "allow-return-values", String.valueOf(getAllowReturnValues()),
495         DEFAULT_ALLOW_RETURN_VALUES.toString());
496     xsb.push("suite", p);
497 
498     XmlUtils.dumpParameters(xsb, m_parameters);
499 
500     if (hasElements(m_listeners)) {
501       xsb.push("listeners");
502       for (String listenerName: m_listeners) {
503         Properties listenerProps = new Properties();
504         listenerProps.setProperty("class-name", listenerName);
505         xsb.addEmptyElement("listener", listenerProps);
506       }
507       xsb.pop("listeners");
508     }
509 
510     if (hasElements(getXmlPackages())) {
511       xsb.push("packages");
512 
513       for (XmlPackage pack : getXmlPackages()) {
514         xsb.getStringBuffer().append(pack.toXml("    "));
515       }
516 
517       xsb.pop("packages");
518     }
519 
520     if (getXmlMethodSelectors() != null) {
521       xsb.getStringBuffer().append(getXmlMethodSelectors().toXml("  "));
522     } else {
523       // deprecated
524       if (hasElements(getMethodSelectors())) {
525         xsb.push("method-selectors");
526         for (XmlMethodSelector selector : getMethodSelectors()) {
527           xsb.getStringBuffer().append(selector.toXml("  "));
528         }
529 
530         xsb.pop("method-selectors");
531       }
532     }
533 
534     List<String> suiteFiles = getSuiteFiles();
535     if (suiteFiles.size() > 0) {
536       xsb.push("suite-files");
537       for (String sf : suiteFiles) {
538         Properties prop = new Properties();
539         prop.setProperty("path", sf);
540         xsb.addEmptyElement("suite-file", prop);
541       }
542       xsb.pop("suite-files");
543     }
544 
545     List<String> included = getIncludedGroups();
546     List<String> excluded = getExcludedGroups();
547     if (hasElements(included) || hasElements(excluded)) {
548       xsb.push("groups");
549       xsb.push("run");
550       for (String g : included) {
551         xsb.addEmptyElement("include", "name", g);
552       }
553       for (String g : excluded) {
554         xsb.addEmptyElement("exclude", "name", g);
555       }
556       xsb.pop("run");
557       xsb.pop("groups");
558     }
559 
560     if (m_xmlGroups != null) {
561       xsb.getStringBuffer().append(m_xmlGroups.toXml("  "));
562     }
563 
564     for (XmlTest test : getTests()) {
565       xsb.getStringBuffer().append(test.toXml("  "));
566     }
567 
568     xsb.pop("suite");
569 
570     return xsb.toXML();
571   }
572 
573   @Tag(name = "method-selectors")
setXmlMethodSelectors(XmlMethodSelectors xms)574   public void setXmlMethodSelectors(XmlMethodSelectors xms) {
575     m_xmlMethodSelectors = xms;
576   }
577 
getXmlMethodSelectors()578   private XmlMethodSelectors getXmlMethodSelectors() {
579     return m_xmlMethodSelectors;
580   }
581 
582   /**
583    * {@inheritDoc}
584    */
585   @Override
toString()586   public String toString() {
587     StringBuffer result = new StringBuffer("[Suite: \"").append( m_name).append( "\" ");
588 
589     for (XmlTest t : m_tests) {
590       result.append("  ").append( t.toString()).append(' ');
591     }
592 
593     for (XmlMethodSelector ms : m_methodSelectors) {
594       result.append(" methodSelector:" + ms);
595     }
596 
597     result.append(']');
598 
599     return result.toString();
600   }
601 
602   /**
603    * Logs to System.out.
604    * @param s the message to log.
605    */
ppp(String s)606   private static void ppp(String s) {
607     System.out.println("[XmlSuite] " + s);
608   }
609 
610   /**
611    * {@inheritDoc}
612    * Note that this is not a full clone:  XmlTest children are not cloned by this
613    * method.
614    */
615   @Override
clone()616   public Object clone() {
617     XmlSuite result = new XmlSuite();
618 
619     result.setExcludedGroups(getExcludedGroups());
620     result.setIncludedGroups(getIncludedGroups());
621     result.setGroupByInstances(getGroupByInstances());
622     result.setGroups(getGroups());
623     result.setMethodSelectors(getXmlMethodSelectors());
624     result.setPackages(getPackages());
625     result.setParentSuite(getParentSuite());
626     result.setPreserveOrder(getPreserveOrder());
627     result.setSuiteFiles(getSuiteFiles());
628     result.setTests(getTests());
629     result.setXmlMethodSelectors(getXmlMethodSelectors());
630     result.setName(getName());
631     result.setFileName(getFileName());
632     result.setListeners(getListeners());
633     result.setParallel(getParallel());
634     result.setParentModule(getParentModule());
635     result.setGuiceStage(getGuiceStage());
636     result.setConfigFailurePolicy(getConfigFailurePolicy());
637     result.setThreadCount(getThreadCount());
638     result.setDataProviderThreadCount(getDataProviderThreadCount());
639     result.setParameters(getAllParameters());
640     result.setVerbose(getVerbose());
641     result.setXmlPackages(getXmlPackages());
642 //    result.setBeanShellExpression(getExpression());
643     result.setMethodSelectors(getMethodSelectors());
644     result.setJUnit(isJUnit()); // TESTNG-141
645     result.setSkipFailedInvocationCounts(skipFailedInvocationCounts());
646     result.setObjectFactory(getObjectFactory());
647     result.setAllowReturnValues(getAllowReturnValues());
648     result.setTimeOut(getTimeOut());
649     return result;
650   }
651 
652   /**
653    * Sets the timeout.
654    *
655    * @param timeOut the timeout.
656    */
setTimeOut(String timeOut)657   public void setTimeOut(String timeOut) {
658     m_timeOut = timeOut;
659   }
660 
661   /**
662    * Returns the timeout.
663    * @return the timeout.
664    */
getTimeOut()665   public String getTimeOut() {
666     return m_timeOut;
667   }
668 
669   /**
670    * Returns the timeout as a long value specifying the default value to be used if
671    * no timeout was specified.
672    *
673    * @param def the the default value to be used if no timeout was specified.
674    * @return the timeout as a long value specifying the default value to be used if
675    * no timeout was specified.
676    */
getTimeOut(long def)677   public long getTimeOut(long def) {
678     long result = def;
679     if (m_timeOut != null) {
680         result = Long.parseLong(m_timeOut);
681     }
682 
683     return result;
684   }
685 
686   /**
687    * Sets the suite files.
688    *
689    * @param files the suite files.
690    */
setSuiteFiles(List<String> files)691   public void setSuiteFiles(List<String> files) {
692     m_suiteFiles = files;
693   }
694 
695   /**
696    * Returns the suite files.
697    * @return the suite files.
698    */
getSuiteFiles()699   public List<String> getSuiteFiles() {
700     return m_suiteFiles;
701   }
702 
setListeners(List<String> listeners)703   public void setListeners(List<String> listeners) {
704     m_listeners = listeners;
705   }
706 
getListeners()707   public List<String> getListeners() {
708     if (m_parentSuite != null) {
709       List<String> listeners = m_parentSuite.getListeners();
710       for (String listener : listeners) {
711         if (!m_listeners.contains(listener)) {
712            m_listeners.add(listener);
713         }
714       }
715     }
716     return m_listeners;
717   }
718 
setDataProviderThreadCount(int count)719   public void setDataProviderThreadCount(int count) {
720     m_dataProviderThreadCount = count;
721   }
722 
getDataProviderThreadCount()723   public int getDataProviderThreadCount() {
724     // org.testng.CommandLineArgs.DATA_PROVIDER_THREAD_COUNT
725     String s = System.getProperty("dataproviderthreadcount");
726     if (s != null) {
727       try {
728         int nthreads = Integer.parseInt(s);
729         return nthreads;
730       } catch(NumberFormatException nfe) {
731         System.err.println("Parsing System property 'dataproviderthreadcount': " + nfe);
732       }
733     }
734     return m_dataProviderThreadCount;
735   }
736 
setParentSuite(XmlSuite parentSuite)737   public void setParentSuite(XmlSuite parentSuite) {
738     m_parentSuite = parentSuite;
739     updateParameters();
740   }
741 
getParentSuite()742   public XmlSuite getParentSuite() {
743     return m_parentSuite;
744   }
745 
getChildSuites()746   public List<XmlSuite> getChildSuites() {
747     return m_childSuites;
748   }
749 
750   @Override
hashCode()751   public int hashCode() {
752     final int prime = 31;
753     int result = 1;
754 //      result = prime * result
755 //          + ((m_childSuites == null) ? 0 : m_childSuites.hashCode());
756     result = prime
757         * result
758         + ((m_configFailurePolicy == null) ? 0 : m_configFailurePolicy
759             .hashCode());
760     result = prime * result + m_dataProviderThreadCount;
761     result = prime * result
762         + ((m_expression == null) ? 0 : m_expression.hashCode());
763     result = prime * result
764         + ((m_fileName == null) ? 0 : m_fileName.hashCode());
765     result = prime * result
766         + ((m_isJUnit == null) ? 0 : m_isJUnit.hashCode());
767     result = prime * result
768         + ((m_listeners == null) ? 0 : m_listeners.hashCode());
769 
770     result = prime * result
771         + ((m_methodSelectors == null) ? 0 : m_methodSelectors.hashCode());
772     result = prime * result + ((m_name == null) ? 0 : m_name.hashCode());
773     result = prime * result
774         + ((m_objectFactory == null) ? 0 : m_objectFactory.hashCode());
775     result = prime * result
776         + ((m_parallel == null) ? 0 : m_parallel.hashCode());
777 //    result = prime * result
778 //        + ((m_parameters == null) ? 0 : m_parameters.hashCode());
779 //      result = prime * result
780 //          + ((m_parentSuite == null) ? 0 : m_parentSuite.hashCode());
781     result = prime
782         * result
783         + ((m_skipFailedInvocationCounts == null) ? 0
784             : m_skipFailedInvocationCounts.hashCode());
785     result = prime * result
786         + ((m_suiteFiles == null) ? 0 : m_suiteFiles.hashCode());
787     result = prime * result + ((m_test == null) ? 0 : m_test.hashCode());
788     result = prime * result + ((m_tests == null) ? 0 : m_tests.hashCode());
789     result = prime * result + m_threadCount;
790     result = prime * result
791         + ((m_timeOut == null) ? 0 : m_timeOut.hashCode());
792     result = prime * result
793         + ((m_verbose == null) ? 0 : m_verbose.hashCode());
794     result = prime * result
795         + ((m_xmlPackages == null) ? 0 : m_xmlPackages.hashCode());
796     return result;
797   }
798 
799   /**
800    * Used to debug equals() bugs.
801    */
f()802   static boolean f() {
803     return false;
804   }
805 
806   @Override
equals(Object obj)807   public boolean equals(Object obj) {
808     if (this == obj) {
809       return true;
810     }
811     if (obj == null) {
812       return f();
813     }
814     if (getClass() != obj.getClass()) {
815       return f();
816     }
817     XmlSuite other = (XmlSuite) obj;
818 //      if (m_childSuites == null) {
819 //        if (other.m_childSuites != null)
820 //          return f();
821 //      } else if (!m_childSuites.equals(other.m_childSuites))
822 //        return f();
823     if (m_configFailurePolicy == null) {
824       if (other.m_configFailurePolicy != null) {
825         return f();
826       }
827     } else if (!m_configFailurePolicy.equals(other.m_configFailurePolicy)) {
828       return f();
829     }
830     if (m_dataProviderThreadCount != other.m_dataProviderThreadCount) {
831       return f();
832     }
833     if (m_expression == null) {
834       if (other.m_expression != null) {
835         return f();
836       }
837     } else if (!m_expression.equals(other.m_expression)) {
838       return f();
839     }
840     if (m_isJUnit == null) {
841       if (other.m_isJUnit != null) {
842         return f();
843       }
844     } else if (!m_isJUnit.equals(other.m_isJUnit)) {
845       return f();
846     }
847     if (m_listeners == null) {
848       if (other.m_listeners != null) {
849         return f();
850       }
851     } else if (!m_listeners.equals(other.m_listeners)) {
852       return f();
853     }
854     if (m_methodSelectors == null) {
855       if (other.m_methodSelectors != null) {
856         return f();
857       }
858     } else if (!m_methodSelectors.equals(other.m_methodSelectors)) {
859       return f();
860     }
861     if (m_name == null) {
862       if (other.m_name != null) {
863         return f();
864       }
865     } else if (!m_name.equals(other.m_name)) {
866       return f();
867     }
868     if (m_objectFactory == null) {
869       if (other.m_objectFactory != null) {
870         return f();
871       }
872     } else if (!m_objectFactory.equals(other.m_objectFactory)) {
873       return f();
874     }
875     if (m_parallel == null) {
876       if (other.m_parallel != null) {
877         return f();
878       }
879     } else if (!m_parallel.equals(other.m_parallel)) {
880       return f();
881     }
882 //    if (m_parameters == null) {
883 //      if (other.m_parameters != null) {
884 //        return f();
885 //      }
886 //    } else if (!m_parameters.equals(other.m_parameters)) {
887 //      return f();
888 //    }
889 //      if (m_parentSuite == null) {
890 //        if (other.m_parentSuite != null)
891 //          return f();
892 //      } else if (!m_parentSuite.equals(other.m_parentSuite))
893 //        return f();
894     if (m_skipFailedInvocationCounts == null) {
895       if (other.m_skipFailedInvocationCounts != null)
896         return f();
897     } else if (!m_skipFailedInvocationCounts
898         .equals(other.m_skipFailedInvocationCounts))
899       return f();
900     if (m_suiteFiles == null) {
901       if (other.m_suiteFiles != null)
902         return f();
903     } else if (!m_suiteFiles.equals(other.m_suiteFiles))
904       return f();
905     if (m_test == null) {
906       if (other.m_test != null)
907         return f();
908     } else if (!m_test.equals(other.m_test))
909       return f();
910     if (m_tests == null) {
911       if (other.m_tests != null)
912         return f();
913     } else if (!m_tests.equals(other.m_tests))
914       return f();
915     if (m_threadCount != other.m_threadCount)
916       return f();
917     if (m_timeOut == null) {
918       if (other.m_timeOut != null)
919         return f();
920     } else if (!m_timeOut.equals(other.m_timeOut))
921       return f();
922     if (m_verbose == null) {
923       if (other.m_verbose != null)
924         return f();
925     } else if (!m_verbose.equals(other.m_verbose))
926       return f();
927     if (m_xmlPackages == null) {
928       if (other.m_xmlPackages != null)
929         return f();
930     } else if (!m_xmlPackages.equals(other.m_xmlPackages))
931       return f();
932     return true;
933   }
934 
935 
936   /**
937    * The DTD sometimes forces certain attributes to receive a default value. Such
938    * a value is considered equal to another one if that other one is null.
939    */
eq(String o1, String o2, String def)940   private boolean eq(String o1, String o2, String def) {
941     boolean result = false;
942     if (o1 == null && o2 == null) result = true;
943     else if (o1 != null) {
944       result = o1.equals(o2) || (def.equals(o1) && o2 == null);
945     }
946     else if (o2 != null) {
947       result = o2.equals(o1) || (def.equals(o2) && o1 == null);
948     }
949     return result;
950   }
951 
setPreserveOrder(String f)952   public void setPreserveOrder(String f) {
953     m_preserveOrder = f;
954   }
955 
getPreserveOrder()956   public String getPreserveOrder() {
957     return m_preserveOrder;
958   }
959 
960   /**
961    * @return Returns the includedGroups.
962    * Note: do not modify the returned value, use {@link #addIncludedGroup(String)}.
963    */
getIncludedGroups()964   public List<String> getIncludedGroups() {
965     if (m_xmlGroups != null) {
966       return m_xmlGroups.getRun().getIncludes();
967     } else {
968       // deprecated
969       return m_includedGroups;
970     }
971   }
972 
addIncludedGroup(String g)973   public void addIncludedGroup(String g) {
974     m_includedGroups.add(g);
975   }
976 
977   /**
978    * @param g
979    */
setIncludedGroups(List<String> g)980   public void setIncludedGroups(List<String> g) {
981     m_includedGroups = g;
982   }
983 
984   /**
985    * @param g The excludedGrousps to set.
986    */
setExcludedGroups(List<String> g)987   public void setExcludedGroups(List<String> g) {
988     m_excludedGroups = g;
989   }
990 
991   /**
992    * @return Returns the excludedGroups.
993    * Note: do not modify the returned value, use {@link #addExcludedGroup(String)}.
994    */
getExcludedGroups()995   public List<String> getExcludedGroups() {
996     if (m_xmlGroups != null) {
997       return m_xmlGroups.getRun().getExcludes();
998     } else {
999       return m_excludedGroups;
1000     }
1001   }
1002 
addExcludedGroup(String g)1003   public void addExcludedGroup(String g) {
1004     m_excludedGroups.add(g);
1005   }
1006 
getGroupByInstances()1007   public Boolean getGroupByInstances() {
1008     return m_groupByInstances;
1009   }
1010 
setGroupByInstances(boolean f)1011   public void setGroupByInstances(boolean f) {
1012     m_groupByInstances = f;
1013   }
1014 
addListener(String listener)1015   public void addListener(String listener) {
1016     m_listeners.add(listener);
1017   }
1018 
getAllowReturnValues()1019   public Boolean getAllowReturnValues() {
1020     return m_allowReturnValues;
1021   }
1022 
setAllowReturnValues(Boolean allowReturnValues)1023   public void setAllowReturnValues(Boolean allowReturnValues) {
1024     m_allowReturnValues = allowReturnValues;
1025   }
1026 
1027   private XmlGroups m_xmlGroups;
1028 
setGroups(XmlGroups xmlGroups)1029   public void setGroups(XmlGroups xmlGroups) {
1030     m_xmlGroups = xmlGroups;
1031   }
1032 
1033   @OnElement(tag = "parameter", attributes = { "name", "value" })
onParameterElement(String name, String value)1034   public void onParameterElement(String name, String value) {
1035     getParameters().put(name, value);
1036   }
1037 
1038   @OnElementList(tag = "listeners", attributes = { "class-name" })
onListenerElement(String className)1039   public void onListenerElement(String className) {
1040     addListener(className);
1041   }
1042 
1043   @OnElementList(tag = "suite-files", attributes = { "path" })
onSuiteFilesElement(String path)1044   public void onSuiteFilesElement(String path) {
1045     getSuiteFiles().add(path);
1046   }
1047 
1048   @OnElementList(tag = "packages", attributes = { "name" })
onPackagesElement(String name)1049   public void onPackagesElement(String name) {
1050     getPackages().add(new XmlPackage(name));
1051   }
1052 
1053 //  @OnElementList(tag = "method-selectors", attributes = { "language", "name", "priority" })
onMethodSelectorElement(String language, String name, String priority)1054   public void onMethodSelectorElement(String language, String name, String priority) {
1055     System.out.println("Language:" + language);
1056   }
1057 
getGroups()1058   public XmlGroups getGroups() {
1059     return m_xmlGroups;
1060   }
1061 
addTest(XmlTest test)1062   public void addTest(XmlTest test) {
1063     getTests().add(test);
1064   }
1065 
getPackageNames()1066   public Collection<String> getPackageNames() {
1067     List<String> result = Lists.newArrayList();
1068     for (XmlPackage p : getPackages()) {
1069       result.add(p.getName());
1070     }
1071     return result;
1072   }
1073 }
1074 
1075