From 7cec85954edcb720fb51ac9ef8c3a6e471caf307 Mon Sep 17 00:00:00 2001 From: jvangaalen Date: Wed, 4 Dec 2024 08:34:00 +0100 Subject: [PATCH 1/5] Fix memory leak when transaction has parents Improve sampler cleanup during thread run --- .../apache/jmeter/samplers/SampleResult.java | 103 +++++++++++++++++- .../apache/jmeter/threads/JMeterThread.java | 8 +- 2 files changed, 109 insertions(+), 2 deletions(-) diff --git a/src/core/src/main/java/org/apache/jmeter/samplers/SampleResult.java b/src/core/src/main/java/org/apache/jmeter/samplers/SampleResult.java index 4888d250fcb..b998818a6e8 100644 --- a/src/core/src/main/java/org/apache/jmeter/samplers/SampleResult.java +++ b/src/core/src/main/java/org/apache/jmeter/samplers/SampleResult.java @@ -32,7 +32,10 @@ import org.apache.jmeter.assertions.AssertionResult; import org.apache.jmeter.gui.Searchable; import org.apache.jmeter.testelement.TestPlan; +import org.apache.jmeter.threads.JMeterContext; +import org.apache.jmeter.threads.JMeterContextService; import org.apache.jmeter.threads.JMeterContext.TestLogicalAction; +import org.apache.jmeter.control.TransactionSampler; import org.apache.jmeter.util.JMeterUtils; import org.apache.jorphan.util.JOrphanUtils; import org.apache.jorphan.util.StringUtilities; @@ -1595,10 +1598,62 @@ public void setStartNextThreadLoop(boolean startNextThreadLoop) { } /** - * Clean up cached data + * Clean up cached data, but only if this is a root result (no parent) + * and not part of a parent transaction. */ public void cleanAfterSample() { + // Only clean if this is a root result (no parent) + if (parent != null) { + return; + } + + // Check if we're part of a parent transaction by walking up the sampler hierarchy + JMeterContext context = JMeterContextService.getContext(); + if (context != null) { + Sampler currentSampler = context.getCurrentSampler(); + if (currentSampler instanceof TransactionSampler) { + TransactionSampler transSampler = (TransactionSampler) currentSampler; + // Get the parent sampler from the transaction + Sampler parentSampler = transSampler.getSubSampler(); + // If there's a parent sampler and it's a transaction, we're nested + if (parentSampler instanceof TransactionSampler) { + return; + } + } + } + + cleanRecursively(); + } + + /** + * Internal method to clean this result and all its sub-results + */ + private void cleanRecursively() { + // Clean sub-results first + if (subResults != null) { + for (SampleResult subResult : subResults) { + if (subResult != null) { + subResult.cleanRecursively(); + } + } + subResults.clear(); + subResults = null; + } + + // Clean assertion results + if (assertionResults != null) { + assertionResults.clear(); + assertionResults = null; + } + + // Clear only memory-heavy data and caches, preserve samplerData + this.parent = null; this.responseDataAsString = null; + this.responseData = EMPTY_BA; + this.responseHeaders = ""; + this.requestHeaders = ""; + this.samplerData = null; + } @Override @@ -1666,4 +1721,50 @@ public TestLogicalAction getTestLogicalAction() { public void setTestLogicalAction(TestLogicalAction testLogicalAction) { this.testLogicalAction = testLogicalAction; } + + /** + * Create a deep copy for async listeners + * @return A deep copy of this result + */ + public SampleResult cloneForListeners() { + // Create clone with the correct type + SampleResult clone; + try { + // Use the same constructor that was used to create this instance + clone = this.getClass().getConstructor(this.getClass()).newInstance(this); + } catch (Exception e) { + // Fallback to base class if constructor is not available + log.debug("Could not create clone with type: " + this.getClass().getName() + ", using base class", e); + clone = new SampleResult(this); + } + + // Deep copy mutable fields that the copy constructor doesn't handle deeply + if (responseData != EMPTY_BA) { + clone.responseData = responseData.clone(); + } + + // Deep copy subResults + if (subResults != null) { + clone.subResults = new ArrayList<>(subResults.size()); + for (SampleResult sub : subResults) { + SampleResult subClone = sub.cloneForListeners(); + subClone.setParent(clone); + clone.subResults.add(subClone); + } + } + + // Deep copy assertion results + if (assertionResults != null) { + clone.assertionResults = new ArrayList<>(assertionResults.size()); + for (AssertionResult assertionResult : assertionResults) { + clone.assertionResults.add(assertionResult); // AssertionResult is immutable + } + } + + // Clear only the caches and unnecessary references in the clone + clone.responseDataAsString = null; + clone.parent = null; // Parent reference not needed in the clone + + return clone; + } } diff --git a/src/core/src/main/java/org/apache/jmeter/threads/JMeterThread.java b/src/core/src/main/java/org/apache/jmeter/threads/JMeterThread.java index 35f94b26982..2f749a91a32 100644 --- a/src/core/src/main/java/org/apache/jmeter/threads/JMeterThread.java +++ b/src/core/src/main/java/org/apache/jmeter/threads/JMeterThread.java @@ -672,6 +672,12 @@ private SampleResult doEndTransactionSampler( notifyListeners(transactionPack.getSampleListeners(), transactionResult); } compiler.done(transactionPack); + + // Clean up the transaction result after listeners have processed it + if (transactionResult != null) { + transactionResult.cleanAfterSample(); + } + return transactionResult; } @@ -1028,7 +1034,7 @@ void notifyTestListeners() { } private void notifyListeners(List listeners, SampleResult result) { - SampleEvent event = new SampleEvent(result, threadGroup.getName(), threadVars); + SampleEvent event = new SampleEvent(result.cloneForListeners(), threadGroup.getName(), threadVars); notifier.notifyListeners(event, listeners); } From 7b0dd68de0d9caa80f9577b029aaf7c85338ccc5 Mon Sep 17 00:00:00 2001 From: jvangaalen Date: Wed, 4 Dec 2024 09:43:11 +0100 Subject: [PATCH 2/5] Fix styling --- .../apache/jmeter/samplers/SampleResult.java | 26 +++++++++---------- .../apache/jmeter/threads/JMeterThread.java | 4 +-- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/core/src/main/java/org/apache/jmeter/samplers/SampleResult.java b/src/core/src/main/java/org/apache/jmeter/samplers/SampleResult.java index b998818a6e8..b7c245542e0 100644 --- a/src/core/src/main/java/org/apache/jmeter/samplers/SampleResult.java +++ b/src/core/src/main/java/org/apache/jmeter/samplers/SampleResult.java @@ -30,12 +30,12 @@ import java.util.concurrent.TimeUnit; import org.apache.jmeter.assertions.AssertionResult; +import org.apache.jmeter.control.TransactionSampler; import org.apache.jmeter.gui.Searchable; import org.apache.jmeter.testelement.TestPlan; import org.apache.jmeter.threads.JMeterContext; -import org.apache.jmeter.threads.JMeterContextService; import org.apache.jmeter.threads.JMeterContext.TestLogicalAction; -import org.apache.jmeter.control.TransactionSampler; +import org.apache.jmeter.threads.JMeterContextService; import org.apache.jmeter.util.JMeterUtils; import org.apache.jorphan.util.JOrphanUtils; import org.apache.jorphan.util.StringUtilities; @@ -1606,7 +1606,7 @@ public void cleanAfterSample() { if (parent != null) { return; } - + // Check if we're part of a parent transaction by walking up the sampler hierarchy JMeterContext context = JMeterContextService.getContext(); if (context != null) { @@ -1621,14 +1621,14 @@ public void cleanAfterSample() { } } } - + cleanRecursively(); } - + /** * Internal method to clean this result and all its sub-results */ - private void cleanRecursively() { + private void cleanRecursively() { // Clean sub-results first if (subResults != null) { for (SampleResult subResult : subResults) { @@ -1639,13 +1639,13 @@ private void cleanRecursively() { subResults.clear(); subResults = null; } - + // Clean assertion results if (assertionResults != null) { assertionResults.clear(); assertionResults = null; } - + // Clear only memory-heavy data and caches, preserve samplerData this.parent = null; this.responseDataAsString = null; @@ -1737,12 +1737,12 @@ public SampleResult cloneForListeners() { log.debug("Could not create clone with type: " + this.getClass().getName() + ", using base class", e); clone = new SampleResult(this); } - + // Deep copy mutable fields that the copy constructor doesn't handle deeply if (responseData != EMPTY_BA) { clone.responseData = responseData.clone(); } - + // Deep copy subResults if (subResults != null) { clone.subResults = new ArrayList<>(subResults.size()); @@ -1752,7 +1752,7 @@ public SampleResult cloneForListeners() { clone.subResults.add(subClone); } } - + // Deep copy assertion results if (assertionResults != null) { clone.assertionResults = new ArrayList<>(assertionResults.size()); @@ -1760,11 +1760,11 @@ public SampleResult cloneForListeners() { clone.assertionResults.add(assertionResult); // AssertionResult is immutable } } - + // Clear only the caches and unnecessary references in the clone clone.responseDataAsString = null; clone.parent = null; // Parent reference not needed in the clone - + return clone; } } diff --git a/src/core/src/main/java/org/apache/jmeter/threads/JMeterThread.java b/src/core/src/main/java/org/apache/jmeter/threads/JMeterThread.java index 2f749a91a32..faaf03e9827 100644 --- a/src/core/src/main/java/org/apache/jmeter/threads/JMeterThread.java +++ b/src/core/src/main/java/org/apache/jmeter/threads/JMeterThread.java @@ -672,12 +672,12 @@ private SampleResult doEndTransactionSampler( notifyListeners(transactionPack.getSampleListeners(), transactionResult); } compiler.done(transactionPack); - + // Clean up the transaction result after listeners have processed it if (transactionResult != null) { transactionResult.cleanAfterSample(); } - + return transactionResult; } From 12f8439b801e5e2041ab35e839830c9bcaf73622 Mon Sep 17 00:00:00 2001 From: jvangaalen Date: Sun, 8 Dec 2024 16:47:11 +0100 Subject: [PATCH 3/5] Revert "doc: update documentation for sampleresult.default.encoding default value" This reverts commit 4340b2a048b04169b98d54f6a1a1fb4ca7059cc7. --- bin/jmeter.properties | 4 +-- .../apache/jmeter/samplers/SampleResult.java | 7 +++- xdocs/changes.xml | 35 +++++++++++++++++++ xdocs/usermanual/properties_reference.xml | 2 +- 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/bin/jmeter.properties b/bin/jmeter.properties index 58c540cfd9c..8fc2432692a 100644 --- a/bin/jmeter.properties +++ b/bin/jmeter.properties @@ -1101,8 +1101,8 @@ csvdataset.file.encoding_list=UTF-8|UTF-16|ISO-8859-15|US-ASCII # List of extra HTTP methods that should be available in select box #httpsampler.user_defined_methods=VERSION-CONTROL,REPORT,CHECKOUT,CHECKIN,UNCHECKOUT,MKWORKSPACE,UPDATE,LABEL,MERGE,BASELINE-CONTROL,MKACTIVITY -# The encoding to be used if none is provided (default UTF-8 since JMeter 5.6.1) -#sampleresult.default.encoding=UTF-8 +# The encoding to be used if none is provided (default ISO-8859-1) +#sampleresult.default.encoding=ISO-8859-1 # CookieManager behaviour - should cookies with null/empty values be deleted? # Default is true. Use false to revert to original behaviour diff --git a/src/core/src/main/java/org/apache/jmeter/samplers/SampleResult.java b/src/core/src/main/java/org/apache/jmeter/samplers/SampleResult.java index b7c245542e0..11f1d3218d9 100644 --- a/src/core/src/main/java/org/apache/jmeter/samplers/SampleResult.java +++ b/src/core/src/main/java/org/apache/jmeter/samplers/SampleResult.java @@ -67,10 +67,15 @@ public class SampleResult implements Serializable, Cloneable, Searchable { private static final String INVALID_CALL_SEQUENCE_MSG = "Invalid call sequence"; // $NON-NLS-1$ + // Bug 33196 - encoding ISO-8859-1 is only suitable for Western countries + // However the suggested System.getProperty("file.encoding") is Cp1252 on + // Windows + // So use a new property with the original value as default + // needs to be accessible from test code /** * The default encoding to be used to decode the responseData byte array. * The value is defined by the property "sampleresult.default.encoding" - * with a default of {@link #DEFAULT_HTTP_ENCODING} if that is not defined. + * with a default of DEFAULT_HTTP_ENCODING if that is not defined. */ protected static final String DEFAULT_ENCODING = JMeterUtils.getPropDefault("sampleresult.default.encoding", // $NON-NLS-1$ diff --git a/xdocs/changes.xml b/xdocs/changes.xml index 17d8185c337..4c9af493671 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -70,6 +70,41 @@ Summary Timer relative to start of Thread Group instead of the start of the test.
  • 63576358 Ensure writable directories when copying template files while report generation.
  • +New and Noteworthy + +Improvements + +

    HTTP Samplers and Test Script Recorder

    +
      +
    • 6010Use UTF-8 as a default encoding in HTTP sampler. It enables sending parameter names, and filenames with unicode characters
    • +
    • 6010Test Recorder will use UTF-8 encoding by default, so it will infer human-readable arguments rather than percent-encoded ones
    • +
    + +Non-functional changes +
      +
    • 6000Add release-drafter for populating GitHub releases info based on the merged PRs
    • +
    • 5989Use Gradle toolchains for JDK provisioning, enable building and testing with different JDKs, start testing with Java 21
    • +
    • 5991Update jackson-core, jackson-databind, jackson-annotations to 2.15.2 (from 2.15.1)
    • +
    • 5993Update ph-commons to 10.2.5 (from 10.2.4)
    • +
    • 6017Update kotlin-stdlib to 1.8.22 (from 1.8.21)
    • +
    • 6020Update error_prone_annotations to 2.20.0 (from 2.19.1)
    • +
    • 6023Update checker-qual to 3.35.0 (from 3.34.0)
    • +
    + + + +Bug fixes + +

    Thread Groups

    +
      +
    • 6011Regression since 5.6: ThreadGroups are running endlessly in non-gui mode: use default value + for LoopController.continue_forever rather than initializing it in the constructor
    • +
    + +

    Other Samplers

    +
      +
    • 6012 Java Request sampler cannot be enabled again after disabling in UI (regression since 5.6)
    • +

    HTTP Samplers and Test Script Recorder

      diff --git a/xdocs/usermanual/properties_reference.xml b/xdocs/usermanual/properties_reference.xml index a40ae5027a6..5a13cbc39ef 100644 --- a/xdocs/usermanual/properties_reference.xml +++ b/xdocs/usermanual/properties_reference.xml @@ -1395,7 +1395,7 @@ JMETER-SERVER The encoding to be used if none is provided.
      - Defaults to: UTF-8 (since 5.6.1) + Defaults to: ISO-8859-1
      CookieManager behaviour - should cookies with null/empty values be deleted?
      From 20a50c48d6291c4e70bd43faa408e3cc71d6946a Mon Sep 17 00:00:00 2001 From: jvangaalen Date: Tue, 10 Dec 2024 13:35:07 +0100 Subject: [PATCH 4/5] Clear transaction from subresults --- .../apache/jmeter/samplers/SampleResult.java | 110 +----------------- .../apache/jmeter/threads/JMeterThread.java | 8 +- .../apache/jmeter/threads/TestCompiler.java | 13 ++- .../org/apache/jmeter/junit/JMeterTest.java | 3 +- 4 files changed, 17 insertions(+), 117 deletions(-) diff --git a/src/core/src/main/java/org/apache/jmeter/samplers/SampleResult.java b/src/core/src/main/java/org/apache/jmeter/samplers/SampleResult.java index 11f1d3218d9..4888d250fcb 100644 --- a/src/core/src/main/java/org/apache/jmeter/samplers/SampleResult.java +++ b/src/core/src/main/java/org/apache/jmeter/samplers/SampleResult.java @@ -30,12 +30,9 @@ import java.util.concurrent.TimeUnit; import org.apache.jmeter.assertions.AssertionResult; -import org.apache.jmeter.control.TransactionSampler; import org.apache.jmeter.gui.Searchable; import org.apache.jmeter.testelement.TestPlan; -import org.apache.jmeter.threads.JMeterContext; import org.apache.jmeter.threads.JMeterContext.TestLogicalAction; -import org.apache.jmeter.threads.JMeterContextService; import org.apache.jmeter.util.JMeterUtils; import org.apache.jorphan.util.JOrphanUtils; import org.apache.jorphan.util.StringUtilities; @@ -67,15 +64,10 @@ public class SampleResult implements Serializable, Cloneable, Searchable { private static final String INVALID_CALL_SEQUENCE_MSG = "Invalid call sequence"; // $NON-NLS-1$ - // Bug 33196 - encoding ISO-8859-1 is only suitable for Western countries - // However the suggested System.getProperty("file.encoding") is Cp1252 on - // Windows - // So use a new property with the original value as default - // needs to be accessible from test code /** * The default encoding to be used to decode the responseData byte array. * The value is defined by the property "sampleresult.default.encoding" - * with a default of DEFAULT_HTTP_ENCODING if that is not defined. + * with a default of {@link #DEFAULT_HTTP_ENCODING} if that is not defined. */ protected static final String DEFAULT_ENCODING = JMeterUtils.getPropDefault("sampleresult.default.encoding", // $NON-NLS-1$ @@ -1603,62 +1595,10 @@ public void setStartNextThreadLoop(boolean startNextThreadLoop) { } /** - * Clean up cached data, but only if this is a root result (no parent) - * and not part of a parent transaction. + * Clean up cached data */ public void cleanAfterSample() { - // Only clean if this is a root result (no parent) - if (parent != null) { - return; - } - - // Check if we're part of a parent transaction by walking up the sampler hierarchy - JMeterContext context = JMeterContextService.getContext(); - if (context != null) { - Sampler currentSampler = context.getCurrentSampler(); - if (currentSampler instanceof TransactionSampler) { - TransactionSampler transSampler = (TransactionSampler) currentSampler; - // Get the parent sampler from the transaction - Sampler parentSampler = transSampler.getSubSampler(); - // If there's a parent sampler and it's a transaction, we're nested - if (parentSampler instanceof TransactionSampler) { - return; - } - } - } - - cleanRecursively(); - } - - /** - * Internal method to clean this result and all its sub-results - */ - private void cleanRecursively() { - // Clean sub-results first - if (subResults != null) { - for (SampleResult subResult : subResults) { - if (subResult != null) { - subResult.cleanRecursively(); - } - } - subResults.clear(); - subResults = null; - } - - // Clean assertion results - if (assertionResults != null) { - assertionResults.clear(); - assertionResults = null; - } - - // Clear only memory-heavy data and caches, preserve samplerData - this.parent = null; this.responseDataAsString = null; - this.responseData = EMPTY_BA; - this.responseHeaders = ""; - this.requestHeaders = ""; - this.samplerData = null; - } @Override @@ -1726,50 +1666,4 @@ public TestLogicalAction getTestLogicalAction() { public void setTestLogicalAction(TestLogicalAction testLogicalAction) { this.testLogicalAction = testLogicalAction; } - - /** - * Create a deep copy for async listeners - * @return A deep copy of this result - */ - public SampleResult cloneForListeners() { - // Create clone with the correct type - SampleResult clone; - try { - // Use the same constructor that was used to create this instance - clone = this.getClass().getConstructor(this.getClass()).newInstance(this); - } catch (Exception e) { - // Fallback to base class if constructor is not available - log.debug("Could not create clone with type: " + this.getClass().getName() + ", using base class", e); - clone = new SampleResult(this); - } - - // Deep copy mutable fields that the copy constructor doesn't handle deeply - if (responseData != EMPTY_BA) { - clone.responseData = responseData.clone(); - } - - // Deep copy subResults - if (subResults != null) { - clone.subResults = new ArrayList<>(subResults.size()); - for (SampleResult sub : subResults) { - SampleResult subClone = sub.cloneForListeners(); - subClone.setParent(clone); - clone.subResults.add(subClone); - } - } - - // Deep copy assertion results - if (assertionResults != null) { - clone.assertionResults = new ArrayList<>(assertionResults.size()); - for (AssertionResult assertionResult : assertionResults) { - clone.assertionResults.add(assertionResult); // AssertionResult is immutable - } - } - - // Clear only the caches and unnecessary references in the clone - clone.responseDataAsString = null; - clone.parent = null; // Parent reference not needed in the clone - - return clone; - } } diff --git a/src/core/src/main/java/org/apache/jmeter/threads/JMeterThread.java b/src/core/src/main/java/org/apache/jmeter/threads/JMeterThread.java index faaf03e9827..35f94b26982 100644 --- a/src/core/src/main/java/org/apache/jmeter/threads/JMeterThread.java +++ b/src/core/src/main/java/org/apache/jmeter/threads/JMeterThread.java @@ -672,12 +672,6 @@ private SampleResult doEndTransactionSampler( notifyListeners(transactionPack.getSampleListeners(), transactionResult); } compiler.done(transactionPack); - - // Clean up the transaction result after listeners have processed it - if (transactionResult != null) { - transactionResult.cleanAfterSample(); - } - return transactionResult; } @@ -1034,7 +1028,7 @@ void notifyTestListeners() { } private void notifyListeners(List listeners, SampleResult result) { - SampleEvent event = new SampleEvent(result.cloneForListeners(), threadGroup.getName(), threadVars); + SampleEvent event = new SampleEvent(result, threadGroup.getName(), threadVars); notifier.notifyListeners(event, listeners); } diff --git a/src/core/src/main/java/org/apache/jmeter/threads/TestCompiler.java b/src/core/src/main/java/org/apache/jmeter/threads/TestCompiler.java index 14b537a0e19..5f399b4d0c6 100644 --- a/src/core/src/main/java/org/apache/jmeter/threads/TestCompiler.java +++ b/src/core/src/main/java/org/apache/jmeter/threads/TestCompiler.java @@ -115,10 +115,21 @@ public SamplePackage configureTransactionSampler(TransactionSampler transactionS } /** - * Reset pack to its initial state + * Reset pack to its initial state and clean up transaction results if needed * @param pack the {@link SamplePackage} to reset */ public void done(SamplePackage pack) { + Sampler sampler = pack.getSampler(); + if (sampler instanceof TransactionSampler) { + TransactionSampler transactionSampler = (TransactionSampler) sampler; + TransactionController controller = transactionSampler.getTransactionController(); + if (transactionSampler.isTransactionDone()) { + // Create new sampler for next iteration + TransactionSampler newSampler = new TransactionSampler(controller, transactionSampler.getName()); + SamplePackage newPack = transactionControllerConfigMap.get(controller); + newPack.setSampler(newSampler); + } + } pack.recoverRunningVersion(); } diff --git a/src/dist-check/src/test/java/org/apache/jmeter/junit/JMeterTest.java b/src/dist-check/src/test/java/org/apache/jmeter/junit/JMeterTest.java index 2aca34f3e1e..72b6fb2e125 100644 --- a/src/dist-check/src/test/java/org/apache/jmeter/junit/JMeterTest.java +++ b/src/dist-check/src/test/java/org/apache/jmeter/junit/JMeterTest.java @@ -581,7 +581,8 @@ static Stream serializableObjects() throws Throwable { return getObjects(Serializable.class) .stream() .map(Serializable.class::cast) - .filter(o -> !o.getClass().getName().endsWith("_Stub")); + .filter(o -> !o.getClass().getName().endsWith("_Stub")) + .filter(o -> o.getClass().getName().startsWith("org.apache.jmeter.")); } /** From dc0521523de8df816e34b69c050001120372eefb Mon Sep 17 00:00:00 2001 From: jvangaalen Date: Tue, 10 Dec 2024 13:44:24 +0100 Subject: [PATCH 5/5] Revert "Revert "doc: update documentation for sampleresult.default.encoding default value"" This reverts commit 78a51ceb09cb43dca8418abc9bc62581a30b39be. --- bin/jmeter.properties | 4 +-- xdocs/changes.xml | 35 ----------------------- xdocs/usermanual/properties_reference.xml | 2 +- 3 files changed, 3 insertions(+), 38 deletions(-) diff --git a/bin/jmeter.properties b/bin/jmeter.properties index 8fc2432692a..58c540cfd9c 100644 --- a/bin/jmeter.properties +++ b/bin/jmeter.properties @@ -1101,8 +1101,8 @@ csvdataset.file.encoding_list=UTF-8|UTF-16|ISO-8859-15|US-ASCII # List of extra HTTP methods that should be available in select box #httpsampler.user_defined_methods=VERSION-CONTROL,REPORT,CHECKOUT,CHECKIN,UNCHECKOUT,MKWORKSPACE,UPDATE,LABEL,MERGE,BASELINE-CONTROL,MKACTIVITY -# The encoding to be used if none is provided (default ISO-8859-1) -#sampleresult.default.encoding=ISO-8859-1 +# The encoding to be used if none is provided (default UTF-8 since JMeter 5.6.1) +#sampleresult.default.encoding=UTF-8 # CookieManager behaviour - should cookies with null/empty values be deleted? # Default is true. Use false to revert to original behaviour diff --git a/xdocs/changes.xml b/xdocs/changes.xml index 4c9af493671..17d8185c337 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -70,41 +70,6 @@ Summary Timer relative to start of Thread Group instead of the start of the test.
    • 63576358 Ensure writable directories when copying template files while report generation.
    -New and Noteworthy - -Improvements - -

    HTTP Samplers and Test Script Recorder

    -
      -
    • 6010Use UTF-8 as a default encoding in HTTP sampler. It enables sending parameter names, and filenames with unicode characters
    • -
    • 6010Test Recorder will use UTF-8 encoding by default, so it will infer human-readable arguments rather than percent-encoded ones
    • -
    - -Non-functional changes -
      -
    • 6000Add release-drafter for populating GitHub releases info based on the merged PRs
    • -
    • 5989Use Gradle toolchains for JDK provisioning, enable building and testing with different JDKs, start testing with Java 21
    • -
    • 5991Update jackson-core, jackson-databind, jackson-annotations to 2.15.2 (from 2.15.1)
    • -
    • 5993Update ph-commons to 10.2.5 (from 10.2.4)
    • -
    • 6017Update kotlin-stdlib to 1.8.22 (from 1.8.21)
    • -
    • 6020Update error_prone_annotations to 2.20.0 (from 2.19.1)
    • -
    • 6023Update checker-qual to 3.35.0 (from 3.34.0)
    • -
    - - - -Bug fixes - -

    Thread Groups

    -
      -
    • 6011Regression since 5.6: ThreadGroups are running endlessly in non-gui mode: use default value - for LoopController.continue_forever rather than initializing it in the constructor
    • -
    - -

    Other Samplers

    -
      -
    • 6012 Java Request sampler cannot be enabled again after disabling in UI (regression since 5.6)
    • -

    HTTP Samplers and Test Script Recorder

      diff --git a/xdocs/usermanual/properties_reference.xml b/xdocs/usermanual/properties_reference.xml index 5a13cbc39ef..a40ae5027a6 100644 --- a/xdocs/usermanual/properties_reference.xml +++ b/xdocs/usermanual/properties_reference.xml @@ -1395,7 +1395,7 @@ JMETER-SERVER The encoding to be used if none is provided.
      - Defaults to: ISO-8859-1 + Defaults to: UTF-8 (since 5.6.1)
      CookieManager behaviour - should cookies with null/empty values be deleted?