Home | History | Annotate | Download | only in testng
      1 package org.testng;
      2 
      3 import java.lang.annotation.Annotation;
      4 import java.util.ArrayList;
      5 import java.util.Arrays;
      6 import java.util.Collection;
      7 import java.util.Collections;
      8 import java.util.Comparator;
      9 import java.util.Date;
     10 import java.util.EnumSet;
     11 import java.util.List;
     12 import java.util.Map;
     13 import java.util.Set;
     14 import java.util.concurrent.LinkedBlockingQueue;
     15 import java.util.concurrent.TimeUnit;
     16 
     17 import org.testng.annotations.Guice;
     18 import org.testng.annotations.IListenersAnnotation;
     19 import org.testng.collections.ListMultiMap;
     20 import org.testng.collections.Lists;
     21 import org.testng.collections.Maps;
     22 import org.testng.collections.Sets;
     23 import org.testng.internal.Attributes;
     24 import org.testng.internal.ClassHelper;
     25 import org.testng.internal.ClassImpl;
     26 import org.testng.internal.ClassInfoMap;
     27 import org.testng.internal.ConfigurationGroupMethods;
     28 import org.testng.internal.Constants;
     29 import org.testng.internal.DynamicGraph;
     30 import org.testng.internal.DynamicGraph.Status;
     31 import org.testng.internal.IConfiguration;
     32 import org.testng.internal.IInvoker;
     33 import org.testng.internal.ITestResultNotifier;
     34 import org.testng.internal.InvokedMethod;
     35 import org.testng.internal.Invoker;
     36 import org.testng.internal.MethodGroupsHelper;
     37 import org.testng.internal.MethodHelper;
     38 import org.testng.internal.MethodInstance;
     39 import org.testng.internal.ResultMap;
     40 import org.testng.internal.RunInfo;
     41 import org.testng.internal.TestMethodWorker;
     42 import org.testng.internal.TestNGClassFinder;
     43 import org.testng.internal.TestNGMethodFinder;
     44 import org.testng.internal.Utils;
     45 import org.testng.internal.XmlMethodSelector;
     46 import org.testng.internal.annotations.AnnotationHelper;
     47 import org.testng.internal.annotations.IAnnotationFinder;
     48 import org.testng.internal.annotations.IListeners;
     49 import org.testng.internal.thread.graph.GraphThreadPoolExecutor;
     50 import org.testng.internal.thread.graph.IThreadWorkerFactory;
     51 import org.testng.internal.thread.graph.IWorker;
     52 import org.testng.junit.IJUnitTestRunner;
     53 import org.testng.xml.XmlClass;
     54 import org.testng.xml.XmlInclude;
     55 import org.testng.xml.XmlPackage;
     56 import org.testng.xml.XmlSuite;
     57 import org.testng.xml.XmlTest;
     58 
     59 import com.google.inject.Injector;
     60 import com.google.inject.Module;
     61 
     62 /**
     63  * This class takes care of running one Test.
     64  *
     65  * @author Cedric Beust, Apr 26, 2004
     66  */
     67 public class TestRunner
     68     implements ITestContext, ITestResultNotifier, IThreadWorkerFactory<ITestNGMethod>
     69 {
     70   /* generated */
     71   private static final long serialVersionUID = 4247820024988306670L;
     72   private ISuite m_suite;
     73   private XmlTest m_xmlTest;
     74   private String m_testName;
     75 
     76   transient private List<XmlClass> m_testClassesFromXml= null;
     77   transient private List<XmlPackage> m_packageNamesFromXml= null;
     78 
     79   transient private IInvoker m_invoker= null;
     80   transient private IAnnotationFinder m_annotationFinder= null;
     81 
     82   /** ITestListeners support. */
     83   transient private List<ITestListener> m_testListeners = Lists.newArrayList();
     84   transient private Set<IConfigurationListener> m_configurationListeners = Sets.newHashSet();
     85 
     86   transient private IConfigurationListener m_confListener= new ConfigurationListener();
     87   transient private boolean m_skipFailedInvocationCounts;
     88 
     89   transient private Collection<IInvokedMethodListener> m_invokedMethodListeners = Lists.newArrayList();
     90   transient private List<IClassListener> m_classListeners = Lists.newArrayList();
     91 
     92   /**
     93    * All the test methods we found, associated with their respective classes.
     94    * Note that these test methods might belong to different classes.
     95    * We pick which ones to run at runtime.
     96    */
     97   private ITestNGMethod[] m_allTestMethods = new ITestNGMethod[0];
     98 
     99   // Information about this test run
    100 
    101   private Date m_startDate = null;
    102   private Date m_endDate = null;
    103 
    104   /** A map to keep track of Class <-> IClass. */
    105   transient private Map<Class<?>, ITestClass> m_classMap = Maps.newLinkedHashMap();
    106 
    107   /** Where the reports will be created. */
    108   private String m_outputDirectory= Constants.getDefaultValueFor(Constants.PROP_OUTPUT_DIR);
    109 
    110   // The XML method selector (groups/methods included/excluded in XML)
    111   private XmlMethodSelector m_xmlMethodSelector = new XmlMethodSelector();
    112 
    113   private static int m_verbose = 1;
    114 
    115   //
    116   // These next fields contain all the configuration methods found on this class.
    117   // At initialization time, they just contain all the various @Configuration methods
    118   // found in all the classes we are going to run.  When comes the time to run them,
    119   // only a subset of them are run:  those that are enabled and belong on the same class as
    120   // (or a parent of) the test class.
    121   //
    122   /** */
    123   private ITestNGMethod[] m_beforeSuiteMethods = {};
    124   private ITestNGMethod[] m_afterSuiteMethods = {};
    125   private ITestNGMethod[] m_beforeXmlTestMethods = {};
    126   private ITestNGMethod[] m_afterXmlTestMethods = {};
    127   private List<ITestNGMethod> m_excludedMethods = Lists.newArrayList();
    128   private ConfigurationGroupMethods m_groupMethods = null;
    129 
    130   // Meta groups
    131   private Map<String, List<String>> m_metaGroups = Maps.newHashMap();
    132 
    133   // All the tests that were run along with their result
    134   private IResultMap m_passedTests = new ResultMap();
    135   private IResultMap m_failedTests = new ResultMap();
    136   private IResultMap m_failedButWithinSuccessPercentageTests = new ResultMap();
    137   private IResultMap m_skippedTests = new ResultMap();
    138 
    139   private RunInfo m_runInfo= new RunInfo();
    140 
    141   // The host where this test was run, or null if run locally
    142   private String m_host;
    143 
    144   // Defined dynamically depending on <test preserve-order="true/false">
    145   transient private List<IMethodInterceptor> m_methodInterceptors;
    146 
    147   private transient ClassMethodMap m_classMethodMap;
    148   private transient TestNGClassFinder m_testClassFinder;
    149   private transient IConfiguration m_configuration;
    150   private IMethodInterceptor builtinInterceptor;
    151 
    152   protected TestRunner(IConfiguration configuration,
    153                     ISuite suite,
    154                     XmlTest test,
    155                     String outputDirectory,
    156                     IAnnotationFinder finder,
    157                     boolean skipFailedInvocationCounts,
    158                     Collection<IInvokedMethodListener> invokedMethodListeners,
    159                     List<IClassListener> classListeners)
    160   {
    161     init(configuration, suite, test, outputDirectory, finder, skipFailedInvocationCounts,
    162         invokedMethodListeners, classListeners);
    163   }
    164 
    165   public TestRunner(IConfiguration configuration, ISuite suite, XmlTest test,
    166       boolean skipFailedInvocationCounts,
    167       Collection<IInvokedMethodListener> invokedMethodListeners,
    168       List<IClassListener> classListeners) {
    169     init(configuration, suite, test, suite.getOutputDirectory(),
    170         suite.getAnnotationFinder(),
    171         skipFailedInvocationCounts, invokedMethodListeners, classListeners);
    172   }
    173 
    174   private void init(IConfiguration configuration,
    175                     ISuite suite,
    176                     XmlTest test,
    177                     String outputDirectory,
    178                     IAnnotationFinder annotationFinder,
    179                     boolean skipFailedInvocationCounts,
    180                     Collection<IInvokedMethodListener> invokedMethodListeners,
    181                     List<IClassListener> classListeners)
    182   {
    183     m_configuration = configuration;
    184     m_xmlTest= test;
    185     m_suite = suite;
    186     m_testName = test.getName();
    187     m_host = suite.getHost();
    188     m_testClassesFromXml= test.getXmlClasses();
    189     m_skipFailedInvocationCounts = skipFailedInvocationCounts;
    190     setVerbose(test.getVerbose());
    191 
    192 
    193     boolean preserveOrder = "true".equalsIgnoreCase(test.getPreserveOrder());
    194     m_methodInterceptors = new ArrayList<IMethodInterceptor>();
    195     builtinInterceptor = preserveOrder ? new PreserveOrderMethodInterceptor() : new InstanceOrderingMethodInterceptor();
    196 
    197     m_packageNamesFromXml= test.getXmlPackages();
    198     if(null != m_packageNamesFromXml) {
    199       for(XmlPackage xp: m_packageNamesFromXml) {
    200         m_testClassesFromXml.addAll(xp.getXmlClasses());
    201       }
    202     }
    203 
    204     m_annotationFinder= annotationFinder;
    205     m_invokedMethodListeners = invokedMethodListeners;
    206     m_classListeners = classListeners;
    207     m_invoker = new Invoker(m_configuration, this, this, m_suite.getSuiteState(),
    208         m_skipFailedInvocationCounts, invokedMethodListeners, classListeners);
    209 
    210     if (suite.getParallel() != null) {
    211       log(3, "Running the tests in '" + test.getName() + "' with parallel mode:" + suite.getParallel());
    212     }
    213 
    214     setOutputDirectory(outputDirectory);
    215 
    216     // Finish our initialization
    217     init();
    218   }
    219 
    220   public IInvoker getInvoker() {
    221     return m_invoker;
    222   }
    223 
    224   public ITestNGMethod[] getBeforeSuiteMethods() {
    225     return m_beforeSuiteMethods;
    226   }
    227 
    228   public ITestNGMethod[] getAfterSuiteMethods() {
    229     return m_afterSuiteMethods;
    230   }
    231 
    232   public ITestNGMethod[] getBeforeTestConfigurationMethods() {
    233     return m_beforeXmlTestMethods;
    234   }
    235 
    236   public ITestNGMethod[] getAfterTestConfigurationMethods() {
    237     return m_afterXmlTestMethods;
    238   }
    239 
    240   private void init() {
    241     initMetaGroups(m_xmlTest);
    242     initRunInfo(m_xmlTest);
    243 
    244     // Init methods and class map
    245     // JUnit behavior is different and doesn't need this initialization step
    246     if(!m_xmlTest.isJUnit()) {
    247       initMethods();
    248     }
    249 
    250     initListeners();
    251     addConfigurationListener(m_confListener);
    252   }
    253 
    254   private static class ListenerHolder {
    255     private List<Class<? extends ITestNGListener>> listenerClasses;
    256     private Class<? extends ITestNGListenerFactory> listenerFactoryClass;
    257   }
    258 
    259   /**
    260    * @return all the @Listeners annotations found in the current class and its
    261    * superclasses.
    262    */
    263   private ListenerHolder findAllListeners(Class<?> cls) {
    264     ListenerHolder result = new ListenerHolder();
    265     result.listenerClasses = Lists.newArrayList();
    266 
    267     do {
    268       IListenersAnnotation l = m_annotationFinder.findAnnotation(cls, IListenersAnnotation.class);
    269       if (l != null) {
    270         Class<? extends ITestNGListener>[] classes = l.getValue();
    271         for (Class<? extends ITestNGListener> c : classes) {
    272           result.listenerClasses.add(c);
    273 
    274           if (ITestNGListenerFactory.class.isAssignableFrom(c)) {
    275             if (result.listenerFactoryClass == null) {
    276               result.listenerFactoryClass = (Class<? extends ITestNGListenerFactory>) c;
    277             }
    278             else {
    279               throw new TestNGException("Found more than one class implementing" +
    280                   "ITestNGListenerFactory:" + c + " and " + result.listenerFactoryClass);
    281             }
    282           }
    283         }
    284       }
    285       cls = cls.getSuperclass();
    286     } while (cls != Object.class);
    287 
    288     return result;
    289   }
    290 
    291   private void initListeners() {
    292     //
    293     // Find all the listener factories and collect all the listeners requested in a
    294     // @Listeners annotation.
    295     //
    296     Set<Class<? extends ITestNGListener>> listenerClasses = Sets.newHashSet();
    297     Class<? extends ITestNGListenerFactory> listenerFactoryClass = null;
    298 
    299     for (IClass cls : getTestClasses()) {
    300       Class<? extends ITestNGListenerFactory> realClass = cls.getRealClass();
    301       ListenerHolder listenerHolder = findAllListeners(realClass);
    302       if (listenerFactoryClass == null) {
    303         listenerFactoryClass = listenerHolder.listenerFactoryClass;
    304       }
    305       listenerClasses.addAll(listenerHolder.listenerClasses);
    306     }
    307 
    308     //
    309     // Now we have all the listeners collected from @Listeners and at most one
    310     // listener factory collected from a class implementing ITestNGListenerFactory.
    311     // Instantiate all the requested listeners.
    312     //
    313     ITestNGListenerFactory listenerFactory = null;
    314 
    315     // If we found a test listener factory, instantiate it.
    316     try {
    317       if (m_testClassFinder != null) {
    318         IClass ic = m_testClassFinder.getIClass(listenerFactoryClass);
    319         if (ic != null) {
    320           listenerFactory = (ITestNGListenerFactory) ic.getInstances(false)[0];
    321         }
    322       }
    323       if (listenerFactory == null) {
    324         listenerFactory = listenerFactoryClass != null ? listenerFactoryClass.newInstance() : null;
    325       }
    326     }
    327     catch(Exception ex) {
    328       throw new TestNGException("Couldn't instantiate the ITestNGListenerFactory: "
    329           + ex);
    330     }
    331 
    332     // Instantiate all the listeners
    333     for (Class<? extends ITestNGListener> c : listenerClasses) {
    334       Object listener = listenerFactory != null ? listenerFactory.createListener(c) : null;
    335       if (listener == null) {
    336         listener = ClassHelper.newInstance(c);
    337       }
    338 
    339       if (listener instanceof IMethodInterceptor) {
    340         m_methodInterceptors.add((IMethodInterceptor) listener);
    341       }
    342       if (listener instanceof ISuiteListener) {
    343         m_suite.addListener((ISuiteListener) listener);
    344       }
    345       if (listener instanceof IInvokedMethodListener) {
    346         m_suite.addListener((ITestNGListener) listener);
    347       }
    348       if (listener instanceof ITestListener) {
    349         // At this point, the field m_testListeners has already been used in the creation
    350         addTestListener((ITestListener) listener);
    351       }
    352       if (listener instanceof IClassListener) {
    353         m_classListeners.add((IClassListener) listener);
    354       }
    355       if (listener instanceof IConfigurationListener) {
    356         addConfigurationListener((IConfigurationListener) listener);
    357       }
    358       if (listener instanceof IReporter) {
    359         m_suite.addListener((ITestNGListener) listener);
    360       }
    361       if (listener instanceof IConfigurable) {
    362         m_configuration.setConfigurable((IConfigurable) listener);
    363       }
    364       if (listener instanceof IHookable) {
    365         m_configuration.setHookable((IHookable) listener);
    366       }
    367       if (listener instanceof IExecutionListener) {
    368         IExecutionListener iel = (IExecutionListener) listener;
    369         iel.onExecutionStart();
    370         m_configuration.addExecutionListener(iel);
    371       }
    372     }
    373   }
    374 
    375   /**
    376    * Initialize meta groups
    377    */
    378   private void initMetaGroups(XmlTest xmlTest) {
    379     Map<String, List<String>> metaGroups = xmlTest.getMetaGroups();
    380 
    381     for (Map.Entry<String, List<String>> entry : metaGroups.entrySet()) {
    382       addMetaGroup(entry.getKey(), entry.getValue());
    383     }
    384   }
    385 
    386   private void initRunInfo(final XmlTest xmlTest) {
    387     // Groups
    388     m_xmlMethodSelector.setIncludedGroups(createGroups(m_xmlTest.getIncludedGroups()));
    389     m_xmlMethodSelector.setExcludedGroups(createGroups(m_xmlTest.getExcludedGroups()));
    390     m_xmlMethodSelector.setExpression(m_xmlTest.getExpression());
    391 
    392     // Methods
    393     m_xmlMethodSelector.setXmlClasses(m_xmlTest.getXmlClasses());
    394 
    395     m_runInfo.addMethodSelector(m_xmlMethodSelector, 10);
    396 
    397     // Add user-specified method selectors (only class selectors, we can ignore
    398     // script selectors here)
    399     if (null != xmlTest.getMethodSelectors()) {
    400       for (org.testng.xml.XmlMethodSelector selector : xmlTest.getMethodSelectors()) {
    401         if (selector.getClassName() != null) {
    402           IMethodSelector s = ClassHelper.createSelector(selector);
    403 
    404           m_runInfo.addMethodSelector(s, selector.getPriority());
    405         }
    406       }
    407     }
    408   }
    409 
    410   private void initMethods() {
    411 
    412     //
    413     // Calculate all the methods we need to invoke
    414     //
    415     List<ITestNGMethod> beforeClassMethods = Lists.newArrayList();
    416     List<ITestNGMethod> testMethods = Lists.newArrayList();
    417     List<ITestNGMethod> afterClassMethods = Lists.newArrayList();
    418     List<ITestNGMethod> beforeSuiteMethods = Lists.newArrayList();
    419     List<ITestNGMethod> afterSuiteMethods = Lists.newArrayList();
    420     List<ITestNGMethod> beforeXmlTestMethods = Lists.newArrayList();
    421     List<ITestNGMethod> afterXmlTestMethods = Lists.newArrayList();
    422 
    423     ClassInfoMap classMap = new ClassInfoMap(m_testClassesFromXml);
    424     m_testClassFinder= new TestNGClassFinder(classMap,
    425                                              null,
    426                                              m_xmlTest,
    427                                              m_configuration,
    428                                              this);
    429     ITestMethodFinder testMethodFinder
    430       = new TestNGMethodFinder(m_runInfo, m_annotationFinder);
    431 
    432     m_runInfo.setTestMethods(testMethods);
    433 
    434     //
    435     // Initialize TestClasses
    436     //
    437     IClass[] classes = m_testClassFinder.findTestClasses();
    438 
    439     for (IClass ic : classes) {
    440 
    441       // Create TestClass
    442       ITestClass tc = new TestClass(ic,
    443                                    testMethodFinder,
    444                                    m_annotationFinder,
    445                                    m_runInfo,
    446                                    m_xmlTest,
    447                                    classMap.getXmlClass(ic.getRealClass()));
    448       m_classMap.put(ic.getRealClass(), tc);
    449     }
    450 
    451     //
    452     // Calculate groups methods
    453     //
    454     Map<String, List<ITestNGMethod>> beforeGroupMethods =
    455         MethodGroupsHelper.findGroupsMethods(m_classMap.values(), true);
    456     Map<String, List<ITestNGMethod>> afterGroupMethods =
    457         MethodGroupsHelper.findGroupsMethods(m_classMap.values(), false);
    458 
    459     //
    460     // Walk through all the TestClasses, store their method
    461     // and initialize them with the correct ITestClass
    462     //
    463     for (ITestClass tc : m_classMap.values()) {
    464       fixMethodsWithClass(tc.getTestMethods(), tc, testMethods);
    465       fixMethodsWithClass(tc.getBeforeClassMethods(), tc, beforeClassMethods);
    466       fixMethodsWithClass(tc.getBeforeTestMethods(), tc, null);
    467       fixMethodsWithClass(tc.getAfterTestMethods(), tc, null);
    468       fixMethodsWithClass(tc.getAfterClassMethods(), tc, afterClassMethods);
    469       fixMethodsWithClass(tc.getBeforeSuiteMethods(), tc, beforeSuiteMethods);
    470       fixMethodsWithClass(tc.getAfterSuiteMethods(), tc, afterSuiteMethods);
    471       fixMethodsWithClass(tc.getBeforeTestConfigurationMethods(), tc, beforeXmlTestMethods);
    472       fixMethodsWithClass(tc.getAfterTestConfigurationMethods(), tc, afterXmlTestMethods);
    473       fixMethodsWithClass(tc.getBeforeGroupsMethods(), tc,
    474           MethodHelper.uniqueMethodList(beforeGroupMethods.values()));
    475       fixMethodsWithClass(tc.getAfterGroupsMethods(), tc,
    476           MethodHelper.uniqueMethodList(afterGroupMethods.values()));
    477     }
    478 
    479     //
    480     // Sort the methods
    481     //
    482     m_beforeSuiteMethods = MethodHelper.collectAndOrderMethods(beforeSuiteMethods,
    483                                                               false /* forTests */,
    484                                                               m_runInfo,
    485                                                               m_annotationFinder,
    486                                                               true /* unique */,
    487                                                               m_excludedMethods);
    488 
    489     m_beforeXmlTestMethods = MethodHelper.collectAndOrderMethods(beforeXmlTestMethods,
    490                                                               false /* forTests */,
    491                                                               m_runInfo,
    492                                                               m_annotationFinder,
    493                                                               true /* unique (CQ added by me)*/,
    494                                                               m_excludedMethods);
    495 
    496     m_allTestMethods = MethodHelper.collectAndOrderMethods(testMethods,
    497                                                                 true /* forTest? */,
    498                                                                 m_runInfo,
    499                                                                 m_annotationFinder,
    500                                                                 false /* unique */,
    501                                                                 m_excludedMethods);
    502     m_classMethodMap = new ClassMethodMap(testMethods, m_xmlMethodSelector);
    503 
    504     m_afterXmlTestMethods = MethodHelper.collectAndOrderMethods(afterXmlTestMethods,
    505                                                               false /* forTests */,
    506                                                               m_runInfo,
    507                                                               m_annotationFinder,
    508                                                               true /* unique (CQ added by me)*/,
    509                                                               m_excludedMethods);
    510 
    511     m_afterSuiteMethods = MethodHelper.collectAndOrderMethods(afterSuiteMethods,
    512                                                               false /* forTests */,
    513                                                               m_runInfo,
    514                                                               m_annotationFinder,
    515                                                               true /* unique */,
    516                                                               m_excludedMethods);
    517     // shared group methods
    518     m_groupMethods = new ConfigurationGroupMethods(m_allTestMethods, beforeGroupMethods, afterGroupMethods);
    519 
    520 
    521   }
    522 
    523   private void fixMethodsWithClass(ITestNGMethod[] methods,
    524                                    ITestClass testCls,
    525                                    List<ITestNGMethod> methodList) {
    526     for (ITestNGMethod itm : methods) {
    527       itm.setTestClass(testCls);
    528 
    529       if (methodList != null) {
    530         methodList.add(itm);
    531       }
    532     }
    533   }
    534 
    535   public Collection<ITestClass> getTestClasses() {
    536     return m_classMap.values();
    537   }
    538 
    539   public void setTestName(String name) {
    540     m_testName = name;
    541   }
    542 
    543   public void setOutputDirectory(String od) {
    544     m_outputDirectory= od;
    545 //  FIX: empty directories were created
    546 //    if (od == null) { m_outputDirectory = null; return; } //for maven2
    547 //    File file = new File(od);
    548 //    file.mkdirs();
    549 //    m_outputDirectory= file.getAbsolutePath();
    550   }
    551 
    552   private void addMetaGroup(String name, List<String> groupNames) {
    553     m_metaGroups.put(name, groupNames);
    554   }
    555 
    556   /**
    557    * Calculate the transitive closure of all the MetaGroups
    558    *
    559    * @param groups
    560    * @param unfinishedGroups
    561    * @param result           The transitive closure containing all the groups found
    562    */
    563   private void collectGroups(String[] groups,
    564                              List<String> unfinishedGroups,
    565                              Map<String, String> result) {
    566     for (String gn : groups) {
    567       List<String> subGroups = m_metaGroups.get(gn);
    568       if (null != subGroups) {
    569 
    570         for (String sg : subGroups) {
    571           if (null == result.get(sg)) {
    572             result.put(sg, sg);
    573             unfinishedGroups.add(sg);
    574           }
    575         }
    576       }
    577     }
    578   }
    579 
    580   private Map<String, String> createGroups(List<String> groups) {
    581     return createGroups(groups.toArray(new String[groups.size()]));
    582   }
    583 
    584   private Map<String, String> createGroups(String[] groups) {
    585     Map<String, String> result = Maps.newHashMap();
    586 
    587     // Groups that were passed on the command line
    588     for (String group : groups) {
    589       result.put(group, group);
    590     }
    591 
    592     // See if we have any MetaGroups and
    593     // expand them if they match one of the groups
    594     // we have just been passed
    595     List<String> unfinishedGroups = Lists.newArrayList();
    596 
    597     if (m_metaGroups.size() > 0) {
    598       collectGroups(groups, unfinishedGroups, result);
    599 
    600       // Do we need to loop over unfinished groups?
    601       while (unfinishedGroups.size() > 0) {
    602         String[] uGroups = unfinishedGroups.toArray(new String[unfinishedGroups.size()]);
    603         unfinishedGroups = Lists.newArrayList();
    604         collectGroups(uGroups, unfinishedGroups, result);
    605       }
    606     }
    607 
    608     //    Utils.dumpMap(result);
    609     return result;
    610   }
    611 
    612   /**
    613    * The main entry method for TestRunner.
    614    *
    615    * This is where all the hard work is done:
    616    * - Invoke configuration methods
    617    * - Invoke test methods
    618    * - Catch exceptions
    619    * - Collect results
    620    * - Invoke listeners
    621    * - etc...
    622    */
    623   public void run() {
    624     beforeRun();
    625 
    626     try {
    627       XmlTest test= getTest();
    628       if(test.isJUnit()) {
    629         privateRunJUnit(test);
    630       }
    631       else {
    632         privateRun(test);
    633       }
    634     }
    635     finally {
    636       afterRun();
    637     }
    638   }
    639 
    640   /** Before run preparements. */
    641   private void beforeRun() {
    642     //
    643     // Log the start date
    644     //
    645     m_startDate = new Date(System.currentTimeMillis());
    646 
    647     // Log start
    648     logStart();
    649 
    650     // Invoke listeners
    651     fireEvent(true /*start*/);
    652 
    653     // invoke @BeforeTest
    654     ITestNGMethod[] testConfigurationMethods= getBeforeTestConfigurationMethods();
    655     if(null != testConfigurationMethods && testConfigurationMethods.length > 0) {
    656       m_invoker.invokeConfigurations(null,
    657                                      testConfigurationMethods,
    658                                      m_xmlTest.getSuite(),
    659                                      m_xmlTest.getAllParameters(),
    660                                      null, /* no parameter values */
    661                                      null /* instance */);
    662     }
    663   }
    664 
    665   private void privateRunJUnit(XmlTest xmlTest) {
    666     final ClassInfoMap cim = new ClassInfoMap(m_testClassesFromXml, false);
    667     final Set<Class<?>> classes = cim.getClasses();
    668     final List<ITestNGMethod> runMethods = Lists.newArrayList();
    669     List<IWorker<ITestNGMethod>> workers = Lists.newArrayList();
    670     // FIXME: directly referencing JUnitTestRunner which uses JUnit classes
    671     // may result in an class resolution exception under different JVMs
    672     // The resolution process is not specified in the JVM spec with a specific implementation,
    673     // so it can be eager => failure
    674     workers.add(new IWorker<ITestNGMethod>() {
    675       /**
    676        * @see TestMethodWorker#getTimeOut()
    677        */
    678       @Override
    679       public long getTimeOut() {
    680         return 0;
    681       }
    682 
    683       /**
    684        * @see java.lang.Runnable#run()
    685        */
    686       @Override
    687       public void run() {
    688         for(Class<?> tc: classes) {
    689           List<XmlInclude> includedMethods = cim.getXmlClass(tc).getIncludedMethods();
    690           List<String> methods = Lists.newArrayList();
    691           for (XmlInclude inc: includedMethods) {
    692               methods.add(inc.getName());
    693           }
    694           IJUnitTestRunner tr= ClassHelper.createTestRunner(TestRunner.this);
    695           tr.setInvokedMethodListeners(m_invokedMethodListeners);
    696           try {
    697             tr.run(tc, methods.toArray(new String[methods.size()]));
    698           }
    699           catch(Exception ex) {
    700             ex.printStackTrace();
    701           }
    702           finally {
    703             runMethods.addAll(tr.getTestMethods());
    704           }
    705         }
    706       }
    707 
    708       @Override
    709       public List<ITestNGMethod> getTasks() {
    710         throw new TestNGException("JUnit not supported");
    711       }
    712 
    713       @Override
    714       public int getPriority() {
    715         if (m_allTestMethods.length == 1) {
    716           return m_allTestMethods[0].getPriority();
    717         } else {
    718           return 0;
    719         }
    720       }
    721 
    722       @Override
    723       public int compareTo(IWorker<ITestNGMethod> other) {
    724         return getPriority() - other.getPriority();
    725       }
    726     });
    727 
    728     runJUnitWorkers(workers);
    729     m_allTestMethods= runMethods.toArray(new ITestNGMethod[runMethods.size()]);
    730   }
    731 
    732   private static final EnumSet<XmlSuite.ParallelMode> PRIVATE_RUN_PARALLEL_MODES
    733       = EnumSet.of(XmlSuite.ParallelMode.METHODS, XmlSuite.ParallelMode.TRUE,
    734                    XmlSuite.ParallelMode.CLASSES, XmlSuite.ParallelMode.INSTANCES);
    735   /**
    736    * Main method that create a graph of methods and then pass it to the
    737    * graph executor to run them.
    738    */
    739   private void privateRun(XmlTest xmlTest) {
    740     XmlSuite.ParallelMode parallelMode = xmlTest.getParallel();
    741     boolean parallel = PRIVATE_RUN_PARALLEL_MODES.contains(parallelMode);
    742 
    743     {
    744       // parallel
    745       int threadCount = parallel ? xmlTest.getThreadCount() : 1;
    746       // Make sure we create a graph based on the intercepted methods, otherwise an interceptor
    747       // removing methods would cause the graph never to terminate (because it would expect
    748       // termination from methods that never get invoked).
    749       DynamicGraph<ITestNGMethod> graph = createDynamicGraph(intercept(m_allTestMethods));
    750       if (parallel) {
    751         if (graph.getNodeCount() > 0) {
    752           GraphThreadPoolExecutor<ITestNGMethod> executor =
    753                   new GraphThreadPoolExecutor<>(graph, this,
    754                           threadCount, threadCount, 0, TimeUnit.MILLISECONDS,
    755                           new LinkedBlockingQueue<Runnable>());
    756           executor.run();
    757           try {
    758             long timeOut = m_xmlTest.getTimeOut(XmlTest.DEFAULT_TIMEOUT_MS);
    759             Utils.log("TestRunner", 2, "Starting executor for test " + m_xmlTest.getName()
    760                 + " with time out:" + timeOut + " milliseconds.");
    761             executor.awaitTermination(timeOut, TimeUnit.MILLISECONDS);
    762             executor.shutdownNow();
    763           } catch (InterruptedException handled) {
    764             handled.printStackTrace();
    765             Thread.currentThread().interrupt();
    766           }
    767         }
    768       } else {
    769         boolean debug = false;
    770         List<ITestNGMethod> freeNodes = graph.getFreeNodes();
    771         if (debug) {
    772           System.out.println("Free nodes:" + freeNodes);
    773         }
    774 
    775         if (graph.getNodeCount() > 0 && freeNodes.isEmpty()) {
    776           throw new TestNGException("No free nodes found in:" + graph);
    777         }
    778 
    779         while (! freeNodes.isEmpty()) {
    780           List<IWorker<ITestNGMethod>> runnables = createWorkers(freeNodes);
    781           for (IWorker<ITestNGMethod> r : runnables) {
    782             r.run();
    783           }
    784           graph.setStatus(freeNodes, Status.FINISHED);
    785           freeNodes = graph.getFreeNodes();
    786           if (debug) {
    787             System.out.println("Free nodes:" + freeNodes);
    788           }
    789         }
    790       }
    791     }
    792   }
    793 
    794   /**
    795    * Apply the method interceptor (if applicable) to the list of methods.
    796    */
    797   private ITestNGMethod[] intercept(ITestNGMethod[] methods) {
    798     List<IMethodInstance> methodInstances = methodsToMethodInstances(Arrays.asList(methods));
    799 
    800     // add built-in interceptor (PreserveOrderMethodInterceptor or InstanceOrderingMethodInterceptor at the end of the list
    801     m_methodInterceptors.add(builtinInterceptor);
    802     for (IMethodInterceptor m_methodInterceptor : m_methodInterceptors) {
    803       methodInstances = m_methodInterceptor.intercept(methodInstances, this);
    804     }
    805 
    806     List<ITestNGMethod> result = Lists.newArrayList();
    807     for (IMethodInstance imi : methodInstances) {
    808       result.add(imi.getMethod());
    809     }
    810 
    811     //Since an interceptor is involved, we would need to ensure that the ClassMethodMap object is in sync with the
    812     //output of the interceptor, else @AfterClass doesn't get executed at all when interceptors are involved.
    813     //so let's update the current classMethodMap object with the list of methods obtained from the interceptor.
    814     this.m_classMethodMap = new ClassMethodMap(result, null);
    815 
    816     return result.toArray(new ITestNGMethod[result.size()]);
    817   }
    818 
    819   /**
    820    * Create a list of workers to run the methods passed in parameter.
    821    * Each test method is run in its own worker except in the following cases:
    822    * - The method belongs to a class that has @Test(sequential=true)
    823    * - The parallel attribute is set to "classes"
    824    * In both these cases, all the methods belonging to that class will then
    825    * be put in the same worker in order to run in the same thread.
    826    */
    827   @Override
    828   public List<IWorker<ITestNGMethod>> createWorkers(List<ITestNGMethod> methods) {
    829     List<IWorker<ITestNGMethod>> result;
    830     if (XmlSuite.ParallelMode.INSTANCES.equals(m_xmlTest.getParallel())) {
    831       result = createInstanceBasedParallelWorkers(methods);
    832     } else {
    833       result = createClassBasedParallelWorkers(methods);
    834     }
    835     return result;
    836   }
    837 
    838   /**
    839    * Create workers for parallel="classes" and similar cases.
    840    */
    841   private List<IWorker<ITestNGMethod>> createClassBasedParallelWorkers(List<ITestNGMethod> methods) {
    842     List<IWorker<ITestNGMethod>> result = Lists.newArrayList();
    843     // Methods that belong to classes with a sequential=true or parallel=classes
    844     // attribute must all be run in the same worker
    845     Set<Class> sequentialClasses = Sets.newHashSet();
    846     for (ITestNGMethod m : methods) {
    847       Class<? extends ITestClass> cls = m.getRealClass();
    848       org.testng.annotations.ITestAnnotation test =
    849           m_annotationFinder.findAnnotation(cls, org.testng.annotations.ITestAnnotation.class);
    850 
    851       // If either sequential=true or parallel=classes, mark this class sequential
    852       if (test != null && (test.getSequential() || test.getSingleThreaded()) ||
    853           XmlSuite.ParallelMode.CLASSES.equals(m_xmlTest.getParallel())) {
    854         sequentialClasses.add(cls);
    855       }
    856     }
    857 
    858     List<IMethodInstance> methodInstances = Lists.newArrayList();
    859     for (ITestNGMethod tm : methods) {
    860       methodInstances.addAll(methodsToMultipleMethodInstances(tm));
    861     }
    862 
    863 
    864     Map<String, String> params = m_xmlTest.getAllParameters();
    865 
    866     Set<Class<?>> processedClasses = Sets.newHashSet();
    867     for (IMethodInstance im : methodInstances) {
    868       Class<?> c = im.getMethod().getTestClass().getRealClass();
    869       if (sequentialClasses.contains(c)) {
    870         if (!processedClasses.contains(c)) {
    871           processedClasses.add(c);
    872           if (System.getProperty("experimental") != null) {
    873             List<List<IMethodInstance>> instances = createInstances(methodInstances);
    874             for (List<IMethodInstance> inst : instances) {
    875               TestMethodWorker worker = createTestMethodWorker(inst, params, c);
    876               result.add(worker);
    877             }
    878           }
    879           else {
    880             // Sequential class: all methods in one worker
    881             TestMethodWorker worker = createTestMethodWorker(methodInstances, params, c);
    882             result.add(worker);
    883           }
    884         }
    885       }
    886       else {
    887         // Parallel class: each method in its own worker
    888         TestMethodWorker worker = createTestMethodWorker(Arrays.asList(im), params, c);
    889         result.add(worker);
    890       }
    891     }
    892 
    893     // Sort by priorities
    894     Collections.sort(result);
    895     return result;
    896   }
    897 
    898 
    899   /**
    900    * Create workers for parallel="instances".
    901    */
    902   private List<IWorker<ITestNGMethod>>
    903       createInstanceBasedParallelWorkers(List<ITestNGMethod> methods) {
    904     List<IWorker<ITestNGMethod>> result = Lists.newArrayList();
    905     ListMultiMap<Object, ITestNGMethod> lmm = Maps.newListMultiMap();
    906     for (ITestNGMethod m : methods) {
    907       lmm.put(m.getInstance(), m);
    908     }
    909     for (Map.Entry<Object, List<ITestNGMethod>> es : lmm.entrySet()) {
    910       List<IMethodInstance> methodInstances = Lists.newArrayList();
    911       for (ITestNGMethod m : es.getValue()) {
    912         methodInstances.add(new MethodInstance(m));
    913       }
    914       TestMethodWorker tmw = new TestMethodWorker(m_invoker,
    915           methodInstances.toArray(new IMethodInstance[methodInstances.size()]),
    916           m_xmlTest.getSuite(),
    917           m_xmlTest.getAllParameters(),
    918           m_groupMethods,
    919           m_classMethodMap,
    920           this,
    921           m_classListeners);
    922       result.add(tmw);
    923     }
    924 
    925     return result;
    926   }
    927 
    928   private List<List<IMethodInstance>> createInstances(List<IMethodInstance> methodInstances) {
    929     Map<Object, List<IMethodInstance>> map = Maps.newHashMap();
    930 //    MapList<IMethodInstance[], Object> map = new MapList<IMethodInstance[], Object>();
    931     for (IMethodInstance imi : methodInstances) {
    932       for (Object o : imi.getInstances()) {
    933         System.out.println(o);
    934         List<IMethodInstance> l = map.get(o);
    935         if (l == null) {
    936           l = Lists.newArrayList();
    937           map.put(o, l);
    938         }
    939         l.add(imi);
    940       }
    941 //      for (Object instance : imi.getInstances()) {
    942 //        map.put(imi, instance);
    943 //      }
    944     }
    945 //    return map.getKeys();
    946 //    System.out.println(map);
    947     return new ArrayList<>(map.values());
    948   }
    949 
    950   private TestMethodWorker createTestMethodWorker(
    951       List<IMethodInstance> methodInstances, Map<String, String> params,
    952       Class<?> c) {
    953     return new TestMethodWorker(m_invoker,
    954         findClasses(methodInstances, c),
    955         m_xmlTest.getSuite(),
    956         params,
    957         m_groupMethods,
    958         m_classMethodMap,
    959         this,
    960         m_classListeners);
    961   }
    962 
    963   private IMethodInstance[] findClasses(List<IMethodInstance> methodInstances, Class<?> c) {
    964     List<IMethodInstance> result = Lists.newArrayList();
    965     for (IMethodInstance mi : methodInstances) {
    966       if (mi.getMethod().getTestClass().getRealClass() == c) {
    967         result.add(mi);
    968       }
    969     }
    970     return result.toArray(new IMethodInstance[result.size()]);
    971   }
    972 
    973   /**
    974    * @@@ remove this
    975    */
    976   private List<MethodInstance> methodsToMultipleMethodInstances(ITestNGMethod... sl) {
    977     List<MethodInstance> vResult = Lists.newArrayList();
    978     for (ITestNGMethod m : sl) {
    979       vResult.add(new MethodInstance(m));
    980     }
    981 
    982     return vResult;
    983   }
    984 
    985   private List<IMethodInstance> methodsToMethodInstances(List<ITestNGMethod> sl) {
    986     List<IMethodInstance> result = new ArrayList<>();
    987       for (ITestNGMethod iTestNGMethod : sl) {
    988         result.add(new MethodInstance(iTestNGMethod));
    989       }
    990     return result;
    991   }
    992 
    993   //
    994   // Invoke the workers
    995   //
    996   private static final EnumSet<XmlSuite.ParallelMode> WORKERS_PARALLEL_MODES
    997       = EnumSet.of(XmlSuite.ParallelMode.METHODS, XmlSuite.ParallelMode.TRUE,
    998                    XmlSuite.ParallelMode.CLASSES);
    999   private void runJUnitWorkers(List<? extends IWorker<ITestNGMethod>> workers) {
   1000       //
   1001       // Sequential run
   1002       //
   1003       for (IWorker<ITestNGMethod> tmw : workers) {
   1004         tmw.run();
   1005       }
   1006   }
   1007 
   1008   private void afterRun() {
   1009     // invoke @AfterTest
   1010     ITestNGMethod[] testConfigurationMethods= getAfterTestConfigurationMethods();
   1011     if(null != testConfigurationMethods && testConfigurationMethods.length > 0) {
   1012       m_invoker.invokeConfigurations(null,
   1013                                      testConfigurationMethods,
   1014                                      m_xmlTest.getSuite(),
   1015                                      m_xmlTest.getAllParameters(),
   1016                                      null, /* no parameter values */
   1017                                      null /* instance */);
   1018     }
   1019 
   1020     //
   1021     // Log the end date
   1022     //
   1023     m_endDate = new Date(System.currentTimeMillis());
   1024 
   1025     if (getVerbose() >= 3) {
   1026       dumpInvokedMethods();
   1027     }
   1028 
   1029     // Invoke listeners
   1030     fireEvent(false /*stop*/);
   1031 
   1032     // Statistics
   1033 //    logResults();
   1034   }
   1035 
   1036   private DynamicGraph<ITestNGMethod> createDynamicGraph(ITestNGMethod[] methods) {
   1037     DynamicGraph<ITestNGMethod> result = new DynamicGraph<>();
   1038     result.setComparator(new Comparator<ITestNGMethod>() {
   1039       @Override
   1040       public int compare(ITestNGMethod o1, ITestNGMethod o2) {
   1041         return o1.getPriority() - o2.getPriority();
   1042       }
   1043     });
   1044 
   1045     DependencyMap dependencyMap = new DependencyMap(methods);
   1046 
   1047     // Keep track of whether we have group dependencies. If we do, preserve-order needs
   1048     // to be ignored since group dependencies create inter-class dependencies which can
   1049     // end up creating cycles when combined with preserve-order.
   1050     boolean hasDependencies = false;
   1051     for (ITestNGMethod m : methods) {
   1052       result.addNode(m);
   1053 
   1054       // Dependent methods
   1055       {
   1056         String[] dependentMethods = m.getMethodsDependedUpon();
   1057         if (dependentMethods != null) {
   1058           for (String d : dependentMethods) {
   1059             ITestNGMethod dm = dependencyMap.getMethodDependingOn(d, m);
   1060             if (m != dm){
   1061             	result.addEdge(m, dm);
   1062             }
   1063           }
   1064         }
   1065       }
   1066 
   1067       // Dependent groups
   1068       {
   1069         String[] dependentGroups = m.getGroupsDependedUpon();
   1070         for (String d : dependentGroups) {
   1071           hasDependencies = true;
   1072           List<ITestNGMethod> dg = dependencyMap.getMethodsThatBelongTo(d, m);
   1073           if (dg == null) {
   1074             throw new TestNGException("Method \"" + m
   1075                 + "\" depends on nonexistent group \"" + d + "\"");
   1076           }
   1077           for (ITestNGMethod ddm : dg) {
   1078             result.addEdge(m, ddm);
   1079           }
   1080         }
   1081       }
   1082     }
   1083 
   1084     // Preserve order
   1085     // Don't preserve the ordering if we're running in parallel, otherwise the suite will
   1086     // create multiple threads but these threads will be created one after the other,
   1087     // giving the impression of parallelism (multiple thread id's) while still running
   1088     // sequentially.
   1089     if (! hasDependencies
   1090         && getCurrentXmlTest().getParallel() == XmlSuite.ParallelMode.FALSE
   1091         && "true".equalsIgnoreCase(getCurrentXmlTest().getPreserveOrder())) {
   1092       // If preserve-order was specified and the class order is A, B
   1093       // create a new set of dependencies where each method of B depends
   1094       // on all the methods of A
   1095       ListMultiMap<ITestNGMethod, ITestNGMethod> classDependencies
   1096           = createClassDependencies(methods, getCurrentXmlTest());
   1097 
   1098       for (Map.Entry<ITestNGMethod, List<ITestNGMethod>> es : classDependencies.entrySet()) {
   1099         for (ITestNGMethod dm : es.getValue()) {
   1100           result.addEdge(dm, es.getKey());
   1101         }
   1102       }
   1103     }
   1104 
   1105     // Group by instances
   1106     if (getCurrentXmlTest().getGroupByInstances()) {
   1107       ListMultiMap<ITestNGMethod, ITestNGMethod> instanceDependencies
   1108           = createInstanceDependencies(methods, getCurrentXmlTest());
   1109 
   1110       for (Map.Entry<ITestNGMethod, List<ITestNGMethod>> es : instanceDependencies.entrySet()) {
   1111         for (ITestNGMethod dm : es.getValue()) {
   1112           result.addEdge(dm, es.getKey());
   1113         }
   1114       }
   1115 
   1116     }
   1117 
   1118     return result;
   1119   }
   1120 
   1121   private ListMultiMap<ITestNGMethod, ITestNGMethod> createInstanceDependencies(
   1122       ITestNGMethod[] methods, XmlTest currentXmlTest)
   1123   {
   1124     ListMultiMap<Object, ITestNGMethod> instanceMap = Maps.newListMultiMap();
   1125     for (ITestNGMethod m : methods) {
   1126       instanceMap.put(m.getInstance(), m);
   1127     }
   1128 
   1129     ListMultiMap<ITestNGMethod, ITestNGMethod> result = Maps.newListMultiMap();
   1130     Object previousInstance = null;
   1131     for (Map.Entry<Object, List<ITestNGMethod>> es : instanceMap.entrySet()) {
   1132       if (previousInstance == null) {
   1133         previousInstance = es.getKey();
   1134       } else {
   1135         List<ITestNGMethod> previousMethods = instanceMap.get(previousInstance);
   1136         Object currentInstance = es.getKey();
   1137         List<ITestNGMethod> currentMethods = instanceMap.get(currentInstance);
   1138         // Make all the methods from the current instance depend on the methods of
   1139         // the previous instance
   1140         for (ITestNGMethod cm : currentMethods) {
   1141           for (ITestNGMethod pm : previousMethods) {
   1142             result.put(cm, pm);
   1143           }
   1144         }
   1145         previousInstance = currentInstance;
   1146       }
   1147     }
   1148 
   1149     return result;
   1150   }
   1151 
   1152   private ListMultiMap<ITestNGMethod, ITestNGMethod> createClassDependencies(
   1153       ITestNGMethod[] methods, XmlTest test)
   1154   {
   1155     Map<String, List<ITestNGMethod>> classes = Maps.newHashMap();
   1156     // Note: use a List here to preserve the ordering but make sure
   1157     // we don't add the same class twice
   1158     List<XmlClass> sortedClasses = Lists.newArrayList();
   1159 
   1160     for (XmlClass c : test.getXmlClasses()) {
   1161       classes.put(c.getName(), new ArrayList<ITestNGMethod>());
   1162       if (! sortedClasses.contains(c)) sortedClasses.add(c);
   1163     }
   1164 
   1165     // Sort the classes based on their order of appearance in the XML
   1166     Collections.sort(sortedClasses, new Comparator<XmlClass>() {
   1167       @Override
   1168       public int compare(XmlClass arg0, XmlClass arg1) {
   1169         return arg0.getIndex() - arg1.getIndex();
   1170       }
   1171     });
   1172 
   1173     Map<String, Integer> indexedClasses1 = Maps.newHashMap();
   1174     Map<Integer, String> indexedClasses2 = Maps.newHashMap();
   1175     int i = 0;
   1176     for (XmlClass c : sortedClasses) {
   1177       indexedClasses1.put(c.getName(), i);
   1178       indexedClasses2.put(i, c.getName());
   1179       i++;
   1180     }
   1181 
   1182     ListMultiMap<String, ITestNGMethod> methodsFromClass = Maps.newListMultiMap();
   1183     for (ITestNGMethod m : methods) {
   1184       methodsFromClass.put(m.getTestClass().getName(), m);
   1185     }
   1186 
   1187     ListMultiMap<ITestNGMethod, ITestNGMethod> result = Maps.newListMultiMap();
   1188     for (ITestNGMethod m : methods) {
   1189       String name = m.getTestClass().getName();
   1190       Integer index = indexedClasses1.get(name);
   1191       // The index could be null if the classes listed in the XML are different
   1192       // from the methods being run (e.g. the .xml only contains a factory that
   1193       // instantiates methods from a different class). In this case, we cannot
   1194       // perform any ordering.
   1195       if (index != null && index > 0) {
   1196         // Make this method depend on all the methods of the class in the previous
   1197         // index
   1198         String classDependedUpon = indexedClasses2.get(index - 1);
   1199         List<ITestNGMethod> methodsDependedUpon = methodsFromClass.get(classDependedUpon);
   1200         if (methodsDependedUpon != null) {
   1201           for (ITestNGMethod mdu : methodsDependedUpon) {
   1202             result.put(mdu, m);
   1203           }
   1204         }
   1205       }
   1206     }
   1207 
   1208     return result;
   1209   }
   1210 
   1211   /**
   1212    * Logs the beginning of the {@link #beforeRun()} .
   1213    */
   1214   private void logStart() {
   1215     log(3,
   1216         "Running test " + m_testName + " on " + m_classMap.size() + " " + " classes, "
   1217         + " included groups:[" + mapToString(m_xmlMethodSelector.getIncludedGroups())
   1218         + "] excluded groups:[" + mapToString(m_xmlMethodSelector.getExcludedGroups()) + "]");
   1219 
   1220     if (getVerbose() >= 3) {
   1221       for (ITestClass tc : m_classMap.values()) {
   1222         ((TestClass) tc).dump();
   1223       }
   1224     }
   1225   }
   1226 
   1227   /**
   1228    * Trigger the start/finish event.
   1229    *
   1230    * @param isStart <tt>true</tt> if the event is for start, <tt>false</tt> if the
   1231    *                event is for finish
   1232    */
   1233   private void fireEvent(boolean isStart) {
   1234     for (ITestListener itl : m_testListeners) {
   1235       if (isStart) {
   1236         itl.onStart(this);
   1237       }
   1238       else {
   1239         itl.onFinish(this);
   1240       }
   1241     }
   1242   }
   1243 
   1244   /////
   1245   // ITestContext
   1246   //
   1247   @Override
   1248   public String getName() {
   1249     return m_testName;
   1250   }
   1251 
   1252   /**
   1253    * @return Returns the startDate.
   1254    */
   1255   @Override
   1256   public Date getStartDate() {
   1257     return m_startDate;
   1258   }
   1259 
   1260   /**
   1261    * @return Returns the endDate.
   1262    */
   1263   @Override
   1264   public Date getEndDate() {
   1265     return m_endDate;
   1266   }
   1267 
   1268   @Override
   1269   public IResultMap getPassedTests() {
   1270     return m_passedTests;
   1271   }
   1272 
   1273   @Override
   1274   public IResultMap getSkippedTests() {
   1275     return m_skippedTests;
   1276   }
   1277 
   1278   @Override
   1279   public IResultMap getFailedTests() {
   1280     return m_failedTests;
   1281   }
   1282 
   1283   @Override
   1284   public IResultMap getFailedButWithinSuccessPercentageTests() {
   1285     return m_failedButWithinSuccessPercentageTests;
   1286   }
   1287 
   1288   @Override
   1289   public String[] getIncludedGroups() {
   1290     Map<String, String> ig= m_xmlMethodSelector.getIncludedGroups();
   1291     String[] result= ig.values().toArray((new String[ig.size()]));
   1292 
   1293     return result;
   1294   }
   1295 
   1296   @Override
   1297   public String[] getExcludedGroups() {
   1298     Map<String, String> eg= m_xmlMethodSelector.getExcludedGroups();
   1299     String[] result= eg.values().toArray((new String[eg.size()]));
   1300 
   1301     return result;
   1302   }
   1303 
   1304   @Override
   1305   public String getOutputDirectory() {
   1306     return m_outputDirectory;
   1307   }
   1308 
   1309   /**
   1310    * @return Returns the suite.
   1311    */
   1312   @Override
   1313   public ISuite getSuite() {
   1314     return m_suite;
   1315   }
   1316 
   1317   @Override
   1318   public ITestNGMethod[] getAllTestMethods() {
   1319     return m_allTestMethods;
   1320   }
   1321 
   1322 
   1323   @Override
   1324   public String getHost() {
   1325     return m_host;
   1326   }
   1327 
   1328   @Override
   1329   public Collection<ITestNGMethod> getExcludedMethods() {
   1330     Map<ITestNGMethod, ITestNGMethod> vResult = Maps.newHashMap();
   1331 
   1332     for (ITestNGMethod m : m_excludedMethods) {
   1333       vResult.put(m, m);
   1334     }
   1335 
   1336     return vResult.keySet();
   1337   }
   1338 
   1339   /**
   1340    * @see org.testng.ITestContext#getFailedConfigurations()
   1341    */
   1342   @Override
   1343   public IResultMap getFailedConfigurations() {
   1344     return m_failedConfigurations;
   1345   }
   1346 
   1347   /**
   1348    * @see org.testng.ITestContext#getPassedConfigurations()
   1349    */
   1350   @Override
   1351   public IResultMap getPassedConfigurations() {
   1352     return m_passedConfigurations;
   1353   }
   1354 
   1355   /**
   1356    * @see org.testng.ITestContext#getSkippedConfigurations()
   1357    */
   1358   @Override
   1359   public IResultMap getSkippedConfigurations() {
   1360     return m_skippedConfigurations;
   1361   }
   1362 
   1363   //
   1364   // ITestContext
   1365   /////
   1366 
   1367   /////
   1368   // ITestResultNotifier
   1369   //
   1370 
   1371   @Override
   1372   public void addPassedTest(ITestNGMethod tm, ITestResult tr) {
   1373     m_passedTests.addResult(tr, tm);
   1374   }
   1375 
   1376   @Override
   1377   public Set<ITestResult> getPassedTests(ITestNGMethod tm) {
   1378     return m_passedTests.getResults(tm);
   1379   }
   1380 
   1381   @Override
   1382   public Set<ITestResult> getFailedTests(ITestNGMethod tm) {
   1383     return m_failedTests.getResults(tm);
   1384   }
   1385 
   1386   @Override
   1387   public Set<ITestResult> getSkippedTests(ITestNGMethod tm) {
   1388     return m_skippedTests.getResults(tm);
   1389   }
   1390 
   1391   @Override
   1392   public void addSkippedTest(ITestNGMethod tm, ITestResult tr) {
   1393     m_skippedTests.addResult(tr, tm);
   1394   }
   1395 
   1396   @Override
   1397   public void addInvokedMethod(InvokedMethod im) {
   1398     synchronized(m_invokedMethods) {
   1399       m_invokedMethods.add(im);
   1400     }
   1401   }
   1402 
   1403   @Override
   1404   public void addFailedTest(ITestNGMethod testMethod, ITestResult result) {
   1405     logFailedTest(testMethod, result, false /* withinSuccessPercentage */);
   1406   }
   1407 
   1408   @Override
   1409   public void addFailedButWithinSuccessPercentageTest(ITestNGMethod testMethod,
   1410                                                       ITestResult result) {
   1411     logFailedTest(testMethod, result, true /* withinSuccessPercentage */);
   1412   }
   1413 
   1414   @Override
   1415   public XmlTest getTest() {
   1416     return m_xmlTest;
   1417   }
   1418 
   1419   @Override
   1420   public List<ITestListener> getTestListeners() {
   1421     return m_testListeners;
   1422   }
   1423 
   1424   @Override
   1425   public List<IConfigurationListener> getConfigurationListeners() {
   1426     return Lists.<IConfigurationListener>newArrayList(m_configurationListeners);
   1427   }
   1428   //
   1429   // ITestResultNotifier
   1430   /////
   1431 
   1432   private void logFailedTest(ITestNGMethod method,
   1433                              ITestResult tr,
   1434                              boolean withinSuccessPercentage) {
   1435     /*
   1436      * We should not remove a passed method from m_passedTests so that we can
   1437      * account for the passed instances of this test method.
   1438      */
   1439     //m_passedTests.removeResult(method);
   1440     if (withinSuccessPercentage) {
   1441       m_failedButWithinSuccessPercentageTests.addResult(tr, method);
   1442     }
   1443     else {
   1444       m_failedTests.addResult(tr, method);
   1445     }
   1446   }
   1447 
   1448   private String mapToString(Map<?, ?> m) {
   1449     StringBuffer result= new StringBuffer();
   1450     for (Object o : m.values()) {
   1451       result.append(o.toString()).append(" ");
   1452     }
   1453 
   1454     return result.toString();
   1455   }
   1456 
   1457   private void log(int level, String s) {
   1458     Utils.log("TestRunner", level, s);
   1459   }
   1460 
   1461   public static int getVerbose() {
   1462     return m_verbose;
   1463   }
   1464 
   1465   public void setVerbose(int n) {
   1466     m_verbose = n;
   1467   }
   1468 
   1469   private void log(String s) {
   1470     Utils.log("TestRunner", 2, s);
   1471   }
   1472 
   1473   /////
   1474   // Listeners
   1475   //
   1476   public void addListener(Object listener) {
   1477     if(listener instanceof ITestListener) {
   1478       addTestListener((ITestListener) listener);
   1479     }
   1480     if(listener instanceof IConfigurationListener) {
   1481       addConfigurationListener((IConfigurationListener) listener);
   1482     }
   1483     if(listener instanceof IClassListener) {
   1484       addClassListener((IClassListener) listener);
   1485     }
   1486   }
   1487 
   1488   public void addTestListener(ITestListener il) {
   1489     m_testListeners.add(il);
   1490   }
   1491 
   1492   public void addClassListener(IClassListener cl) {
   1493     m_classListeners.add(cl);
   1494   }
   1495 
   1496   void addConfigurationListener(IConfigurationListener icl) {
   1497     m_configurationListeners.add(icl);
   1498   }
   1499   //
   1500   // Listeners
   1501   /////
   1502 
   1503   private final List<InvokedMethod> m_invokedMethods = Lists.newArrayList();
   1504 
   1505   private void dumpInvokedMethods() {
   1506     System.out.println("===== Invoked methods");
   1507     for (IInvokedMethod im : m_invokedMethods) {
   1508       if (im.isTestMethod()) {
   1509         System.out.print("    ");
   1510       }
   1511       else if (im.isConfigurationMethod()) {
   1512         System.out.print("  ");
   1513       }
   1514       else {
   1515         continue;
   1516       }
   1517       System.out.println("" + im);
   1518     }
   1519     System.out.println("=====");
   1520   }
   1521 
   1522   public List<ITestNGMethod> getInvokedMethods() {
   1523     List<ITestNGMethod> result= Lists.newArrayList();
   1524     synchronized(m_invokedMethods) {
   1525       for (IInvokedMethod im : m_invokedMethods) {
   1526         ITestNGMethod tm= im.getTestMethod();
   1527         tm.setDate(im.getDate());
   1528         result.add(tm);
   1529       }
   1530     }
   1531 
   1532     return result;
   1533   }
   1534 
   1535   private IResultMap m_passedConfigurations= new ResultMap();
   1536   private IResultMap m_skippedConfigurations= new ResultMap();
   1537   private IResultMap m_failedConfigurations= new ResultMap();
   1538 
   1539   private class ConfigurationListener implements IConfigurationListener2 {
   1540     @Override
   1541     public void beforeConfiguration(ITestResult tr) {
   1542     }
   1543 
   1544     @Override
   1545     public void onConfigurationFailure(ITestResult itr) {
   1546       m_failedConfigurations.addResult(itr, itr.getMethod());
   1547     }
   1548 
   1549     @Override
   1550     public void onConfigurationSkip(ITestResult itr) {
   1551       m_skippedConfigurations.addResult(itr, itr.getMethod());
   1552     }
   1553 
   1554     @Override
   1555     public void onConfigurationSuccess(ITestResult itr) {
   1556       m_passedConfigurations.addResult(itr, itr.getMethod());
   1557     }
   1558   }
   1559 
   1560   @Deprecated
   1561   public void setMethodInterceptor(IMethodInterceptor methodInterceptor){
   1562     m_methodInterceptors.add(methodInterceptor);
   1563   }
   1564 
   1565   public void addMethodInterceptor(IMethodInterceptor methodInterceptor){
   1566     m_methodInterceptors.add(methodInterceptor);
   1567   }
   1568 
   1569   @Override
   1570   public XmlTest getCurrentXmlTest() {
   1571     return m_xmlTest;
   1572   }
   1573 
   1574   private IAttributes m_attributes = new Attributes();
   1575 
   1576   @Override
   1577   public Object getAttribute(String name) {
   1578     return m_attributes.getAttribute(name);
   1579   }
   1580 
   1581   @Override
   1582   public void setAttribute(String name, Object value) {
   1583     m_attributes.setAttribute(name, value);
   1584   }
   1585 
   1586   @Override
   1587   public Set<String> getAttributeNames() {
   1588     return m_attributes.getAttributeNames();
   1589   }
   1590 
   1591   @Override
   1592   public Object removeAttribute(String name) {
   1593     return m_attributes.removeAttribute(name);
   1594   }
   1595 
   1596   private ListMultiMap<Class<? extends Module>, Module> m_guiceModules = Maps.newListMultiMap();
   1597 
   1598   @Override
   1599   public List<Module> getGuiceModules(Class<? extends Module> cls) {
   1600     List<Module> result = m_guiceModules.get(cls);
   1601     return result;
   1602   }
   1603 
   1604   private void addGuiceModule(Class<? extends Module> cls, Module module) {
   1605     m_guiceModules.put(cls, module);
   1606   }
   1607 
   1608   private Map<List<Module>, Injector> m_injectors = Maps.newHashMap();
   1609 
   1610   @Override
   1611   public Injector getInjector(List<Module> moduleInstances) {
   1612     return m_injectors .get(moduleInstances);
   1613   }
   1614 
   1615   @Override
   1616   public Injector getInjector(IClass iClass) {
   1617     Annotation annotation = AnnotationHelper.findAnnotationSuperClasses(Guice.class, iClass.getRealClass());
   1618     if (annotation == null) return null;
   1619     if (iClass instanceof TestClass) {
   1620       iClass = ((TestClass)iClass).getIClass();
   1621     }
   1622     if (!(iClass instanceof ClassImpl)) return null;
   1623     Injector parentInjector = ((ClassImpl)iClass).getParentInjector();
   1624 
   1625     Guice guice = (Guice) annotation;
   1626     List<Module> moduleInstances = Lists.newArrayList(getModules(guice, parentInjector, iClass.getRealClass()));
   1627 
   1628     // Reuse the previous injector, if any
   1629     Injector injector = getInjector(moduleInstances);
   1630     if (injector == null) {
   1631       injector = parentInjector.createChildInjector(moduleInstances);
   1632       addInjector(moduleInstances, injector);
   1633     }
   1634     return injector;
   1635   }
   1636 
   1637   private Module[] getModules(Guice guice, Injector parentInjector, Class<?> testClass) {
   1638     List<Module> result = Lists.newArrayList();
   1639     for (Class<? extends Module> moduleClass : guice.modules()) {
   1640       List<Module> modules = getGuiceModules(moduleClass);
   1641       if (modules != null && modules.size() > 0) {
   1642         result.addAll(modules);
   1643       } else {
   1644         Module instance = parentInjector.getInstance(moduleClass);
   1645         result.add(instance);
   1646         addGuiceModule(moduleClass, instance);
   1647       }
   1648     }
   1649     Class<? extends IModuleFactory> factory = guice.moduleFactory();
   1650     if (factory != IModuleFactory.class) {
   1651       IModuleFactory factoryInstance = parentInjector.getInstance(factory);
   1652       Module moduleClass = factoryInstance.createModule(this, testClass);
   1653       if (moduleClass != null) {
   1654         result.add(moduleClass);
   1655       }
   1656     }
   1657 
   1658     return result.toArray(new Module[result.size()]);
   1659   }
   1660 
   1661   @Override
   1662   public void addInjector(List<Module> moduleInstances, Injector injector) {
   1663     m_injectors.put(moduleInstances, injector);
   1664   }
   1665 
   1666 } // TestRunner
   1667