From 950e42ed8c1e3e720d51e0abfa2ccf9b9a7ef6da Mon Sep 17 00:00:00 2001 From: benoit Date: Fri, 18 Mar 2016 10:34:10 +0100 Subject: [PATCH] Bug 59197 : it should be possible to only run a single threadgroup or a selection of threadgroups. Right click on the TG and choose Start or Start no pauses --- .../apache/jmeter/gui/action/ActionNames.java | 8 +- .../org/apache/jmeter/gui/action/Start.java | 108 ++++++++++++++++-- .../jmeter/resources/messages.properties | 2 + .../threads/gui/AbstractThreadGroupGui.java | 20 +++- 4 files changed, 127 insertions(+), 11 deletions(-) diff --git a/src/core/org/apache/jmeter/gui/action/ActionNames.java b/src/core/org/apache/jmeter/gui/action/ActionNames.java index f61bdb267d8..c666f9b44e6 100644 --- a/src/core/org/apache/jmeter/gui/action/ActionNames.java +++ b/src/core/org/apache/jmeter/gui/action/ActionNames.java @@ -99,9 +99,11 @@ public final class ActionNames { public static final String QUICK_COMPONENT = "quick_component"; // $NON-NLS-1$ public static final String COLLAPSE = "collapse"; // $NON-NLS-1$ public static final String EXPAND = "expand"; // $NON-NLS-1$ + /**@since 3.0.0*/ + public static final String RUN_TG = "run_tg"; // $NON-NLS-1$ + /**@since 3.0.0*/ + public static final String RUN_TG_NO_TIMERS = "run_tg_no_timers"; // $NON-NLS-1$ // Prevent instantiation - private ActionNames(){ - - } + private ActionNames() {} } diff --git a/src/core/org/apache/jmeter/gui/action/Start.java b/src/core/org/apache/jmeter/gui/action/Start.java index 2606d1a627e..6411585d101 100644 --- a/src/core/org/apache/jmeter/gui/action/Start.java +++ b/src/core/org/apache/jmeter/gui/action/Start.java @@ -19,7 +19,10 @@ package org.apache.jmeter.gui.action; import java.awt.event.ActionEvent; +import java.util.ArrayList; import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; import java.util.Set; import javax.swing.JOptionPane; @@ -30,15 +33,21 @@ import org.apache.jmeter.engine.TreeCloner; import org.apache.jmeter.engine.TreeClonerNoTimer; import org.apache.jmeter.gui.GuiPackage; +import org.apache.jmeter.gui.tree.JMeterTreeListener; +import org.apache.jmeter.gui.tree.JMeterTreeNode; +import org.apache.jmeter.testelement.TestElement; import org.apache.jmeter.testelement.TestPlan; +import org.apache.jmeter.threads.AbstractThreadGroup; import org.apache.jmeter.timers.Timer; import org.apache.jmeter.util.JMeterUtils; import org.apache.jorphan.collections.HashTree; +import org.apache.jorphan.collections.ListedHashTree; import org.apache.jorphan.logging.LoggingManager; import org.apache.log.Logger; public class Start extends AbstractAction { - private static final Logger log = LoggingManager.getLoggerForClass(); + + private static final Logger LOGGER = LoggingManager.getLoggerForClass(); private static final Set commands = new HashSet<>(); @@ -47,6 +56,8 @@ public class Start extends AbstractAction { commands.add(ActionNames.ACTION_START_NO_TIMERS); commands.add(ActionNames.ACTION_STOP); commands.add(ActionNames.ACTION_SHUTDOWN); + commands.add(ActionNames.RUN_TG); + commands.add(ActionNames.RUN_TG_NO_TIMERS); } private StandardJMeterEngine engine; @@ -77,42 +88,125 @@ public void doAction(ActionEvent e) { startEngine(true); } else if (e.getActionCommand().equals(ActionNames.ACTION_STOP)) { if (engine != null) { - log.info("Stopping test"); + LOGGER.info("Stopping test"); GuiPackage.getInstance().getMainFrame().showStoppingMessage(""); engine.stopTest(); } } else if (e.getActionCommand().equals(ActionNames.ACTION_SHUTDOWN)) { if (engine != null) { - log.info("Shutting test down"); + LOGGER.info("Shutting test down"); GuiPackage.getInstance().getMainFrame().showStoppingMessage(""); engine.askThreadsToStop(); } + } else if (e.getActionCommand().equals(ActionNames.RUN_TG) || e.getActionCommand().equals(ActionNames.RUN_TG_NO_TIMERS)) { + popupShouldSave(e); + boolean noTimers = e.getActionCommand().equals(ActionNames.RUN_TG_NO_TIMERS); + JMeterTreeListener treeListener = GuiPackage.getInstance().getTreeListener(); + JMeterTreeNode[] nodes = treeListener.getSelectedNodes(); + nodes = Copy.keepOnlyAncestors(nodes); + AbstractThreadGroup[] tg = keepOnlyThreadGroups(nodes); + if(nodes.length > 0) { + startEngine(noTimers, tg); + } + else { + LOGGER.warn("No thread group selected the test will not be started"); + } + } + } + + /** + * filter the nodes to keep only the thread group + * @param currentNodes jmeter tree nodes + * @return the thread groups + */ + private AbstractThreadGroup[] keepOnlyThreadGroups(JMeterTreeNode[] currentNodes) { + List nodes = new ArrayList<>(); + for (JMeterTreeNode jMeterTreeNode : currentNodes) { + if(jMeterTreeNode.getTestElement() instanceof AbstractThreadGroup) { + nodes.add((AbstractThreadGroup) jMeterTreeNode.getTestElement()); + } } + return nodes.toArray(new AbstractThreadGroup[nodes.size()]); } + private void startEngine(boolean ignoreTimer) { + startEngine(ignoreTimer, null); + } + /** * Start JMeter engine * @param ignoreTimer flag to ignore timers */ - private void startEngine(boolean ignoreTimer) { + private void startEngine(boolean ignoreTimer, AbstractThreadGroup[] tg) { GuiPackage gui = GuiPackage.getInstance(); HashTree testTree = gui.getTreeModel().getTestPlan(); + JMeter.convertSubTree(testTree); + if(tg != null) { + removeThreadGroup(testTree, tg); + } + testTree.add(testTree.getArray()[0], gui.getMainFrame()); - log.debug("test plan before cloning is running version: " + LOGGER.debug("test plan before cloning is running version: " + ((TestPlan) testTree.getArray()[0]).isRunningVersion()); + + TreeCloner cloner = cloneTree(testTree, ignoreTimer); + + ListedHashTree clonedTree = cloner.getClonedTree(); engine = new StandardJMeterEngine(); - engine.configure(cloner.getClonedTree()); + engine.configure(clonedTree); try { engine.runTest(); } catch (JMeterEngineException e) { JOptionPane.showMessageDialog(gui.getMainFrame(), e.getMessage(), JMeterUtils.getResString("error_occurred"), JOptionPane.ERROR_MESSAGE); //$NON-NLS-1$ } - log.debug("test plan after cloning and running test is running version: " + LOGGER.debug("test plan after cloning and running test is running version: " + ((TestPlan) testTree.getArray()[0]).isRunningVersion()); } + + /** + * Remove thread groups from tree + * @param testTree the tree + * @param threadGroupsToKeep the thread group to keep + */ + private void removeThreadGroup(HashTree testTree, AbstractThreadGroup[] threadGroupsToKeep) { + LinkedList copyList = new LinkedList<>(testTree.list()); + for (Object o : copyList) { + TestElement item = (TestElement) o; + if (o instanceof AbstractThreadGroup) { + if (!isInThreadGroups(item, threadGroupsToKeep)) { + // hack hack hack + // due to the bug of equals / hashcode on AbstractTestElement + // where 2 AbstractTestElement can be equals but have different hashcode + try { + item.setEnabled(false); + testTree.remove(item); + } finally { + item.setEnabled(true); + } + } + else { + removeThreadGroup(testTree.getTree(item), threadGroupsToKeep); + } + } + else { + removeThreadGroup(testTree.getTree(item), threadGroupsToKeep); + } + } + } + + private boolean isInThreadGroups(TestElement item, AbstractThreadGroup[] tg) { + for (AbstractThreadGroup abstractThreadGroup : tg) { + if(item == abstractThreadGroup) { + return true; + } + } + + return false; + } + /** * Create a Cloner that ignores {@link Timer} if removeTimers is true diff --git a/src/core/org/apache/jmeter/resources/messages.properties b/src/core/org/apache/jmeter/resources/messages.properties index 55c575b0868..57bb28d7843 100644 --- a/src/core/org/apache/jmeter/resources/messages.properties +++ b/src/core/org/apache/jmeter/resources/messages.properties @@ -893,6 +893,8 @@ revert_project?=Revert project? root=Root root_title=Root run=Run +run_threadgroup=Start +run_threadgroup_no_timers=Start no pauses running_test=Running test runtime_controller_title=Runtime Controller runtime_seconds=Runtime (seconds) diff --git a/src/core/org/apache/jmeter/threads/gui/AbstractThreadGroupGui.java b/src/core/org/apache/jmeter/threads/gui/AbstractThreadGroupGui.java index ba5bcb70e79..b378912ab43 100644 --- a/src/core/org/apache/jmeter/threads/gui/AbstractThreadGroupGui.java +++ b/src/core/org/apache/jmeter/threads/gui/AbstractThreadGroupGui.java @@ -22,16 +22,18 @@ import java.awt.Dimension; import java.util.Arrays; import java.util.Collection; + import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.ButtonGroup; +import javax.swing.JMenuItem; import javax.swing.JPanel; - import javax.swing.JPopupMenu; import javax.swing.JRadioButton; import org.apache.jmeter.gui.AbstractJMeterGuiComponent; import org.apache.jmeter.gui.action.ActionNames; +import org.apache.jmeter.gui.action.ActionRouter; import org.apache.jmeter.gui.util.MenuFactory; import org.apache.jmeter.testelement.TestElement; import org.apache.jmeter.testelement.property.StringProperty; @@ -78,6 +80,22 @@ public JPopupMenu createPopupMenu() { }, JMeterUtils.getResString("add"), // $NON-NLS-1$ ActionNames.ADD)); + + if(this.isEnabled()) { + pop.addSeparator(); + JMenuItem runTg = new JMenuItem(JMeterUtils.getResString("run_threadgroup")); + runTg.setName("run_threadgroup"); + runTg.addActionListener(ActionRouter.getInstance()); + runTg.setActionCommand(ActionNames.RUN_TG); + pop.add(runTg); + + JMenuItem runTgNotimers = new JMenuItem(JMeterUtils.getResString("run_threadgroup_no_timers")); + runTgNotimers.setName("run_threadgroup_no_timers"); + runTgNotimers.addActionListener(ActionRouter.getInstance()); + runTgNotimers.setActionCommand(ActionNames.RUN_TG_NO_TIMERS); + pop.add(runTgNotimers); + } + MenuFactory.addEditMenu(pop, true); MenuFactory.addFileMenu(pop, false); return pop;