Bug 64581 - Allow SampleResult#setIgnore to influence behaviour on

Sampler Error

Fix also misnamed lastSampleInError to lastSampleOk
When SampleResult#isIgnore() is true, use is for impacting algorithmic
execution, it will be taken into account to:

- Decide what to do on Error ("Action to be taken after a Sampler error"
in Thread Group)
- set JMeterThread.last_sample_ok
This commit is contained in:
pmouawad
2020-07-06 13:19:27 +02:00
parent fadf375b00
commit 65b75c0e74
3 changed files with 43 additions and 25 deletions

View File

@@ -256,17 +256,17 @@ public class JMeterThread implements Runnable, Interruptible {
processSampler(sam, null, threadContext);
threadContext.cleanAfterSample();
boolean lastSampleInError = TRUE.equals(threadContext.getVariables().get(LAST_SAMPLE_OK));
boolean lastSampleOk = TRUE.equals(threadContext.getVariables().get(LAST_SAMPLE_OK));
// restart of the next loop
// - was requested through threadContext
// - or the last sample failed AND the onErrorStartNextLoop option is enabled
if (threadContext.getTestLogicalAction() != TestLogicalAction.CONTINUE
|| (onErrorStartNextLoop && !lastSampleInError)) {
|| (onErrorStartNextLoop && !lastSampleOk)) {
if (log.isDebugEnabled() && onErrorStartNextLoop
&& threadContext.getTestLogicalAction() != TestLogicalAction.CONTINUE) {
log.debug("Start Next Thread Loop option is on, Last sample failed, starting next thread loop");
}
if(onErrorStartNextLoop && !lastSampleInError){
if(onErrorStartNextLoop && !lastSampleOk){
triggerLoopLogicalActionOnParentControllers(sam, threadContext, JMeterThread::continueOnThreadLoop);
} else {
switch (threadContext.getTestLogicalAction()) {
@@ -285,7 +285,7 @@ public class JMeterThread implements Runnable, Interruptible {
}
threadContext.setTestLogicalAction(TestLogicalAction.CONTINUE);
sam = null;
threadContext.getVariables().put(LAST_SAMPLE_OK, TRUE);
setLastSampleOk(threadContext.getVariables(), true);
}
else {
sam = threadGroupLoopController.next();
@@ -558,30 +558,33 @@ public class JMeterThread implements Runnable, Interruptible {
result = doSampling(threadContext, sampler);
}
// If we got any results, then perform processing on the result
if (result != null && !result.isIgnore()) {
int nbActiveThreadsInThreadGroup = threadGroup.getNumberOfThreads();
int nbTotalActiveThreads = JMeterContextService.getNumberOfThreads();
fillThreadInformation(result, nbActiveThreadsInThreadGroup, nbTotalActiveThreads);
SampleResult[] subResults = result.getSubResults();
if (subResults != null) {
for (SampleResult subResult : subResults) {
fillThreadInformation(subResult, nbActiveThreadsInThreadGroup, nbTotalActiveThreads);
}
}
threadContext.setPreviousResult(result);
runPostProcessors(pack.getPostProcessors());
checkAssertions(pack.getAssertions(), result, threadContext);
if (result != null) {
if (!result.isIgnore()) {
int nbActiveThreadsInThreadGroup = threadGroup.getNumberOfThreads();
int nbTotalActiveThreads = JMeterContextService.getNumberOfThreads();
fillThreadInformation(result, nbActiveThreadsInThreadGroup, nbTotalActiveThreads);
SampleResult[] subResults = result.getSubResults();
if (subResults != null) {
for (SampleResult subResult : subResults) {
fillThreadInformation(subResult, nbActiveThreadsInThreadGroup, nbTotalActiveThreads);
}
}
threadContext.setPreviousResult(result);
runPostProcessors(pack.getPostProcessors());
checkAssertions(pack.getAssertions(), result, threadContext);
// Do not send subsamples to listeners which receive the transaction sample
List<SampleListener> sampleListeners = getSampleListeners(pack, transactionPack, transactionSampler);
notifyListeners(sampleListeners, result);
compiler.done(pack);
// Add the result as subsample of transaction if we are in a transaction
if (transactionSampler != null && !result.isIgnore()) {
transactionSampler.addSubSamplerResult(result);
}
} else {
// This call is done by checkAssertions() , as we don't call it
// for isIgnore, we explictely call it here
setLastSampleOk(threadContext.getVariables(), result.isSuccessful());
}
compiler.done(pack);
// Add the result as subsample of transaction if we are in a transaction
if (transactionSampler != null && !result.isIgnore()) {
transactionSampler.addSubSamplerResult(result);
}
// Check if thread or test should be stopped
if (result.isStopThread() || (!result.isSuccessful() && onErrorStopThread)) {
stopThread();
@@ -689,6 +692,13 @@ public class JMeterThread implements Runnable, Interruptible {
return sampleListeners;
}
/**
* Store {@link JMeterThread#LAST_SAMPLE_OK} in JMeter Variables context
*/
private void setLastSampleOk(JMeterVariables variables, boolean value) {
variables.put(LAST_SAMPLE_OK, Boolean.toString(value));
}
/**
* @param threadContext
* @return the iteration listener
@@ -697,7 +707,7 @@ public class JMeterThread implements Runnable, Interruptible {
threadVars.putObject(JMeterVariables.VAR_IS_SAME_USER_KEY, isSameUserOnNextIteration);
threadContext.setVariables(threadVars);
threadContext.setThreadNum(getThreadNum());
threadContext.getVariables().put(LAST_SAMPLE_OK, TRUE);
setLastSampleOk(threadVars, true);
threadContext.setThread(this);
threadContext.setThreadGroup(threadGroup);
threadContext.setEngine(engine);
@@ -885,7 +895,7 @@ public class JMeterThread implements Runnable, Interruptible {
processAssertion(parent, assertion);
}
}
threadContext.getVariables().put(LAST_SAMPLE_OK, Boolean.toString(parent.isSuccessful()));
setLastSampleOk(threadContext.getVariables(), parent.isSuccessful());
}
private void recurseAssertionChecks(SampleResult parent, Assertion assertion, int level) {

View File

@@ -112,6 +112,7 @@ Summary
<ul>
<li><bug>64446</bug>Better parse curl commands with backslash at line endings and support <code>PUT</code> method with data arguments</li>
<li><pr>599</pr>Ensure all buttons added to the toolbar behave/look consistently. Contributed by Jannis Weis</li>
<li><bug>64581</bug>Allow SampleResult#setIgnore to influence behaviour on Sampler Error</li>
</ul>
<ch_section>Non-functional changes</ch_section>

View File

@@ -1119,6 +1119,13 @@ The JSR223 Sampler allows JSR223 script code to be used to perform a sample or s
<note>
If you don't want to generate a <apilink href="org/apache/jmeter/samplers/SampleResult.html">SampleResult</apilink> when this sampler is run, call the following method:
<source>SampleResult.setIgnore();</source>
This call will have the following impact:
<ul>
<li>SampleResult will not be delivered to SampleListeners like View Results Tree, Summariser ...</li>
<li>SampleResult will not be evaluated in Assertions nor PostProcessors</li>
<li>SampleResult will be evaluated to computing last sample status (${JMeterThread.last_sample_ok}),
and ThreadGroup "Action to be taken after a Sampler error" (since JMeter 5.4)</li>
</ul>
</note>
</p>
<p>