Am 28.11.2017 um 08:11 schrieb pmouawad@apache.org: > Author: pmouawad > Date: Tue Nov 28 07:11:35 2017 > New Revision: 1816519 > > URL: http://svn.apache.org/viewvc?rev=1816519&view=rev > Log: > Bug 61802 - Loop / ForEach Controller should expose a variable for current iteration > Bugzilla Id: 61802 > > Modified: > jmeter/trunk/src/components/org/apache/jmeter/control/ForeachController.java > jmeter/trunk/src/core/org/apache/jmeter/control/LoopController.java > jmeter/trunk/src/core/org/apache/jmeter/util/JMeterUtils.java > jmeter/trunk/test/src/org/apache/jmeter/control/TestLoopController.java > jmeter/trunk/xdocs/changes.xml > > Modified: jmeter/trunk/src/components/org/apache/jmeter/control/ForeachController.java > URL: http://svn.apache.org/viewvc/jmeter/trunk/src/components/org/apache/jmeter/control/ForeachController.java?rev=1816519&r1=1816518&r2=1816519&view=diff > ============================================================================== > --- jmeter/trunk/src/components/org/apache/jmeter/control/ForeachController.java (original) > +++ jmeter/trunk/src/components/org/apache/jmeter/control/ForeachController.java Tue Nov 28 07:11:35 2017 > @@ -24,7 +24,9 @@ import org.apache.jmeter.samplers.Sample > import org.apache.jmeter.testelement.property.BooleanProperty; > import org.apache.jmeter.testelement.property.StringProperty; > import org.apache.jmeter.threads.JMeterContext; > +import org.apache.jmeter.threads.JMeterContextService; > import org.apache.jmeter.threads.JMeterVariables; > +import org.apache.jmeter.util.JMeterUtils; > import org.slf4j.Logger; > import org.slf4j.LoggerFactory; > > @@ -36,6 +38,7 @@ import org.slf4j.LoggerFactory; > * > */ > public class ForeachController extends GenericController implements Serializable { > + > private static final Logger log = LoggerFactory.getLogger(ForeachController.class); > > private static final long serialVersionUID = 241L; > @@ -195,12 +198,21 @@ public class ForeachController extends G > // Prevent entry if nothing to do > @Override > public Sampler next() { > - if (emptyList()) { > - reInitialize(); > - resetLoopCount(); > - return null; > + try { > + if (emptyList()) { > + reInitialize(); > + resetLoopCount(); > + return null; > + } > + return super.next(); > + } finally { > + JMeterVariables variables = JMeterContextService.getContext().getVariables(); > + if(variables != null) { > + variables.putObject( > + JMeterUtils.formatJMeterExportedVariableName( > + getName()+LoopController.INDEX_VAR_NAME_SUFFIX), loopCount); > + } > } > - return super.next(); > } > > /** > > Modified: jmeter/trunk/src/core/org/apache/jmeter/control/LoopController.java > URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/control/LoopController.java?rev=1816519&r1=1816518&r2=1816519&view=diff > ============================================================================== > --- jmeter/trunk/src/core/org/apache/jmeter/control/LoopController.java (original) > +++ jmeter/trunk/src/core/org/apache/jmeter/control/LoopController.java Tue Nov 28 07:11:35 2017 > @@ -25,12 +25,16 @@ import org.apache.jmeter.testelement.pro > import org.apache.jmeter.testelement.property.IntegerProperty; > import org.apache.jmeter.testelement.property.JMeterProperty; > import org.apache.jmeter.testelement.property.StringProperty; > +import org.apache.jmeter.threads.JMeterContextService; > +import org.apache.jmeter.threads.JMeterVariables; > +import org.apache.jmeter.util.JMeterUtils; > > /** > * Class that implements the Loop Controller, ie iterate infinitely or a configured number of times > */ > public class LoopController extends GenericController implements Serializable { > - > + static final String INDEX_VAR_NAME_SUFFIX = "__idx"; Should this be private? > + > public static final int INFINITE_LOOP_COUNT = -1; // $NON-NLS-1$ > > public static final String LOOPS = "LoopController.loops"; // $NON-NLS-1$ > @@ -114,15 +118,23 @@ public class LoopController extends Gene > */ > @Override > public Sampler next() { > - if(endOfLoop()) { > - if (!getContinueForever()) { > - setDone(true); > + try { > + if(endOfLoop()) { > + if (!getContinueForever()) { > + setDone(true); > + } > + return null; > + } > + return super.next(); > + } finally { > + JMeterVariables variables = JMeterContextService.getContext().getVariables(); > + if(variables != null) { > + variables.putObject( > + JMeterUtils.formatJMeterExportedVariableName(getName()+INDEX_VAR_NAME_SUFFIX), loopCount); > } > - return null; > } > - return super.next(); > } > - > + > private boolean endOfLoop() { > final int loops = getLoops(); > return (loops > INFINITE_LOOP_COUNT) && (loopCount >= loops); > > Modified: jmeter/trunk/src/core/org/apache/jmeter/util/JMeterUtils.java > URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/util/JMeterUtils.java?rev=1816519&r1=1816518&r2=1816519&view=diff > ============================================================================== > --- jmeter/trunk/src/core/org/apache/jmeter/util/JMeterUtils.java (original) > +++ jmeter/trunk/src/core/org/apache/jmeter/util/JMeterUtils.java Tue Nov 28 07:11:35 2017 > @@ -79,7 +79,7 @@ import com.thoughtworks.xstream.security > */ > public class JMeterUtils implements UnitTestManager { > private static final Logger log = LoggerFactory.getLogger(JMeterUtils.class); > - > + private static final String JMETER_VARS_PREFIX = "__jm__"; > // Note: cannot use a static variable here, because that would be processed before the JMeter properties > // have been defined (Bug 52783) > private static class LazyPatternCacheHolder { > @@ -1261,4 +1261,16 @@ public class JMeterUtils implements Unit > // TODO : How much are we concerned by CVE-2013-7285 > xstream.addPermission(AnyTypePermission.ANY); > } > + > + /** > + * @param elementName String elementName > + * @return variable name for index following JMeter convention > + */ > + public static String formatJMeterExportedVariableName(String elementName) { > + StringBuilder builder = new StringBuilder( > + JMETER_VARS_PREFIX.length()+elementName.length()); > + return builder.append(JMETER_VARS_PREFIX) > + .append(elementName) > + .toString(); a "return JMETER_VARS_PREFIX + elementName;" is probably more readable and should result in some equivalent bytecode. Regards,  Felix > + } > } > > Modified: jmeter/trunk/test/src/org/apache/jmeter/control/TestLoopController.java > URL: http://svn.apache.org/viewvc/jmeter/trunk/test/src/org/apache/jmeter/control/TestLoopController.java?rev=1816519&r1=1816518&r2=1816519&view=diff > ============================================================================== > --- jmeter/trunk/test/src/org/apache/jmeter/control/TestLoopController.java (original) > +++ jmeter/trunk/test/src/org/apache/jmeter/control/TestLoopController.java Tue Nov 28 07:11:35 2017 > @@ -36,12 +36,17 @@ import org.apache.jmeter.testelement.pro > import org.apache.jmeter.threads.JMeterContext; > import org.apache.jmeter.threads.JMeterContextService; > import org.apache.jmeter.threads.JMeterVariables; > +import org.apache.jmeter.util.JMeterUtils; > import org.junit.Test; > > public class TestLoopController extends JMeterTestCase { > > @Test > public void testProcessing() throws Exception { > + JMeterContext jmctx = JMeterContextService.getContext(); > + JMeterVariables variables = new JMeterVariables(); > + jmctx.setVariables(variables); > + > GenericController controller = new GenericController(); > GenericController sub_1 = new GenericController(); > sub_1.addTestElement(new TestSampler("one")); > @@ -49,6 +54,8 @@ public class TestLoopController extends > controller.addTestElement(sub_1); > controller.addTestElement(new TestSampler("three")); > LoopController sub_2 = new LoopController(); > + String lcName = "LC"; > + sub_2.setName(lcName); > sub_2.setLoops(3); > GenericController sub_3 = new GenericController(); > sub_2.addTestElement(new TestSampler("four")); > @@ -65,41 +72,72 @@ public class TestLoopController extends > sub_2.setRunningVersion(true); > sub_3.setRunningVersion(true); > controller.initialize(); > + int loopControl = 0; > for (int i = 0; i < 2; i++) { > + loopControl = 0; > assertEquals(15, counter); > counter = 0; > TestElement sampler = null; > while ((sampler = controller.next()) != null) { > assertEquals(order[counter++], sampler.getName()); > + if("four".equals(sampler.getName())) { > + Integer value = (Integer) variables.getObject( > + JMeterUtils.formatJMeterExportedVariableName(lcName+LoopController.INDEX_VAR_NAME_SUFFIX)); > + assertNotNull(value); > + assertEquals(Integer.valueOf(loopControl++), value); > + } > } > + > } > + > } > > @Test > public void testLoopZeroTimes() throws Exception { > + JMeterContext jmctx = JMeterContextService.getContext(); > + JMeterVariables variables = new JMeterVariables(); > + jmctx.setVariables(variables); > + > LoopController loop = new LoopController(); > + String lcName = "LC"; > + loop.setName(lcName); > loop.setLoops(0); > loop.addTestElement(new TestSampler("never run")); > loop.initialize(); > assertNull(loop.next()); > + Integer value = (Integer) variables.getObject( > + JMeterUtils.formatJMeterExportedVariableName(lcName+LoopController.INDEX_VAR_NAME_SUFFIX)); > + assertNotNull(value); > + assertEquals(Integer.valueOf(0), value); > } > > @Test > public void testInfiniteLoop() throws Exception { > + JMeterContext jmctx = JMeterContextService.getContext(); > LoopController loop = new LoopController(); > + String lcName = "LC"; > + loop.setName(lcName); > loop.setLoops(LoopController.INFINITE_LOOP_COUNT); > loop.addTestElement(new TestSampler("never run")); > + JMeterVariables variables = new JMeterVariables(); > + jmctx.setVariables(variables); > loop.setRunningVersion(true); > loop.initialize(); > for (int i = 0; i < 42; i++) { > assertNotNull(loop.next()); > + Integer value = (Integer) variables.getObject( > + JMeterUtils.formatJMeterExportedVariableName(lcName+LoopController.INDEX_VAR_NAME_SUFFIX)); > + assertNotNull(value); > + assertEquals(Integer.valueOf(i), value); > } > } > > @Test > public void testBug54467() throws Exception { > JMeterContext jmctx = JMeterContextService.getContext(); > + String lcName = "LC"; > LoopController loop = new LoopController(); > + loop.setName(lcName); > Map variables = new HashMap<>(); > ReplaceStringWithFunctions transformer = new ReplaceStringWithFunctions(new CompoundVariable(), variables); > jmctx.setVariables(new JMeterVariables()); > @@ -116,6 +154,10 @@ public class TestLoopController extends > for (int i = 0; i < loops; i++) { > Sampler s = loop.next(); > assertNotNull(s); > + Integer value = (Integer) jmctx.getVariables().getObject( > + JMeterUtils.formatJMeterExportedVariableName(lcName+LoopController.INDEX_VAR_NAME_SUFFIX)); > + assertNotNull(value); > + assertEquals(Integer.valueOf(i), value); > } > assertNull(loop.next()); > } > > Modified: jmeter/trunk/xdocs/changes.xml > URL: http://svn.apache.org/viewvc/jmeter/trunk/xdocs/changes.xml?rev=1816519&r1=1816518&r2=1816519&view=diff > ============================================================================== > --- jmeter/trunk/xdocs/changes.xml [utf-8] (original) > +++ jmeter/trunk/xdocs/changes.xml [utf-8] Tue Nov 28 07:11:35 2017 > @@ -172,6 +172,7 @@ Summary >
  • 61640JSR223 Test Elements : Enable by default caching. Contributed by Ubik Load Pack (support at ubikloadpack.com)
  • >
  • 61785Add HelpUseful links to create issues and download nightly build
  • >
  • 61808Fix main frame position. Implemented by Artem Fedorov (artem at blazemeter.com) and contributed by BlazeMeter Ltd.
  • > +
  • 61802Loop / ForEach Controller should expose a variable for current iteration. Contributed by Ubik Load Pack (support at ubikloadpack.com)
  • > > > Non-functional changes > >