New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allowing custom Thread Groups #2343
Comments
Andrey Pohilko (migrated from Bugzilla): |
Andrey Pohilko (migrated from Bugzilla): AbstractThreadGroup.java/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.jmeter.threads;
import java.io.Serializable;
import org.apache.jmeter.control.Controller;
import org.apache.jmeter.control.LoopController;
import org.apache.jmeter.engine.event.LoopIterationListener;
import org.apache.jmeter.samplers.Sampler;
import org.apache.jmeter.testelement.AbstractTestElement;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.testelement.property.IntegerProperty;
import org.apache.jmeter.testelement.property.JMeterProperty;
import org.apache.jmeter.testelement.property.TestElementProperty;
/**
* ThreadGroup holds the settings for a JMeter thread group.
*
* This class is intended to be ThreadSafe.
*/
public abstract class AbstractThreadGroup extends AbstractTestElement implements Serializable, Controller {
/** Action to be taken when a Sampler error occurs */
public final static String ON_SAMPLE_ERROR = "ThreadGroup.on_sample_error"; // int
/** Continue, i.e. ignore sampler errors */
public final static String ON_SAMPLE_ERROR_CONTINUE = "continue";
/** Stop current thread if sampler error occurs */
public final static String ON_SAMPLE_ERROR_STOPTHREAD = "stopthread";
/** Stop test (all threads) if sampler error occurs */
public final static String ON_SAMPLE_ERROR_STOPTEST = "stoptest";
/** Stop test NOW (all threads) if sampler error occurs */
public final static String ON_SAMPLE_ERROR_STOPTEST_NOW = "stoptestnow";
/** Number of threads in the thread group */
public final static String NUM_THREADS = "ThreadGroup.num_threads";
public final static String MAIN_CONTROLLER = "ThreadGroup.main_controller";
// @GuardedBy("this")
private int numberOfThreads = 0; // Number of active threads in this group
/** {@inheritDoc} */
public boolean isDone() {
return getSamplerController().isDone();
}
/** {@inheritDoc} */
public Sampler next() {
return getSamplerController().next();
}
/**
* Get the sampler controller.
*
* @return the sampler controller.
*/
public Controller getSamplerController() {
Controller c = (Controller) getProperty(MAIN_CONTROLLER).getObjectValue();
return c;
}
/**
* Set the sampler controller.
*
* @param c
* the sampler controller.
*/
public void setSamplerController(LoopController c) {
c.setContinueForever(false);
setProperty(new TestElementProperty(MAIN_CONTROLLER, c));
}
/**
* Add a test element.
*
* @param child
* the test element to add.
*/
@Override
public void addTestElement(TestElement child) {
getSamplerController().addTestElement(child);
}
/** {@inheritDoc} */
public void addIterationListener(LoopIterationListener lis) {
getSamplerController().addIterationListener(lis);
}
/** {@inheritDoc} */
public void initialize() {
Controller c = getSamplerController();
JMeterProperty property = c.getProperty(TestElement.NAME);
property.setObjectValue(getName()); // Copy our name into that of the controller
property.setRunningVersion(property.isRunningVersion());// otherwise name reverts
c.initialize();
}
/**
* Set the total number of threads to start
*
* @param numThreads
* the number of threads.
*/
public void setNumThreads(int numThreads) {
setProperty(new IntegerProperty(NUM_THREADS, numThreads));
}
/**
* Increment the number of active threads
*/
synchronized void incrNumberOfThreads() {
numberOfThreads++;
}
/**
* Decrement the number of active threads
*/
synchronized void decrNumberOfThreads() {
numberOfThreads--;
}
/**
* Get the number of active threads
*/
public synchronized int getNumberOfThreads() {
return numberOfThreads;
}
/**
* Get the number of threads.
*
* @return the number of threads.
*/
public int getNumThreads() {
return this.getPropertyAsInt(AbstractThreadGroup.NUM_THREADS);
}
/**
* Check if a sampler error should cause thread to stop.
*
* @return true if thread should stop
*/
public boolean getOnErrorStopThread() {
return getPropertyAsString(ThreadGroup.ON_SAMPLE_ERROR).equalsIgnoreCase(ON_SAMPLE_ERROR_STOPTHREAD);
}
/**
* Check if a sampler error should cause test to stop.
*
* @return true if test (all threads) should stop
*/
public boolean getOnErrorStopTest() {
return getPropertyAsString(ThreadGroup.ON_SAMPLE_ERROR).equalsIgnoreCase(ON_SAMPLE_ERROR_STOPTEST);
}
/**
* Check if a sampler error should cause test to stop now.
*
* @return true if test (all threads) should stop immediately
*/
public boolean getOnErrorStopTestNow() {
return getPropertyAsString(ThreadGroup.ON_SAMPLE_ERROR).equalsIgnoreCase(ON_SAMPLE_ERROR_STOPTEST_NOW);
}
public abstract void scheduleThread(JMeterThread thread);
} |
Andrey Pohilko (migrated from Bugzilla): AbstractThreadGroupGui.java/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.jmeter.threads.gui;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ItemListener;
import java.util.Arrays;
import java.util.Collection;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.ButtonGroup;
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.tree.JMeterTreeNode;
import org.apache.jmeter.gui.util.MenuFactory;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.testelement.property.StringProperty;
import org.apache.jmeter.threads.AbstractThreadGroup;
import org.apache.jmeter.util.JMeterUtils;
public abstract class AbstractThreadGroupGui extends AbstractJMeterGuiComponent implements ItemListener {
// Sampler error action buttons
private JRadioButton continueBox;
private JRadioButton stopThrdBox;
private JRadioButton stopTestBox;
private JRadioButton stopTestNowBox;
public Collection<String> getMenuCategories() {
return Arrays.asList(new String[] { MenuFactory.THREADS });
}
public JPopupMenu createPopupMenu() {
JPopupMenu pop = new JPopupMenu();
pop.add(MenuFactory.makeMenus(new String[] {
MenuFactory.CONTROLLERS,
MenuFactory.CONFIG_ELEMENTS,
MenuFactory.TIMERS,
MenuFactory.PRE_PROCESSORS,
MenuFactory.SAMPLERS,
MenuFactory.POST_PROCESSORS,
MenuFactory.ASSERTIONS,
MenuFactory.LISTENERS,
},
JMeterUtils.getResString("add"), // $NON-NLS-1$
ActionNames.ADD));
MenuFactory.addEditMenu(pop, true);
MenuFactory.addFileMenu(pop);
return pop;
}
public void setNode(JMeterTreeNode node) {
getNamePanel().setNode(node);
}
@Override
public Dimension getPreferredSize() {
return getMinimumSize();
}
protected void init() {
setLayout(new BorderLayout(0, 5));
setBorder(makeBorder());
Box box = Box.createVerticalBox();
box.add(makeTitlePanel());
box.add(createOnErrorPanel());
add(box, BorderLayout.NORTH);
continueBox.setSelected(true);
}
private JPanel createOnErrorPanel() {
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createTitledBorder(JMeterUtils.getResString("sampler_on_error_action"))); // $NON-NLS-1$
ButtonGroup group = new ButtonGroup();
continueBox = new JRadioButton(JMeterUtils.getResString("sampler_on_error_continue")); // $NON-NLS-1$
group.add(continueBox);
panel.add(continueBox);
stopThrdBox = new JRadioButton(JMeterUtils.getResString("sampler_on_error_stop_thread")); // $NON-NLS-1$
group.add(stopThrdBox);
panel.add(stopThrdBox);
stopTestBox = new JRadioButton(JMeterUtils.getResString("sampler_on_error_stop_test")); // $NON-NLS-1$
group.add(stopTestBox);
panel.add(stopTestBox);
stopTestNowBox = new JRadioButton(JMeterUtils.getResString("sampler_on_error_stop_test_now")); // $NON-NLS-1$
group.add(stopTestNowBox);
panel.add(stopTestNowBox);
return panel;
}
private void setSampleErrorBoxes(AbstractThreadGroup te) {
if (te.getOnErrorStopTest()) {
stopTestBox.setSelected(true);
} else if (te.getOnErrorStopTestNow()) {
stopTestNowBox.setSelected(true);
} else if (te.getOnErrorStopThread()) {
stopThrdBox.setSelected(true);
} else {
continueBox.setSelected(true);
}
}
private String onSampleError() {
if (stopTestBox.isSelected()) {
return AbstractThreadGroup.ON_SAMPLE_ERROR_STOPTEST;
}
if (stopTestNowBox.isSelected()) {
return AbstractThreadGroup.ON_SAMPLE_ERROR_STOPTEST_NOW;
}
if (stopThrdBox.isSelected()) {
return AbstractThreadGroup.ON_SAMPLE_ERROR_STOPTHREAD;
}
// Defaults to continue
return AbstractThreadGroup.ON_SAMPLE_ERROR_CONTINUE;
}
@Override
public void configure(TestElement tg) {
super.configure(tg);
setSampleErrorBoxes((AbstractThreadGroup) tg);
}
@Override
protected void configureTestElement(TestElement tg) {
tg.setProperty(new StringProperty(AbstractThreadGroup.ON_SAMPLE_ERROR, onSampleError()));
}
@Override
public void clearGui(){
super.clearGui();
continueBox.setSelected(true);
}
} |
Andrey Pohilko (migrated from Bugzilla): |
Andrey Pohilko (migrated from Bugzilla): |
Andrey Pohilko (migrated from Bugzilla): |
Andrey Pohilko (migrated from Bugzilla): Created attachment 48749.diff: Proposed source code changes |
Sebb (migrated from Bugzilla): The code has been applied: URL: http://svn.apache.org/viewvc?rev=915587&view=rev Added: There were a few changes needed:
|
Andrey Pohilko (Bug 48749):
One unable to write custom plugin for Thread Groups to have advanced thread start/stop scheduling. Attached patch adds such ability to JMeter.
Responsibility for threads scheduling moved from StandardJMeterEngine to implementations of AbstractThreadGroup.
OS: Windows XP
Blocks:
The text was updated successfully, but these errors were encountered: