diff --git a/src/main/java/org/testng/TestRunner.java b/src/main/java/org/testng/TestRunner.java index 64b8fb33bb..bebfbe2140 100644 --- a/src/main/java/org/testng/TestRunner.java +++ b/src/main/java/org/testng/TestRunner.java @@ -47,7 +47,6 @@ import java.util.Collections; import java.util.Comparator; import java.util.Date; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -706,70 +705,18 @@ public int compareTo(IWorker other) { m_allTestMethods= runMethods.toArray(new ITestNGMethod[runMethods.size()]); } + /** + * Main method that create a graph of methods and then pass it to the + * graph executor to run them. + */ private void privateRun(XmlTest xmlTest) { - // - // Calculate the lists of tests that can be run in sequence and in parallel - // - List> sequentialList= Lists.newArrayList(); - List parallelList= Lists.newArrayList(); - ListMultiMap sequentialMapList = Maps.newListMultiMap(); - String parallelMode = xmlTest.getParallel(); boolean parallel = XmlSuite.PARALLEL_METHODS.equals(parallelMode) || "true".equalsIgnoreCase(parallelMode) || XmlSuite.PARALLEL_CLASSES.equals(parallelMode) || XmlSuite.PARALLEL_INSTANCES.equals(parallelMode); - // @@@ - if (false) { // (!parallel) { - // sequential - computeTestLists(sequentialList, parallelList, sequentialMapList); - - int seqCount = 0; - for (List l : sequentialList) { - seqCount += l.size(); - } - log(3, "Found " + seqCount + " sequential methods and " + parallelList.size() - + " parallel methods"); - - // - // If the user specified preserve-order = true, we can't change the ordering - // of the methods on the sequential list, since they are not free, however - // we can still reorder the classes to reflect that order. - // - if ("true".equalsIgnoreCase(xmlTest.getPreserveOrder())) { - // Note: modifying sequentialList - sequentialList = preserveClassOrder(xmlTest, sequentialList); - } - - // - // Create the workers - // - List workers = Lists.newArrayList(); - - createSequentialWorkers(sequentialList, xmlTest, m_classMethodMap, workers); - ListMultiMap ml = - createSequentialWorkers(sequentialMapList, xmlTest.getParameters(), m_classMethodMap); - - // All the parallel tests are placed in a separate worker, so they can be - // invoked in parallel - createParallelWorkers(parallelList, xmlTest, m_classMethodMap, workers); - -// m_testPlan = -// new TestPlan(sequentialList, parallelList, cmm, -// getBeforeSuiteMethods(), getAfterSuiteMethods(), -// m_groupMethods, xmlTest); - - try { - // Sort by priorities - Collections.sort(workers); - runWorkers(workers, xmlTest.getParallel(), ml); - } - finally { - m_classMethodMap.clear(); - } - } - else { + { // parallel int threadCount = parallel ? xmlTest.getThreadCount() : 1; // Make sure we create a graph based on the intercepted methods, otherwise an interceptor @@ -829,57 +776,6 @@ private ITestNGMethod[] intercept(ITestNGMethod[] methods) { return result.toArray(new ITestNGMethod[result.size()]); } - /** - * Reorder the methods to preserve the class order without changing the method ordering. - */ - private List> preserveClassOrder(XmlTest test, - List> lists) { - - List> result = Lists.newArrayList(); - - Map> classes = Maps.newHashMap(); - List sortedClasses = Lists.newArrayList(); - - for (XmlClass c : test.getXmlClasses()) { - classes.put(c.getName(), new ArrayList()); - sortedClasses.add(c); - } - - // Sort the classes based on their order of appearance in the XML - Collections.sort(sortedClasses, new Comparator() { - @Override - public int compare(XmlClass arg0, XmlClass arg1) { - return arg0.getIndex() - arg1.getIndex(); - } - }); - - // Put each method in their class bucket - for (List ll : lists) { - for (ITestNGMethod m : ll) { - String declaredClass = m.getTestClass().getName(); - List l = classes.get(declaredClass); - // The list might be null if the class came from somewhere else than XML, - // e.g. a factory - if (l == null) { - l = Lists.newArrayList(); - classes.put(declaredClass, l); - } - l.add(m); - } - } - // Recreate the list based on the class ordering - List tmpResult = Lists.newArrayList(); - for (XmlClass xc : sortedClasses) { - List methods = classes.get(xc.getName()); - tmpResult.addAll(methods); - } - result.add(tmpResult); -// } - -// System.out.println(result); - return result; - } - /** * Create a list of workers to run the methods passed in parameter. * Each test method is run in its own worker except in the following cases: @@ -1012,8 +908,8 @@ private List[] createInstances(List methodInst // } } // return map.getKeys(); - System.out.println(map); - List[] result = new List[map.size()]; +// System.out.println(map); + List[] result = new List[map.size()]; int i = 0; for (List imi : map.values()) { result[i++] = imi; @@ -1044,152 +940,6 @@ private IMethodInstance[] findClasses(List methodInstances, Cla return result.toArray(new IMethodInstance[result.size()]); } - private void createParallelWorkers(List parallel, - XmlTest xmlTest, ClassMethodMap cmm, List workers) { - - if(parallel.isEmpty()) { - return; - } - - List methodInstances = Lists.newArrayList(); - for (ITestNGMethod tm : parallel) { - methodInstances.addAll(methodsToMultipleMethodInstances(tm)); - } - - // - // Finally, sort the parallel methods by classes - // - methodInstances = m_methodInterceptor.intercept(methodInstances, this); - - if (getVerbose() >= 2) { - log(3, "Will be run in random order:"); - for (IMethodInstance mi : methodInstances) { - log(3, " " + mi.getMethod()); - log(3, " on instances"); - for(Object o: mi.getInstances()) { - log(3, " " + o); - } - } - log(3, "==="); - } - - Map params = xmlTest.getParameters(); - for (IMethodInstance mi : methodInstances) { - workers.add(new TestMethodWorker(m_invoker, - new IMethodInstance[] { mi }, - m_xmlTest.getSuite(), - params, - m_allTestMethods, - m_groupMethods, - cmm, - this)); - } - } - - /** - * @return a Set of arrays of IMethodInstances. Each element in the array is a method that belongs - * to the same class. - */ - private Map> groupMethodInstancesByClass(List instances) { - Map> result = Maps.newHashMap(); - for (IMethodInstance mi : instances) { - Class cl = mi.getMethod().getTestClass().getRealClass(); - Set methods = result.get(cl); - if (methods == null) { - methods = new HashSet(); - result.put(cl, methods); - } - methods.add(mi); - } - - return result; - } - - private void createSequentialWorkers(List> sequentialList, - XmlTest xmlTest, ClassMethodMap cmm, List workers) { - - Map params = xmlTest.getParameters(); - if(sequentialList.isEmpty()) { - return; - } - - Map> map = Maps.newHashMap(); - - for (List sl : sequentialList) { - for (ITestNGMethod m : sl) { - Object o = m.getInstance(); - List l = map.get(o); - if (l == null) { - l = Lists.newArrayList(); - map.put(o, l); - } - l.add(m); - } - } - - if (xmlTest.groupByInstances()) { - for (Map.Entry> es : map.entrySet()) { - List instances = Lists.newArrayList(); - for (ITestNGMethod m : es.getValue()) { - instances.add(new MethodInstance(m)); - } - - workers.add(new TestMethodWorker(m_invoker, - instances.toArray(new MethodInstance[instances.size()]), - m_xmlTest.getSuite(), - params, - m_allTestMethods, - m_groupMethods, - cmm, - this)); - } - } else { - // All the sequential tests are place in one worker, guaranteeing they - // will be invoked sequentially - for (List sl : sequentialList) { - workers.add(new TestMethodWorker(m_invoker, - methodsToMethodInstances(sl), - m_xmlTest.getSuite(), - params, - m_allTestMethods, - m_groupMethods, - cmm, - this)); - } - } - - if (getVerbose() >= 2) { - log(3, "Will be run sequentially:"); - for (List l : sequentialList) { - for (ITestNGMethod tm : l) { - log(3, " " + tm); - } - log(3, "===="); - } - - log(3, "==="); - } - } - - private ListMultiMap createSequentialWorkers(ListMultiMap mapList, Map params, ClassMethodMap cmm) { - - ListMultiMap result = Maps.newListMultiMap(); - // All the sequential tests are place in one worker, guaranteeing they - // will be invoked sequentially - for (Integer i : mapList.getKeys()) { - result.put(i, - new TestMethodWorker(m_invoker, methodsToMethodInstances(mapList.get(i)), - m_xmlTest.getSuite(), params, m_allTestMethods, m_groupMethods, cmm, this)); - } - - if (getVerbose() >= 2) { - log(3, "Will be run sequentially:" + result); - } - - return result; - } - /** * @@@ remove this */ @@ -1274,23 +1024,6 @@ private void afterRun() { // logResults(); } - /** - * @param regexps - * @param group - * @return true if the map contains at least one regexp that matches the - * given group - */ - private boolean containsString(Map regexps, String group) { - for (String regexp : regexps.values()) { - boolean match = Pattern.matches(regexp, group); - if (match) { - return true; - } - } - - return false; - } - private DynamicGraph createDynamicGraph(ITestNGMethod[] methods) { DynamicGraph result = new DynamicGraph(); result.setComparator(new Comparator() { @@ -1384,7 +1117,6 @@ public int compare(ITestNGMethod o1, ITestNGMethod o2) { } - List n = result.getFreeNodes(); return result; } @@ -1469,131 +1201,6 @@ public int compare(XmlClass arg0, XmlClass arg1) { return result; } - /** - * Creates the - * @param sl the sequential list of methods - * @param parallelList the list of methods that can be run in parallel - */ - private void computeTestLists(List> sl, - List parallelList, ListMultiMap outSequentialList) { - - Map groupsDependedUpon = Maps.newHashMap(); - Map methodsDependedUpon = Maps.newHashMap(); - - Map> sequentialAttributeList = Maps.newHashMap(); - List sequentialList = Lists.newArrayList(); - - for (int i= m_allTestMethods.length - 1; i >= 0; i--) { - ITestNGMethod tm= m_allTestMethods[i]; - - // - // If the class this method belongs to has @Test(sequential = true), we - // put this method in the sequential list right away - // - Class cls= tm.getRealClass(); - org.testng.annotations.ITestAnnotation test = - (org.testng.annotations.ITestAnnotation) m_annotationFinder. - findAnnotation(cls, org.testng.annotations.ITestAnnotation.class); - if (test != null) { - if (test.getSequential() || test.getSingleThreaded()) { - String className = tm.getTestClass().getName(); - List list = sequentialAttributeList.get(className); - if (list == null) { - list = Lists.newArrayList(); - sequentialAttributeList.put(className, list); - } - list.add(0, tm); - continue; - } - } - - // - // Otherwise, determine if it depends on other methods/groups or if - // it is depended upon - // - String[] currentGroups = tm.getGroups(); - String[] currentGroupsDependedUpon= tm.getGroupsDependedUpon(); - String[] currentMethodsDependedUpon= tm.getMethodsDependedUpon(); - - String thisMethodName = tm.getMethod().getDeclaringClass().getName() - + "." + tm.getMethod().getName(); - if (currentGroupsDependedUpon.length > 0) { - for (String gdu : currentGroupsDependedUpon) { - groupsDependedUpon.put(gdu, gdu); - } - - sequentialList.add(0, tm); - } - else if (currentMethodsDependedUpon.length > 0) { - for (String cmu : currentMethodsDependedUpon) { - methodsDependedUpon.put(cmu, cmu); - } - sequentialList.add(0, tm); - } - // Is there a method that depends on the current method? - else if (containsString(methodsDependedUpon, thisMethodName)) { - int index = 0; - for (int j = 0; j < sequentialList.size(); j++) { - ITestNGMethod m = sequentialList.get(j); - if (arrayContains(m.getMethodsDependedUpon(), thisMethodName)) { - index = j; - break; - } - } - // Insert the dependee as close to its dependent as possible (TESTNG-317) - sequentialList.add(index, tm); - } - else if (currentGroups.length > 0) { - boolean isSequential= false; - - for (String group : currentGroups) { - if (containsString(groupsDependedUpon, group)) { - sequentialList.add(0, tm); - isSequential = true; - - break; - } - } - if (!isSequential) { - parallelList.add(0, tm); - } - } - else { - parallelList.add(0, tm); - } - } - - // - // Put all the sequential methods in the output argument - // - if(sequentialList.size() > 0) { - sl.add(sequentialList); - } - - String previousGroup = ""; - int index = 0; - for (ITestNGMethod m : sequentialList) { - String[] g = m.getGroupsDependedUpon(); - if (g.length > 0 && !m.getGroupsDependedUpon()[0].equals(previousGroup)) { - index++; - previousGroup = m.getGroupsDependedUpon()[0]; - } - outSequentialList.put(index, m); - } -// System.out.println("Map list:" + mapList); - - sl.addAll(sequentialAttributeList.values()); - } - - private boolean arrayContains(String[] array, String element) { - for (String a : array) { - if (element.equals(a)) { - return true; - } - } - return false; - } - /** * Logs the beginning of the {@link #beforeRun()} . */