From 403842148e82c24e560c365efd8b7290076b0ba5 Mon Sep 17 00:00:00 2001 From: Vladimir Sitnikov Date: Fri, 10 Dec 2021 16:34:56 +0300 Subject: [PATCH 001/736] Update log4j2 to 2.15.0 to fix CVE-2021-44228: Apache Log4j2 JNDI features do not protect against attacker controlled LDAP and other JNDI related endpoints See https://logging.apache.org/log4j/2.x/security.html --- gradle.properties | 2 +- src/dist/src/dist/expected_release_jars.csv | 8 ++++---- xdocs/changes.xml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/gradle.properties b/gradle.properties index 4c87f94cd6a..f516d615f2b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -115,7 +115,7 @@ junit4.version=4.13.2 junit5.version=5.8.1 lets-plot-batik.version=2.2.0 lets-plot-kotlin-jvm.version=3.1.0 -log4j.version=2.14.1 +log4j.version=2.15.0 mail.version=1.5.0-b01 miglayout.version=5.3 mina-core.version=2.0.19 diff --git a/src/dist/src/dist/expected_release_jars.csv b/src/dist/src/dist/expected_release_jars.csv index 0d377ae880f..ff087660121 100644 --- a/src/dist/src/dist/expected_release_jars.csv +++ b/src/dist/src/dist/expected_release_jars.csv @@ -94,10 +94,10 @@ 792176,kotlinx-html-jvm-0.7.3.jar 191102,lets-plot-batik-2.2.0.jar 3995999,lets-plot-common-2.2.0.jar -206756,log4j-1.2-api-2.14.1.jar -300365,log4j-api-2.14.1.jar -1745700,log4j-core-2.14.1.jar -23625,log4j-slf4j-impl-2.14.1.jar +207879,log4j-1.2-api-2.15.0.jar +301804,log4j-api-2.15.0.jar +1789769,log4j-core-2.15.0.jar +24231,log4j-slf4j-impl-2.15.0.jar 519087,mail-1.5.0-b01.jar 106949,miglayout-core-5.3.jar 22576,miglayout-swing-5.3.jar diff --git a/xdocs/changes.xml b/xdocs/changes.xml index 548a1c25cce..69f6b0eb151 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -168,7 +168,7 @@ Summary
  • Updated json-path to 2.6.0 (from 2.4.0).
  • Updated jsoup to 1.14.1 (from 1.13.1).
  • Updated JUnit to 4.13.2 and 5.8.1 (from 4.13.1 and 5.7.0).
  • -
  • Updated Apache log4j2 to 2.14.1 (from 2.13.3).
  • +
  • Updated Apache log4j2 to 2.15.0 (from 2.13.3).
  • Updated Miglayout to 5.3 (from 5.2).
  • Updated Neo4j Java driver to 4.3.3 (from 4.2.0).
  • Updated Objenesis to 3.2 (from 2.6).
  • From bdc610a1df6d5d92e7b8ee2e36f186a45ba0d428 Mon Sep 17 00:00:00 2001 From: Vladimir Sitnikov Date: Tue, 14 Dec 2021 17:51:09 +0300 Subject: [PATCH 002/736] Update log4j2 to 2.16.0 See https://lists.apache.org/thread/d6v4r6nosxysyq9rvnr779336yf0woz4 --- gradle.properties | 2 +- src/dist/src/dist/expected_release_jars.csv | 8 ++++---- xdocs/changes.xml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/gradle.properties b/gradle.properties index f516d615f2b..f5c262fbae2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -115,7 +115,7 @@ junit4.version=4.13.2 junit5.version=5.8.1 lets-plot-batik.version=2.2.0 lets-plot-kotlin-jvm.version=3.1.0 -log4j.version=2.15.0 +log4j.version=2.16.0 mail.version=1.5.0-b01 miglayout.version=5.3 mina-core.version=2.0.19 diff --git a/src/dist/src/dist/expected_release_jars.csv b/src/dist/src/dist/expected_release_jars.csv index ff087660121..ee47255c6bf 100644 --- a/src/dist/src/dist/expected_release_jars.csv +++ b/src/dist/src/dist/expected_release_jars.csv @@ -94,10 +94,10 @@ 792176,kotlinx-html-jvm-0.7.3.jar 191102,lets-plot-batik-2.2.0.jar 3995999,lets-plot-common-2.2.0.jar -207879,log4j-1.2-api-2.15.0.jar -301804,log4j-api-2.15.0.jar -1789769,log4j-core-2.15.0.jar -24231,log4j-slf4j-impl-2.15.0.jar +207909,log4j-1.2-api-2.16.0.jar +301892,log4j-api-2.16.0.jar +1789565,log4j-core-2.16.0.jar +24258,log4j-slf4j-impl-2.16.0.jar 519087,mail-1.5.0-b01.jar 106949,miglayout-core-5.3.jar 22576,miglayout-swing-5.3.jar diff --git a/xdocs/changes.xml b/xdocs/changes.xml index 69f6b0eb151..967f6b89d29 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -168,7 +168,7 @@ Summary
  • Updated json-path to 2.6.0 (from 2.4.0).
  • Updated jsoup to 1.14.1 (from 1.13.1).
  • Updated JUnit to 4.13.2 and 5.8.1 (from 4.13.1 and 5.7.0).
  • -
  • Updated Apache log4j2 to 2.15.0 (from 2.13.3).
  • +
  • Updated Apache log4j2 to 2.16.0 (from 2.13.3).
  • Updated Miglayout to 5.3 (from 5.2).
  • Updated Neo4j Java driver to 4.3.3 (from 4.2.0).
  • Updated Objenesis to 3.2 (from 2.6).
  • From 0551e4cef9c693fb1661580a3abb212763104a9d Mon Sep 17 00:00:00 2001 From: Vladimir Sitnikov Date: Tue, 14 Dec 2021 18:06:31 +0300 Subject: [PATCH 003/736] Add Matt Sicker's b4c70893b62babe8 key for org.apache.logging.log4j See https://downloads.apache.org/logging/KEYS --- checksum.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/checksum.xml b/checksum.xml index e197b841691..c335c72277a 100644 --- a/checksum.xml +++ b/checksum.xml @@ -124,6 +124,7 @@ + From f2f4a0e7fbc0b527929e0d1e7235d62175abf122 Mon Sep 17 00:00:00 2001 From: Milamber Date: Fri, 17 Dec 2021 10:54:53 +0100 Subject: [PATCH 004/736] Add the 5.4.2 release --- doap_JMeter.rdf | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doap_JMeter.rdf b/doap_JMeter.rdf index 347f21ee5b1..24d6f555584 100644 --- a/doap_JMeter.rdf +++ b/doap_JMeter.rdf @@ -300,6 +300,13 @@ 5.4.1 final + + + Apache JMeter + 2021-12-16 + 5.4.2 final + + From 5f1d3d27dfda35fd5c604156ad1d2c02e0063691 Mon Sep 17 00:00:00 2001 From: Chromico Rek Date: Sun, 19 Dec 2021 20:08:48 +0400 Subject: [PATCH 005/736] Update log4j to 2.17.0 Relates to CVE-2021-45105 Closes #683 --- gradle.properties | 2 +- src/dist/src/dist/expected_release_jars.csv | 8 ++++---- xdocs/changes.xml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/gradle.properties b/gradle.properties index f5c262fbae2..bb5ff14426e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -115,7 +115,7 @@ junit4.version=4.13.2 junit5.version=5.8.1 lets-plot-batik.version=2.2.0 lets-plot-kotlin-jvm.version=3.1.0 -log4j.version=2.16.0 +log4j.version=2.17.0 mail.version=1.5.0-b01 miglayout.version=5.3 mina-core.version=2.0.19 diff --git a/src/dist/src/dist/expected_release_jars.csv b/src/dist/src/dist/expected_release_jars.csv index ee47255c6bf..52aaea2489c 100644 --- a/src/dist/src/dist/expected_release_jars.csv +++ b/src/dist/src/dist/expected_release_jars.csv @@ -94,10 +94,10 @@ 792176,kotlinx-html-jvm-0.7.3.jar 191102,lets-plot-batik-2.2.0.jar 3995999,lets-plot-common-2.2.0.jar -207909,log4j-1.2-api-2.16.0.jar -301892,log4j-api-2.16.0.jar -1789565,log4j-core-2.16.0.jar -24258,log4j-slf4j-impl-2.16.0.jar +207909,log4j-1.2-api-2.17.0.jar +301892,log4j-api-2.17.0.jar +1789565,log4j-core-2.17.0.jar +24258,log4j-slf4j-impl-2.17.0.jar 519087,mail-1.5.0-b01.jar 106949,miglayout-core-5.3.jar 22576,miglayout-swing-5.3.jar diff --git a/xdocs/changes.xml b/xdocs/changes.xml index 967f6b89d29..af8db71c33f 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -168,7 +168,7 @@ Summary
  • Updated json-path to 2.6.0 (from 2.4.0).
  • Updated jsoup to 1.14.1 (from 1.13.1).
  • Updated JUnit to 4.13.2 and 5.8.1 (from 4.13.1 and 5.7.0).
  • -
  • Updated Apache log4j2 to 2.16.0 (from 2.13.3).
  • +
  • Updated Apache log4j2 to 2.17.0 (from 2.13.3).
  • Updated Miglayout to 5.3 (from 5.2).
  • Updated Neo4j Java driver to 4.3.3 (from 4.2.0).
  • Updated Objenesis to 3.2 (from 2.6).
  • From 610eeeb866b1fda23025787e70bf0a81d0e8740c Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Sun, 19 Dec 2021 19:17:22 +0100 Subject: [PATCH 006/736] Update expected_release_jars.csv for log4j 2.17.0 --- src/dist/src/dist/expected_release_jars.csv | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/dist/src/dist/expected_release_jars.csv b/src/dist/src/dist/expected_release_jars.csv index 52aaea2489c..8ef431f9fe3 100644 --- a/src/dist/src/dist/expected_release_jars.csv +++ b/src/dist/src/dist/expected_release_jars.csv @@ -94,10 +94,10 @@ 792176,kotlinx-html-jvm-0.7.3.jar 191102,lets-plot-batik-2.2.0.jar 3995999,lets-plot-common-2.2.0.jar -207909,log4j-1.2-api-2.17.0.jar -301892,log4j-api-2.17.0.jar -1789565,log4j-core-2.17.0.jar -24258,log4j-slf4j-impl-2.17.0.jar +208235,log4j-1.2-api-2.17.0.jar +301776,log4j-api-2.17.0.jar +1789339,log4j-core-2.17.0.jar +24252,log4j-slf4j-impl-2.17.0.jar 519087,mail-1.5.0-b01.jar 106949,miglayout-core-5.3.jar 22576,miglayout-swing-5.3.jar From ac47049163a20bf2982911829e0e457fa7dd0641 Mon Sep 17 00:00:00 2001 From: Milamber Date: Fri, 24 Dec 2021 16:06:29 +0100 Subject: [PATCH 007/736] Add the 5.4.3 release --- doap_JMeter.rdf | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doap_JMeter.rdf b/doap_JMeter.rdf index 24d6f555584..414ac06cdcd 100644 --- a/doap_JMeter.rdf +++ b/doap_JMeter.rdf @@ -307,6 +307,13 @@ 5.4.2 final + + + Apache JMeter + 2021-12-24 + 5.4.3 final + + From 3236c61a94ef0fddb5549d8887b2e714ac772b12 Mon Sep 17 00:00:00 2001 From: Vladimir Sitnikov Date: Tue, 14 Dec 2021 19:56:02 +0300 Subject: [PATCH 008/736] Bump lets-plot to 2.2.1 and 3.1.1 It resolves * https://github.com/JetBrains/lets-plot/issues/472 * https://github.com/JetBrains/lets-plot/issues/485 --- gradle.properties | 4 +-- .../threads/openmodel/gui/TargetRateChart.kt | 28 ++++++++----------- src/dist/src/dist/expected_release_jars.csv | 18 ++++++------ src/licenses/build.gradle.kts | 18 ------------ src/licenses/licenses/lets-plot/LICENSE | 21 -------------- 5 files changed, 23 insertions(+), 66 deletions(-) delete mode 100644 src/licenses/licenses/lets-plot/LICENSE diff --git a/gradle.properties b/gradle.properties index bb5ff14426e..154d602a448 100644 --- a/gradle.properties +++ b/gradle.properties @@ -113,8 +113,8 @@ jsoup.version=1.14.1 jtidy.version=r938 junit4.version=4.13.2 junit5.version=5.8.1 -lets-plot-batik.version=2.2.0 -lets-plot-kotlin-jvm.version=3.1.0 +lets-plot-batik.version=2.2.1 +lets-plot-kotlin-jvm.version=3.1.1 log4j.version=2.17.0 mail.version=1.5.0-b01 miglayout.version=5.3 diff --git a/src/core/src/main/kotlin/org/apache/jmeter/threads/openmodel/gui/TargetRateChart.kt b/src/core/src/main/kotlin/org/apache/jmeter/threads/openmodel/gui/TargetRateChart.kt index 306803612d8..facfb6182f0 100644 --- a/src/core/src/main/kotlin/org/apache/jmeter/threads/openmodel/gui/TargetRateChart.kt +++ b/src/core/src/main/kotlin/org/apache/jmeter/threads/openmodel/gui/TargetRateChart.kt @@ -24,7 +24,7 @@ import jetbrains.letsPlot.geom.geomLine import jetbrains.letsPlot.intern.toSpec import jetbrains.letsPlot.label.ggtitle import jetbrains.letsPlot.letsPlot -import jetbrains.letsPlot.scale.scaleXContinuous +import jetbrains.letsPlot.scale.scaleXTime import jetbrains.letsPlot.theme import org.apache.jmeter.threads.openmodel.ThreadSchedule import org.apache.jmeter.threads.openmodel.ThreadScheduleStep @@ -51,10 +51,15 @@ public class TargetRateChart : JPanel() { layout = BorderLayout() } + private var prevSteps: List? = null private var prevTimes: DoubleArray? = null private var prevRate: DoubleArray? = null public fun updateSchedule(threadSchedule: ThreadSchedule) { + if (threadSchedule.steps == prevSteps) { + return + } + prevSteps = threadSchedule.steps val timeValues = mutableListOf() val rateValues = mutableListOf() var time = 0.0 @@ -92,18 +97,9 @@ public class TargetRateChart : JPanel() { } prevTimes = time.copyOf() prevRate = rate.copyOf() - val totalDuration = time.last() - val timeUnit = when { - totalDuration > MIN_TICKS_FOR_TIME_AXIS * TimeUnit.DAYS.asSeconds -> TimeUnit.DAYS - totalDuration > MIN_TICKS_FOR_TIME_AXIS * TimeUnit.HOURS.asSeconds -> TimeUnit.HOURS - totalDuration > MIN_TICKS_FOR_TIME_AXIS * TimeUnit.MINUTES.asSeconds -> TimeUnit.MINUTES - else -> TimeUnit.SECONDS - } - if (timeUnit != TimeUnit.SECONDS) { - val scale = 1.0 / timeUnit.asSeconds - for (i in time.indices) { - time[i] *= scale - } + val timeScale = TimeUnit.SECONDS.toMillis(1).toDouble() + for (i in time.indices) { + time[i] *= timeScale } val maxRate = rate.maxOrNull() ?: 0.0 val rateUnit = rateUnitFor(maxRate) @@ -120,16 +116,16 @@ public class TargetRateChart : JPanel() { } } removeAll() - add(createChart(time = time, rate = rate, timeUnit = timeUnit, rateUnit = rateUnit), BorderLayout.CENTER) + add(createChart(time = time, rate = rate, rateUnit = rateUnit), BorderLayout.CENTER) } - private fun createChart(time: DoubleArray, rate: DoubleArray, timeUnit: TimeUnit, rateUnit: TimeUnit): JComponent { + private fun createChart(time: DoubleArray, rate: DoubleArray, rateUnit: TimeUnit): JComponent { val data = mapOf( "time" to time, "rate" to rate ) val plot = letsPlot(data) + geomLine { x = "time"; y = "rate" } + - scaleXContinuous("Time, " + timeUnit.name.lowercase(), expand = listOf(0, 0)) + + scaleXTime("Time since test start", expand = listOf(0, 0)) + ggtitle("Target load rate per " + rateUnit.name.lowercase().removeSuffix("s")) + theme(axisTitleY = "blank") diff --git a/src/dist/src/dist/expected_release_jars.csv b/src/dist/src/dist/expected_release_jars.csv index 8ef431f9fe3..27a5d84f98a 100644 --- a/src/dist/src/dist/expected_release_jars.csv +++ b/src/dist/src/dist/expected_release_jars.csv @@ -2,7 +2,7 @@ 29371,annotations-23.0.0.jar 2387,apiguardian-api-1.1.0.jar 122004,asm-9.2.jar -517353,base-portable-jvm-2.2.0.jar +518460,base-portable-jvm-2.2.1.jar 485809,batik-anim-1.14.jar 424624,batik-awt-util-1.14.jar 703757,batik-bridge-1.14.jar @@ -92,8 +92,8 @@ 22357,kotlin-stdlib-jdk7-1.6.0.jar 16201,kotlin-stdlib-jdk8-1.6.0.jar 792176,kotlinx-html-jvm-0.7.3.jar -191102,lets-plot-batik-2.2.0.jar -3995999,lets-plot-common-2.2.0.jar +181223,lets-plot-batik-2.2.1.jar +4025480,lets-plot-common-2.2.1.jar 208235,log4j-1.2-api-2.17.0.jar 301776,log4j-api-2.17.0.jar 1789339,log4j-core-2.17.0.jar @@ -107,11 +107,11 @@ 65261,oro-2.0.8.jar 1307434,ph-commons-10.1.2.jar 506616,ph-css-6.3.4.jar -640740,plot-api-jvm-3.1.0.jar -882161,plot-base-portable-jvm-2.2.0.jar -847234,plot-builder-portable-jvm-2.2.0.jar -115295,plot-common-portable-jvm-2.2.0.jar -744679,plot-config-portable-jvm-2.2.0.jar +642167,plot-api-jvm-3.1.1.jar +891618,plot-base-portable-jvm-2.2.1.jar +845777,plot-builder-portable-jvm-2.2.1.jar +116030,plot-common-portable-jvm-2.2.1.jar +749095,plot-config-portable-jvm-2.2.1.jar 11369,reactive-streams-1.0.3.jar 1315838,rhino-1.7.13.jar 1242230,rsyntaxtextarea-3.1.3.jar @@ -123,7 +123,7 @@ 2539,swing-extensions-visual-padding-0.1.3.jar 734528,tika-core-1.27.jar 1397879,tika-parsers-1.27.jar -173926,vis-svg-portable-jvm-2.2.0.jar +174661,vis-svg-portable-jvm-2.2.1.jar 3154938,xalan-2.7.2.jar 1386502,xercesImpl-2.12.1.jar 220536,xml-apis-1.4.01.jar diff --git a/src/licenses/build.gradle.kts b/src/licenses/build.gradle.kts index 67115faa3fe..05d5a27a889 100644 --- a/src/licenses/build.gradle.kts +++ b/src/licenses/build.gradle.kts @@ -135,24 +135,6 @@ val gatherBinaryLicenses by tasks.registering(GatherLicenseTask::class) { expectedLicense = SpdxLicense.MIT } - for ( - a in listOf( - "lets-plot-kotlin-jvm", - "lets-plot-common", - "plot-config-portable-jvm", - "plot-builder-portable-jvm", - "plot-base-portable-jvm", - "plot-common-portable-jvm", - "vis-svg-portable-jvm", - "base-portable-jvm" - ) - ) { - overrideLicense("org.jetbrains.lets-plot:$a") { - expectedLicense = SpdxLicense.MIT - licenseFiles = "lets-plot" - } - } - overrideLicense("com.sun.mail:all:1.5.0-b01") { // Multiple licenses, specify explicitly expectedLicense = SimpleLicense("CDDL", uri("http://www.sun.com/cddl")) and SimpleLicense("GPLv2+CE", uri("https://glassfish.java.net/public/CDDL+GPL_1_1.html")) diff --git a/src/licenses/licenses/lets-plot/LICENSE b/src/licenses/licenses/lets-plot/LICENSE deleted file mode 100644 index 1bcc8b5941d..00000000000 --- a/src/licenses/licenses/lets-plot/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2019 JetBrains - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. From 1977e4c2dd0c49d037ade10e0946c36970da25eb Mon Sep 17 00:00:00 2001 From: Milamber Date: Thu, 23 Dec 2021 17:51:02 +0100 Subject: [PATCH 009/736] Update changes_history.xml for 5.4.2 and 5.4.3 --- xdocs/changes_history.xml | 272 ++++++++++++++++++++++++++++++-------- 1 file changed, 218 insertions(+), 54 deletions(-) diff --git a/xdocs/changes_history.xml b/xdocs/changes_history.xml index b0e24c9055d..8b8b4f40006 100644 --- a/xdocs/changes_history.xml +++ b/xdocs/changes_history.xml @@ -41,73 +41,257 @@ Current changes are detailed in Changes.

    Changes sections are chronologically ordered from top (most recent) to bottom (least recent)

    - + -

    Version 5.4.1

    +

    Version 5.4.3

    Summary

    +

    This version is a fix release against the vulnerability CVE-2021-45105: Apache Log4j2 versions 2.0-alpha1 through 2.16.0 (excluding 2.12.3) did not protect from uncontrolled recursion from self-referential lookups. This allows an attacker with control over Thread Context Map data to cause a denial of service when a crafted string is interpreted. +

    -New and Noteworthy - -UX improvements - - - -Incompatible changes +Non-functional changes
      -
    • Restart after LAF change has been reinstated, it had been removed in JMeter 5.3
    • +
    • Updated Apache log4j2 to 2.17.0 (from 2.16.0).
    - -Improvements + -

    HTTP Samplers and Test Script Recorder

    +Known problems and workarounds
      -
    +
  • The Once Only controller behaves correctly under a Thread Group or Loop Controller, +but otherwise its behaviour is not consistent (or clearly specified).
  • -

    Other samplers

    -
      -
    +
  • +The numbers that appear to the left of the green box are the number of active threads / total number of threads, +the total number of threads only applies to a locally run test, otherwise it will show 0 (see 55510). +
  • + +
  • +Note that under some windows systems you may have this WARNING: + +java.util.prefs.WindowsPreferences +WARNING: Could not open/create prefs root node Software\JavaSoft\Prefs at root 0 +x80000002. Windows RegCreateKeyEx(…) returned error code 5. + +The fix is to run JMeter as Administrator, it will create the registry key for you, then you can restart JMeter as a normal user and you won't have the warning anymore. +
  • + +
  • +You may encounter the following error: +java.security.cert.CertificateException: Certificates does not conform to algorithm constraints + if you run a HTTPS request on a web site with a SSL certificate (itself or one of SSL certificates in its chain of trust) with a signature + algorithm using MD2 (like md2WithRSAEncryption) or with a SSL certificate with a size lower than 1024 bits. +This error is related to increased security in Java 8+. +

    +To allow you to perform your HTTPS request, you can downgrade the security of your Java installation by editing +the Java jdk.certpath.disabledAlgorithms property. Remove the MD2 value or the constraint on size, depending on your case. +

    +This property is in this file: +JAVA_HOME/jre/lib/security/java.security +See 56357 for details. +
  • + +
  • +Under Mac OSX Aggregate Graph will show wrong values due to mirroring effect on numbers. +This is due to a known Java bug, see Bug JDK-8065373 +The fix is to use JDK8_u45 or later. +
  • + +
  • +View Results Tree may fail to display some HTML code under HTML renderer, see 54586. +This is due to a known Java bug which fails to parse "px" units in row/col attributes. +See Bug JDK-8031109 +The fix is to use JDK9 b65 or later. +
  • + +
  • +JTable selection with keyboard (SHIFTup/down) is totally unusable with Java 7 on Mac OSX. +This is due to a known Java bug JDK-8025126 +The fix is to use JDK 8 b132 or later. +
  • + +
  • +Since Java 11 the JavaScript implementation Nashorn has been deprecated. +Java will emit the following deprecation warnings, if you are using JavaScript based on Nashorn. + +Warning: Nashorn engine is planned to be removed from a future JDK release + +To silence these warnings, add -Dnashorn.args=--no-deprecation-warning to your Java arguments. +That can be achieved by setting the enviroment variable JVM_ARGS + +export JVM_ARGS="-Dnashorn.args=--no-deprecation-warning" + +
  • + +
  • +With Java 15 the JavaScript implementation Nashorn has been removed. To add back a JSR-223 compatible JavaScript engine you have two options: +
    +
    Use Mozilla Rhino
    +
    Copy rhino-engine-1.7.13.jar into $JMETER_HOME/lib/ext.
    +
    Use OpenJDK Nashorn
    +
    + The OpenJDK Nashorn implementation comes as a module. To use it, you will have to download it and add it to the module path. A hacky way to download the version 15.0 and its dependencies and set the module path is outlined below: + +mkdir lib/modules +pushd lib/modules +wget https://repo1.maven.org/maven2/org/openjdk/nashorn/nashorn-core/15.0/nashorn-core-15.0.jar +wget https://repo1.maven.org/maven2/org/ow2/asm/asm/9.0/asm-9.0.jar +wget https://repo1.maven.org/maven2/org/ow2/asm/asm-commons/9.0/asm-commons-9.0.jar +wget https://repo1.maven.org/maven2/org/ow2/asm/asm-util/9.0/asm-util-9.0.jar +wget https://repo1.maven.org/maven2/org/ow2/asm/asm-tree/9.0/asm-tree-9.0.jar +wget https://repo1.maven.org/maven2/org/ow2/asm/asm-analysis/9.0/asm-analysis-9.0.jar +popd +export JVM_ARGS="--modulepath $PWD/lib/modules" +./bin/jmeter + +
    +
    +
  • -

    Controllers

    -
    -

    Listeners

    + + +

    Version 5.4.2

    +

    +Summary +

    +

    This version is a fix release against the vulnerability CVE-2021-44228: Apache Log4j2 JNDI features do not protect against attacker controlled LDAP and other JNDI related endpoints. +

    -

    Timers, Assertions, Config, Pre- & Post-Processors

    +Non-functional changes
      +
    • Updated Apache log4j2 to 2.16.0 (from 2.13.3).
    -

    Functions

    + + +Known problems and workarounds
      +
    • The Once Only controller behaves correctly under a Thread Group or Loop Controller, +but otherwise its behaviour is not consistent (or clearly specified).
    • + +
    • +The numbers that appear to the left of the green box are the number of active threads / total number of threads, +the total number of threads only applies to a locally run test, otherwise it will show 0 (see 55510). +
    • + +
    • +Note that under some windows systems you may have this WARNING: + +java.util.prefs.WindowsPreferences +WARNING: Could not open/create prefs root node Software\JavaSoft\Prefs at root 0 +x80000002. Windows RegCreateKeyEx(…) returned error code 5. + +The fix is to run JMeter as Administrator, it will create the registry key for you, then you can restart JMeter as a normal user and you won't have the warning anymore. +
    • + +
    • +You may encounter the following error: +java.security.cert.CertificateException: Certificates does not conform to algorithm constraints + if you run a HTTPS request on a web site with a SSL certificate (itself or one of SSL certificates in its chain of trust) with a signature + algorithm using MD2 (like md2WithRSAEncryption) or with a SSL certificate with a size lower than 1024 bits. +This error is related to increased security in Java 8+. +

      +To allow you to perform your HTTPS request, you can downgrade the security of your Java installation by editing +the Java jdk.certpath.disabledAlgorithms property. Remove the MD2 value or the constraint on size, depending on your case. +

      +This property is in this file: +JAVA_HOME/jre/lib/security/java.security +See 56357 for details. +
    • + +
    • +Under Mac OSX Aggregate Graph will show wrong values due to mirroring effect on numbers. +This is due to a known Java bug, see Bug JDK-8065373 +The fix is to use JDK8_u45 or later. +
    • + +
    • +View Results Tree may fail to display some HTML code under HTML renderer, see 54586. +This is due to a known Java bug which fails to parse "px" units in row/col attributes. +See Bug JDK-8031109 +The fix is to use JDK9 b65 or later. +
    • + +
    • +JTable selection with keyboard (SHIFTup/down) is totally unusable with Java 7 on Mac OSX. +This is due to a known Java bug JDK-8025126 +The fix is to use JDK 8 b132 or later. +
    • + +
    • +Since Java 11 the JavaScript implementation Nashorn has been deprecated. +Java will emit the following deprecation warnings, if you are using JavaScript based on Nashorn. + +Warning: Nashorn engine is planned to be removed from a future JDK release + +To silence these warnings, add -Dnashorn.args=--no-deprecation-warning to your Java arguments. +That can be achieved by setting the enviroment variable JVM_ARGS + +export JVM_ARGS="-Dnashorn.args=--no-deprecation-warning" + +
    • + +
    • +With Java 15 the JavaScript implementation Nashorn has been removed. To add back a JSR-223 compatible JavaScript engine you have two options: +
      +
      Use Mozilla Rhino
      +
      Copy rhino-engine-1.7.13.jar into $JMETER_HOME/lib/ext.
      +
      Use OpenJDK Nashorn
      +
      + The OpenJDK Nashorn implementation comes as a module. To use it, you will have to download it and add it to the module path. A hacky way to download the version 15.0 and its dependencies and set the module path is outlined below: + +mkdir lib/modules +pushd lib/modules +wget https://repo1.maven.org/maven2/org/openjdk/nashorn/nashorn-core/15.0/nashorn-core-15.0.jar +wget https://repo1.maven.org/maven2/org/ow2/asm/asm/9.0/asm-9.0.jar +wget https://repo1.maven.org/maven2/org/ow2/asm/asm-commons/9.0/asm-commons-9.0.jar +wget https://repo1.maven.org/maven2/org/ow2/asm/asm-util/9.0/asm-util-9.0.jar +wget https://repo1.maven.org/maven2/org/ow2/asm/asm-tree/9.0/asm-tree-9.0.jar +wget https://repo1.maven.org/maven2/org/ow2/asm/asm-analysis/9.0/asm-analysis-9.0.jar +popd +export JVM_ARGS="--modulepath $PWD/lib/modules" +./bin/jmeter + +
      +
      +
    • +
    -

    I18N

    + + +

    Version 5.4.1

    +

    +Summary +

    -

    Report / Dashboard

    +Incompatible changes
      +
    • Restart after LAF change has been reinstated, it had been removed in JMeter 5.3
    + + +Improvements

    General

      @@ -153,32 +337,12 @@ Summary the case of waiting for an EOM.
    -

    Controllers

    -
      -
    -

    Listeners

    • 64821When importing XML formatted jtl files, sub samplers will get renamed
    • 65052XPath2 Tester and JSON JMESPath Tester are missing in view.results.tree.renderers_order property
    -

    Timers, Assertions, Config, Pre- & Post-Processors

    -
      -
    - -

    Functions

    -
      -
    - -

    I18N

    -
      -
    - -

    Report / Dashboard

    -
      -
    -

    Documentation

    • 64960Change scheduler reference in Thread Group documentation. Contributed by Ori Marko
    • From 52f4945766287806d6ab447214f64e4a95e61803 Mon Sep 17 00:00:00 2001 From: Vladimir Sitnikov Date: Mon, 27 Dec 2021 20:37:50 +0300 Subject: [PATCH 010/736] Update changelog for JMeter 5.5 --- xdocs/changes.xml | 53 +++++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/xdocs/changes.xml b/xdocs/changes.xml index af8db71c33f..22bd0e92559 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -59,26 +59,41 @@ Summary
    New and Noteworthy -
      -
    • Support building and running JMeter with Java 17
    • -
    • Open Model Thread Group: load generator with programmable profile
    • -
    - -UX improvements +

    Kotlin language is now used in some core classes and tests (e.g. Open Model Thread Group). + JMeter is compiled with apiTarget=1.5, and it ships with kotlin-stdlib 1.6. +

    + +

    lets-plot-kotlin charting library is added, + so it will be easier to refine and create new charts in UI in the future. +

    - +Improvements -Incompatible changes +

    Thread Groups

    - - -Improvements

    HTTP Samplers and Test Script Recorder

      @@ -118,14 +133,6 @@ Summary not their string representations.
    -

    Functions

    -
      -
    - -

    I18N

    -
      -
    -

    Report / Dashboard

    • 65353Make the estimator used for calculating percentiles on the dashboard configurable
    • From 879a2b935c0c8e7e087d96f141c28e915504c537 Mon Sep 17 00:00:00 2001 From: Woonsan Ko Date: Mon, 27 Dec 2021 21:54:31 +0300 Subject: [PATCH 011/736] 65108: Support JMeter variables in GraphQL HTTP Request Previously the variables were parsed as JSON, and now the variable contents is added as a raw part (no parsing) of the JSON. fixes #660 --- .../http/config/GraphQLRequestParams.java | 9 +++ .../http/util/GraphQLRequestParamUtils.java | 64 ++++++++----------- .../util/TestGraphQLRequestParamUtils.java | 53 +++++++++------ xdocs/changes.xml | 1 + 4 files changed, 68 insertions(+), 59 deletions(-) diff --git a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/config/GraphQLRequestParams.java b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/config/GraphQLRequestParams.java index 6edabbf4c8c..ded3b8d8594 100644 --- a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/config/GraphQLRequestParams.java +++ b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/config/GraphQLRequestParams.java @@ -64,4 +64,13 @@ public String getVariables() { public void setVariables(String variables) { this.variables = variables; } + + @Override + public String toString() { + return "GraphQLRequestParams{" + + "operationName='" + operationName + '\'' + + ", query='" + query + '\'' + + ", variables='" + variables + '\'' + + '}'; + } } diff --git a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/util/GraphQLRequestParamUtils.java b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/util/GraphQLRequestParamUtils.java index 0d3f7422079..00673bf4ab5 100644 --- a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/util/GraphQLRequestParamUtils.java +++ b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/util/GraphQLRequestParamUtils.java @@ -20,6 +20,7 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStreamReader; +import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.util.regex.Pattern; @@ -31,13 +32,12 @@ import org.apache.jmeter.config.Arguments; import org.apache.jmeter.protocol.http.config.GraphQLRequestParams; import org.apache.jmeter.testelement.property.JMeterProperty; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.JsonNodeType; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -46,16 +46,16 @@ */ public final class GraphQLRequestParamUtils { - private static final String VARIABLES_FIELD = "variables"; + public static final String VARIABLES_FIELD = "variables"; - private static final String OPERATION_NAME_FIELD = "operationName"; + public static final String OPERATION_NAME_FIELD = "operationName"; - private static final String QUERY_FIELD = "query"; - - private static Logger log = LoggerFactory.getLogger(GraphQLRequestParamUtils.class); + public static final String QUERY_FIELD = "query"; private static final Pattern WHITESPACES_PATTERN = Pattern.compile("\\p{Space}+"); + private static final JsonFactory jsonFactory = new JsonFactory(); + private GraphQLRequestParamUtils() { } @@ -79,28 +79,26 @@ public static boolean isGraphQLContentType(final String contentType) { * @throws RuntimeException if JSON serialization fails for some reason due to any runtime environment issues */ public static String toPostBodyString(final GraphQLRequestParams params) { - final ObjectMapper mapper = new ObjectMapper(); - final ObjectNode postBodyJson = mapper.createObjectNode(); - postBodyJson.set(OPERATION_NAME_FIELD, - JsonNodeFactory.instance.textNode(StringUtils.trimToNull(params.getOperationName()))); - - if (StringUtils.isNotBlank(params.getVariables())) { - try { - final ObjectNode variablesJson = mapper.readValue(params.getVariables(), ObjectNode.class); - postBodyJson.set(VARIABLES_FIELD, variablesJson); - } catch (JsonProcessingException e) { - log.error("Ignoring the GraphQL query variables content due to the syntax error: {}", - e.getLocalizedMessage()); + final StringWriter writer = new StringWriter(); + + try (JsonGenerator gen = jsonFactory.createGenerator(writer)) { + gen.writeStartObject(); + + gen.writeStringField(OPERATION_NAME_FIELD, StringUtils.trimToNull(params.getOperationName())); + + if (StringUtils.isNotBlank(params.getVariables())) { + gen.writeFieldName(VARIABLES_FIELD); + gen.writeRawValue(StringUtils.trim(params.getVariables())); } - } - postBodyJson.set(QUERY_FIELD, JsonNodeFactory.instance.textNode(StringUtils.trim(params.getQuery()))); + gen.writeStringField(QUERY_FIELD, StringUtils.trim(params.getQuery())); - try { - return mapper.writeValueAsString(postBodyJson); - } catch (JsonProcessingException e) { - throw new RuntimeException("Cannot serialize JSON for POST body string", e); + gen.writeEndObject(); + } catch (IOException e) { + throw new IllegalStateException("Error while writing graphql post body " + params, e); } + + return writer.toString(); } /** @@ -118,17 +116,7 @@ public static String queryToGetParamValue(final String query) { * @return an HTTP GET request parameter value converted from the GraphQL Variables JSON input string */ public static String variablesToGetParamValue(final String variables) { - final ObjectMapper mapper = new ObjectMapper(); - - try { - final ObjectNode variablesJson = mapper.readValue(variables, ObjectNode.class); - return mapper.writeValueAsString(variablesJson); - } catch (JsonProcessingException e) { - log.error("Ignoring the GraphQL query variables content due to the syntax error: {}", - e.getLocalizedMessage()); - } - - return null; + return StringUtils.trimToNull(variables); } /** @@ -151,7 +139,7 @@ public static GraphQLRequestParams toGraphQLRequestParams(byte[] postData, final try (InputStreamReader reader = new InputStreamReader(new ByteArrayInputStream(postData), encoding)) { data = mapper.readValue(reader, ObjectNode.class); } catch (IOException e) { - throw new IllegalArgumentException("Invalid json data: " + e.getLocalizedMessage()); + throw new IllegalArgumentException("Invalid json data: " + e.getLocalizedMessage(), e); } String operationName = null; diff --git a/src/protocol/http/src/test/java/org/apache/jmeter/protocol/http/util/TestGraphQLRequestParamUtils.java b/src/protocol/http/src/test/java/org/apache/jmeter/protocol/http/util/TestGraphQLRequestParamUtils.java index 4b4d0ea782b..be7b075eed1 100644 --- a/src/protocol/http/src/test/java/org/apache/jmeter/protocol/http/util/TestGraphQLRequestParamUtils.java +++ b/src/protocol/http/src/test/java/org/apache/jmeter/protocol/http/util/TestGraphQLRequestParamUtils.java @@ -22,8 +22,8 @@ import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.params.provider.Arguments.arguments; -import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; import java.util.stream.Stream; @@ -36,7 +36,8 @@ import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.ValueSource; -import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; class TestGraphQLRequestParamUtils { @@ -72,6 +73,8 @@ class TestGraphQLRequestParamUtils { + "\"query\":\"" + StringUtils.replace(QUERY.trim(), "\n", "\\n") + "\"" + "}"; + private static final ObjectMapper objectMapper = new ObjectMapper(); + private GraphQLRequestParams params; @BeforeEach @@ -81,7 +84,7 @@ void setUp() { @ParameterizedTest @ValueSource(strings = { "application/json", "application/json;charset=utf-8", "application/json; charset=utf-8" }) - void testIsGraphQLContentType(String contentType) throws Exception { + void testIsGraphQLContentType(String contentType) { assertTrue(GraphQLRequestParamUtils.isGraphQLContentType(contentType)); } @@ -97,20 +100,32 @@ void testInvalidGraphQLContentType(String contentType) { assertFalse(GraphQLRequestParamUtils.isGraphQLContentType(contentType)); } - @Test - void testToPostBodyString() throws Exception { - assertEquals(EXPECTED_POST_BODY, GraphQLRequestParamUtils.toPostBodyString(params)); + static Stream postBodyFieldNameAndJsonNodes() throws Exception { + final JsonNode expectedPostBodyJson = objectMapper.readTree(EXPECTED_POST_BODY); + final JsonNode actualPostBodyJson = objectMapper.readTree( + GraphQLRequestParamUtils.toPostBodyString(new GraphQLRequestParams(OPERATION_NAME, QUERY, VARIABLES))); + return Stream.of( + arguments(GraphQLRequestParamUtils.OPERATION_NAME_FIELD, expectedPostBodyJson, actualPostBodyJson), + arguments(GraphQLRequestParamUtils.VARIABLES_FIELD, expectedPostBodyJson, actualPostBodyJson), + arguments(GraphQLRequestParamUtils.QUERY_FIELD, expectedPostBodyJson, actualPostBodyJson)); + } + + @ParameterizedTest + @MethodSource("postBodyFieldNameAndJsonNodes") + void testFieldInJsonFromToPostBodyString(String fieldName, JsonNode expectedNode, JsonNode actualNode) { + assertEquals(expectedNode.get(fieldName), actualNode.get(fieldName), + "The value of the '" + fieldName + "' field doesn't match in " + actualNode); } @Test - void testQueryToGetParamValue() throws Exception { + void testQueryToGetParamValue() { assertEquals(EXPECTED_QUERY_GET_PARAM_VALUE, GraphQLRequestParamUtils.queryToGetParamValue(params.getQuery())); } @Test void testVariablesToGetParamValue() throws Exception { - assertEquals(EXPECTED_VARIABLES_GET_PARAM_VALUE, - GraphQLRequestParamUtils.variablesToGetParamValue(params.getVariables())); + assertEquals(objectMapper.readTree(EXPECTED_VARIABLES_GET_PARAM_VALUE), + objectMapper.readTree(GraphQLRequestParamUtils.variablesToGetParamValue(params.getVariables()))); } @Test @@ -132,24 +147,20 @@ void testToGraphQLRequestParamsWithPostData() throws Exception { @ParameterizedTest @ValueSource(strings = { "", "{}"}) - void testInvalidJsonData(String postDataAsString) throws JsonProcessingException, UnsupportedEncodingException { + void testInvalidJsonData(String postDataAsString) { byte[] postData = postDataAsString.getBytes(StandardCharsets.UTF_8); assertThrows(IllegalArgumentException.class, - () -> { - GraphQLRequestParamUtils.toGraphQLRequestParams(postData, null); - }); + () -> GraphQLRequestParamUtils.toGraphQLRequestParams(postData, null)); } @ParameterizedTest @ValueSource(strings = { "{\"query\":\"select * from emp\"}", "{\"operationName\":{\"id\":123},\"query\":\"query { droid { id }}\"}", "{\"variables\":\"r2d2\",\"query\":\"query { droid { id }}\"}" }) - void testInvalidGraphQueryParam(String postDataAsString) - throws JsonProcessingException, UnsupportedEncodingException { + void testInvalidGraphQueryParam(String postDataAsString) { byte[] postData = postDataAsString.getBytes(StandardCharsets.UTF_8); - assertThrows(IllegalArgumentException.class, () -> { - GraphQLRequestParamUtils.toGraphQLRequestParams(postData, null); - }); + assertThrows(IllegalArgumentException.class, + () -> GraphQLRequestParamUtils.toGraphQLRequestParams(postData, null)); } @Test @@ -186,14 +197,14 @@ void testToGraphQLRequestParamsWithHttpArguments() throws Exception { } @Test - void testMissingParams() throws UnsupportedEncodingException { + void testMissingParams() { Arguments args = new Arguments(); assertThrows(IllegalArgumentException.class, () -> GraphQLRequestParamUtils.toGraphQLRequestParams(args, null)); } @Test - void testInvalidQueryParam() throws UnsupportedEncodingException { + void testInvalidQueryParam() { Arguments args = new Arguments(); args.addArgument(new HTTPArgument("query", "select * from emp", "=", false)); assertThrows(IllegalArgumentException.class, @@ -201,7 +212,7 @@ void testInvalidQueryParam() throws UnsupportedEncodingException { } @Test - void testInvalidQueryParamVariables() throws UnsupportedEncodingException { + void testInvalidQueryParamVariables() { Arguments args = new Arguments(); args.addArgument(new HTTPArgument("query", "query { droid { id }}", "=", false)); args.addArgument(new HTTPArgument("variables", "r2d2", "=", false)); diff --git a/xdocs/changes.xml b/xdocs/changes.xml index 22bd0e92559..de4a9ca6b4a 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -206,6 +206,7 @@ however, the profile can't be updated while the test is running. header in HC4 sampler.
    • 65363NullPointerException in HTTPHC4Impl$ManagedCredentialsProvider.getAuthorizationForAuthScope when 401 response from remote and httpclient4.auth.preemptive=false
    • 65692HTTP(s) Test Script Recorder: Enable setting enabled cipher suite and enabled protocols on SSLContext/ Align ssl properties between Java and HC4 impl
    • +
    • 65108Support JMeter variables in GraphQL HTTP Request

    Other Samplers

    From 3786a5e61340a6eccb3594db03d919e5c94f7af8 Mon Sep 17 00:00:00 2001 From: Vladimir Sitnikov Date: Tue, 28 Dec 2021 12:42:12 +0300 Subject: [PATCH 012/736] Simplify :src:dist:clean configuration, ensure /lib/junit/test.jar is removed on clean In practice, clean should not be required, however, making it a bit more precise makes sense anyway. See https://bz.apache.org/bugzilla/show_bug.cgi?id=63914 fixes #659 --- src/dist/build.gradle.kts | 15 +++++++-------- xdocs/changes.xml | 1 + 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/dist/build.gradle.kts b/src/dist/build.gradle.kts index d414fb3ac88..9fc84783deb 100644 --- a/src/dist/build.gradle.kts +++ b/src/dist/build.gradle.kts @@ -92,14 +92,13 @@ dependencies { buildDocs("org.jdom:jdom") } -tasks.named(BasePlugin.CLEAN_TASK_NAME).configure { - doLast { - // createDist can't yet remove outdated jars (e.g. when dependency is updated to a newer version) - // so we enhance "clean" task to kill the jars - delete(fileTree("$rootDir/bin") { include("ApacheJMeter.jar") }) - delete(fileTree("$rootDir/lib") { include("*.jar") }) - delete(fileTree("$rootDir/lib/ext") { include("ApacheJMeter*.jar") }) - } +tasks.clean { + // copyLibs uses Sync task, so it can't predict all the possible output files (e.g. from previous executions) + // So we register patterns to remove explicitly + delete(fileTree("$rootDir/bin") { include("ApacheJMeter.jar") }) + delete(fileTree("$rootDir/lib") { include("*.jar") }) + delete(fileTree("$rootDir/lib/ext") { include("ApacheJMeter*.jar") }) + delete(fileTree("$rootDir/lib/junit") { include("test.jar") }) } // Libs are populated dynamically since we can't get the full set of dependencies diff --git a/xdocs/changes.xml b/xdocs/changes.xml index de4a9ca6b4a..a3a9cfb2a7c 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -265,6 +265,7 @@ however, the profile can't be updated while the test is running.
  • 65300IllegalAccessError when opening file dialog with Java 16
  • 65336Blank labels when different elements had the same name
  • 65522Restart doesn't work, when parameters contain spaces
  • +
  • 63914Simplify :src:dist:clean configuration, ensure /lib/junit/test.jar is removed on clean
  • From 155485c72b74ca8bc225aa19706676f7e33f5272 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20Sp=C3=A5ngdal?= Date: Wed, 14 Apr 2021 19:05:42 +0200 Subject: [PATCH 013/736] Allow setters in ConstantThroughputTimer to updating the values during the run time fixes #662 --- .../timers/ConstantThroughputTimer.java | 35 +++++++++++-------- .../ConstantThroughputTimerBeanInfo.java | 8 ++--- xdocs/changes.xml | 2 ++ 3 files changed, 26 insertions(+), 19 deletions(-) diff --git a/src/components/src/main/java/org/apache/jmeter/timers/ConstantThroughputTimer.java b/src/components/src/main/java/org/apache/jmeter/timers/ConstantThroughputTimer.java index a4dafcfe946..7b745b9c0fe 100644 --- a/src/components/src/main/java/org/apache/jmeter/timers/ConstantThroughputTimer.java +++ b/src/components/src/main/java/org/apache/jmeter/timers/ConstantThroughputTimer.java @@ -30,6 +30,8 @@ import org.apache.jmeter.testbeans.gui.GenericTestBeanCustomizer; import org.apache.jmeter.testelement.AbstractTestElement; import org.apache.jmeter.testelement.TestStateListener; +import org.apache.jmeter.testelement.property.DoubleProperty; +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.AbstractThreadGroup; @@ -60,6 +62,12 @@ private static class ThroughputInfo{ private static final double MILLISEC_PER_MIN = 60000.0; + private static final Mode DEFAULT_CALC_MODE = Mode.ThisThreadOnly; + + // TODO: most props use class simpleName as prefix but that would break backward compatiblity here + public static final String THROUGHPUT = "throughput"; + public static final String CALC_MODE = "calcMode"; + /** * This enum defines the calculation modes used by the ConstantThroughputTimer. */ @@ -72,6 +80,8 @@ public enum Mode { ; private final String propertyName; // The property name to be used to look up the display string + // Enum#values() clones the array, and we don't want to pay that cost as we know we don't modify the array + private static final Mode[] CACHED_VALUES = values(); Mode(String name) { this.propertyName = name; @@ -89,13 +99,6 @@ public String toString() { */ private long previousTime = 0; - private Mode mode = Mode.ThisThreadOnly; - - /** - * Desired throughput, in samples per minute. - */ - private double throughput; - //For calculating throughput across all threads private static final ThroughputInfo allThreadsInfo = new ThroughputInfo(); @@ -117,7 +120,7 @@ public ConstantThroughputTimer() { * Desired sampling rate, in samples per minute. */ public void setThroughput(double throughput) { - this.throughput = throughput; + setProperty(new DoubleProperty(THROUGHPUT, throughput)); } /** @@ -126,15 +129,16 @@ public void setThroughput(double throughput) { * @return the rate at which samples should occur, in samples per minute. */ public double getThroughput() { - return throughput; + return getPropertyAsDouble(THROUGHPUT); } public int getCalcMode() { - return mode.ordinal(); + return getPropertyAsInt(CALC_MODE, DEFAULT_CALC_MODE.ordinal()); } public void setCalcMode(int mode) { - this.mode = Mode.values()[mode]; + Mode resolved = Mode.CACHED_VALUES[mode]; + setProperty(new IntegerProperty(CALC_MODE, resolved.ordinal())); } /** @@ -178,7 +182,7 @@ private long calculateDelay() { long delay; // N.B. we fetch the throughput each time, as it may vary during a test double msPerRequest = MILLISEC_PER_MIN / getThroughput(); - switch (mode) { + switch (getMode()) { case AllActiveThreads: // Total number of threads delay = Math.round(JMeterContextService.getNumberOfThreads() * msPerRequest); break; @@ -279,7 +283,7 @@ public void setProperty(JMeterProperty property) { try { final BeanInfo beanInfo = Introspector.getBeanInfo(this.getClass()); final ResourceBundle rb = (ResourceBundle) beanInfo.getBeanDescriptor().getValue(GenericTestBeanCustomizer.RESOURCE_BUNDLE); - for(Enum e : Mode.values()) { + for(Enum e : Mode.CACHED_VALUES) { final String propName = e.toString(); if (objectValue.equals(rb.getObject(propName))) { final int tmpMode = e.ordinal(); @@ -324,11 +328,12 @@ public void testEnded(String host) { // For access from test code Mode getMode() { - return mode; + int mode = getCalcMode(); + return Mode.CACHED_VALUES[mode]; } // For access from test code void setMode(Mode newMode) { - mode = newMode; + setCalcMode(newMode.ordinal()); } } diff --git a/src/components/src/main/java/org/apache/jmeter/timers/ConstantThroughputTimerBeanInfo.java b/src/components/src/main/java/org/apache/jmeter/timers/ConstantThroughputTimerBeanInfo.java index 0d28dffb438..63db360d1f2 100644 --- a/src/components/src/main/java/org/apache/jmeter/timers/ConstantThroughputTimerBeanInfo.java +++ b/src/components/src/main/java/org/apache/jmeter/timers/ConstantThroughputTimerBeanInfo.java @@ -30,14 +30,14 @@ public ConstantThroughputTimerBeanInfo() { super(ConstantThroughputTimer.class); createPropertyGroup("delay", //$NON-NLS-1$ - new String[] { "throughput", //$NON-NLS-1$ - "calcMode" }); //$NON-NLS-1$ + new String[] { ConstantThroughputTimer.THROUGHPUT, //$NON-NLS-1$ + ConstantThroughputTimer.CALC_MODE }); //$NON-NLS-1$ - PropertyDescriptor p = property("throughput"); //$NON-NLS-1$ + PropertyDescriptor p = property(ConstantThroughputTimer.THROUGHPUT); //$NON-NLS-1$ p.setValue(NOT_UNDEFINED, Boolean.TRUE); p.setValue(DEFAULT, 0.0); - p = property("calcMode", ConstantThroughputTimer.Mode.class); //$NON-NLS-1$ + p = property(ConstantThroughputTimer.CALC_MODE, ConstantThroughputTimer.Mode.class); //$NON-NLS-1$ p.setValue(DEFAULT, ConstantThroughputTimer.Mode.ThisThreadOnly.ordinal()); p.setValue(NOT_UNDEFINED, Boolean.TRUE); // must be defined } diff --git a/xdocs/changes.xml b/xdocs/changes.xml index a3a9cfb2a7c..d29ffc259a1 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -232,6 +232,7 @@ however, the profile can't be updated while the test is running.
  • 65269JSON Extractor and JSON JMESPath Extractor ignore sub-samples
  • 65352Warning logged when Boundary Extractor doesn't find any match
  • 65681Use default values for null values when extracting with JSONPostProcessor
  • +
  • Allow setters in ConstantThroughputTimer to updating the values during the run time
  • Functions

    @@ -286,6 +287,7 @@ however, the profile can't be updated while the test is running.
  • Rithvik Patibandla (rithvikp98 at gmail.com)
  • Mariusz (mawasak at gmail.com)
  • peter.wong@csexperts.com
  • +
  • Magnus Spångdal (magnus.spangdal as avanza.se)
  • We also thank bug reporters who helped us improve JMeter.

      From eb851f3f1f1ba0d86fe90ab8fb0e1ef5ffc6940a Mon Sep 17 00:00:00 2001 From: Vladimir Sitnikov Date: Tue, 28 Dec 2021 13:18:10 +0300 Subject: [PATCH 014/736] Update "thanks" section for 5.5 --- xdocs/changes.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xdocs/changes.xml b/xdocs/changes.xml index d29ffc259a1..e48dfb09190 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -287,6 +287,8 @@ however, the profile can't be updated while the test is running.
    • Rithvik Patibandla (rithvikp98 at gmail.com)
    • Mariusz (mawasak at gmail.com)
    • peter.wong@csexperts.com
    • +
    • Woonsan Ko (woonsan.ko at bloomreach.com)
    • +
    • Chromico Rek (atech5122 at gmail.com)
    • Magnus Spångdal (magnus.spangdal as avanza.se)

    We also thank bug reporters who helped us improve JMeter.

    From 08e350d8e58044655c2f6f58444e8b60798af93d Mon Sep 17 00:00:00 2001 From: Piotr Smietana Date: Wed, 29 Dec 2021 16:58:15 +0100 Subject: [PATCH 015/736] Update log4j2 to 2.17.1 (#685) Co-authored-by: smiep --- gradle.properties | 2 +- src/dist/src/dist/expected_release_jars.csv | 8 ++++---- xdocs/changes.xml | 5 +++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/gradle.properties b/gradle.properties index 154d602a448..df7baa176cc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -115,7 +115,7 @@ junit4.version=4.13.2 junit5.version=5.8.1 lets-plot-batik.version=2.2.1 lets-plot-kotlin-jvm.version=3.1.1 -log4j.version=2.17.0 +log4j.version=2.17.1 mail.version=1.5.0-b01 miglayout.version=5.3 mina-core.version=2.0.19 diff --git a/src/dist/src/dist/expected_release_jars.csv b/src/dist/src/dist/expected_release_jars.csv index 27a5d84f98a..3cd09108c19 100644 --- a/src/dist/src/dist/expected_release_jars.csv +++ b/src/dist/src/dist/expected_release_jars.csv @@ -94,10 +94,10 @@ 792176,kotlinx-html-jvm-0.7.3.jar 181223,lets-plot-batik-2.2.1.jar 4025480,lets-plot-common-2.2.1.jar -208235,log4j-1.2-api-2.17.0.jar -301776,log4j-api-2.17.0.jar -1789339,log4j-core-2.17.0.jar -24252,log4j-slf4j-impl-2.17.0.jar +208006,log4j-1.2-api-2.17.1.jar +301872,log4j-api-2.17.1.jar +1790452,log4j-core-2.17.1.jar +24279,log4j-slf4j-impl-2.17.1.jar 519087,mail-1.5.0-b01.jar 106949,miglayout-core-5.3.jar 22576,miglayout-swing-5.3.jar diff --git a/xdocs/changes.xml b/xdocs/changes.xml index e48dfb09190..33606f2ab5a 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -61,7 +61,7 @@ Summary New and Noteworthy

    JMeter now supports Java 17

    -

    JMeter 5.5 ships with log4j2 2.17

    +

    JMeter 5.5 ships with log4j2 2.17.1

    New component: Open Model Thread Group allows creating load profiles with variable load.

    @@ -175,7 +175,7 @@ however, the profile can't be updated while the test is running.
  • Updated json-path to 2.6.0 (from 2.4.0).
  • Updated jsoup to 1.14.1 (from 1.13.1).
  • Updated JUnit to 4.13.2 and 5.8.1 (from 4.13.1 and 5.7.0).
  • -
  • Updated Apache log4j2 to 2.17.0 (from 2.13.3).
  • +
  • Updated Apache log4j2 to 2.17.1 (from 2.13.3).
  • Updated Miglayout to 5.3 (from 5.2).
  • Updated Neo4j Java driver to 4.3.3 (from 4.2.0).
  • Updated Objenesis to 3.2 (from 2.6).
  • @@ -290,6 +290,7 @@ however, the profile can't be updated while the test is running.
  • Woonsan Ko (woonsan.ko at bloomreach.com)
  • Chromico Rek (atech5122 at gmail.com)
  • Magnus Spångdal (magnus.spangdal as avanza.se)
  • +
  • Piotr Smietana (piotrsmietana1998 at gmail.com)
  • We also thank bug reporters who helped us improve JMeter.

      From 1d8f1e1665ce3aefd091c1d37648674af599b572 Mon Sep 17 00:00:00 2001 From: Vladimir Sitnikov Date: Mon, 3 Jan 2022 17:34:15 +0300 Subject: [PATCH 016/736] Gradle 7.5 compatibility: add checksum for gradle-enterprise-gradle-plugin-3.8.jar --- settings.gradle.kts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/settings.gradle.kts b/settings.gradle.kts index 4fd91363720..e27df11c67c 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -149,6 +149,8 @@ val expectedSha512 = mapOf( to "gradle-enterprise-gradle-plugin-3.7.jar", "7AC5F1C070A8C0A2BD096D96E896EB147966C39E0746120ABA5E107DDBDED441FF71F31F167475CD36EE082D8430D1FB98C51D29C6B91D147CC64DCE59C66D49" to "gradle-enterprise-gradle-plugin-3.7.2.jar", + "24A1722CB574BA3126C3C6EBEB3D4A39D2A86ECCEDD378BA96A5508626D1AEAC7BB5FFBC189929E16900B94C1D016AFA83A462DCB2BB03F634FCA9C7FDE9EBA5" + to "gradle-enterprise-gradle-plugin-3.8.jar", "FA305ACAAF45D005F5032D93C4F37CD097936C802943885A8F2B9EC27DA24F148DB41748655347C9A707C62614087432B3D32CC1B297381D45F3D8063BFFFA6D" to "bcpg-jdk15on-1.62.jar", "2BA6A5DEC9C8DAC2EB427A65815EB3A9ADAF4D42D476B136F37CD57E6D013BF4E9140394ABEEA81E42FBDB8FC59228C7B85C549ED294123BF898A7D048B3BD95" From dc91e8bcf6bcb6ec6572672b12ec9fbb389c7159 Mon Sep 17 00:00:00 2001 From: Sampath Kumar Krishnasamy Date: Tue, 4 Jan 2022 09:20:25 +0000 Subject: [PATCH 017/736] Deleted the redundant log variable --- .../protocol/http/gui/action/ParseCurlCommandAction.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/gui/action/ParseCurlCommandAction.java b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/gui/action/ParseCurlCommandAction.java index 7e42bc03dd9..cc3c67433cb 100644 --- a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/gui/action/ParseCurlCommandAction.java +++ b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/gui/action/ParseCurlCommandAction.java @@ -123,7 +123,6 @@ public class ParseCurlCommandAction extends AbstractAction implements MenuCreato public static final String IMPORT_CURL = "import_curl"; private static final String CREATE_REQUEST = "CREATE_REQUEST"; private static final String CERT = "cert"; - private Logger log = LoggerFactory.getLogger(getClass()); /** A panel allowing results to be saved. */ private FilePanel filePanel = null; static { @@ -550,11 +549,11 @@ private void setFormData(Request request, HTTPSamplerProxy httpSampler) { if (contentFile.canRead()) { contentType = tika.detect(contentFile); } else { - log.info("Can not read file {}, so guessing contentType by extension.", formValue); + LOGGER.info("Can not read file {}, so guessing contentType by extension.", formValue); contentType = tika.detect(formValue); } } catch (IOException e) { - log.info( + LOGGER.info( "Could not detect contentType for file {} by content, so falling back to detection by filename", formValue); contentType = tika.detect(formValue); From 374cda59bb17af9f2ead0344132c1c32ef63d0da Mon Sep 17 00:00:00 2001 From: Sampath Kumar Krishnasamy Date: Tue, 4 Jan 2022 09:24:03 +0000 Subject: [PATCH 018/736] Remove unnecessary throws exception --- .../apache/jmeter/engine/DistributedRunnerTest.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/core/src/test/java/org/apache/jmeter/engine/DistributedRunnerTest.java b/src/core/src/test/java/org/apache/jmeter/engine/DistributedRunnerTest.java index 0241287a3bc..6aa30b8faf8 100644 --- a/src/core/src/test/java/org/apache/jmeter/engine/DistributedRunnerTest.java +++ b/src/core/src/test/java/org/apache/jmeter/engine/DistributedRunnerTest.java @@ -53,7 +53,7 @@ public static void createJmeterEnv() { } @Test - public void testSuccess() throws Exception { + public void testSuccess() { createJmeterEnv(); JMeterUtils.setProperty(DistributedRunner.RETRIES_NUMBER, "1"); JMeterUtils.setProperty(DistributedRunner.CONTINUE_ON_FAIL, "false"); @@ -69,7 +69,7 @@ public void testSuccess() throws Exception { } @Test - public void testFailure1() throws Exception { + public void testFailure1() { createJmeterEnv(); JMeterUtils.setProperty(DistributedRunner.RETRIES_NUMBER, "2"); JMeterUtils.setProperty(DistributedRunner.RETRIES_DELAY, "1"); @@ -101,7 +101,7 @@ private void initRunner(DistributedRunnerEmul runner, List hosts) { } @Test - public void testFailure2() throws Exception { + public void testFailure2() { createJmeterEnv(); JMeterUtils.setProperty(DistributedRunner.RETRIES_NUMBER, "1"); JMeterUtils.setProperty(DistributedRunner.RETRIES_DELAY, "1"); @@ -112,7 +112,7 @@ public void testFailure2() throws Exception { } @Test - public void testFailure3() throws Exception { + public void testFailure3() { createJmeterEnv(); JMeterUtils.setProperty(DistributedRunner.RETRIES_NUMBER, "1"); JMeterUtils.setProperty(DistributedRunner.RETRIES_DELAY, "1"); @@ -154,7 +154,7 @@ public void configure(HashTree testPlan) { } @Override - public void runTest() throws JMeterEngineException { + public void runTest() { log.debug("Running {}", host); } @@ -188,4 +188,4 @@ public void setHost(String host) { this.host = host; } } -} +} \ No newline at end of file From 5c68bf81510bd2665a19f82ed7a929b9da93122f Mon Sep 17 00:00:00 2001 From: Sampath Kumar Krishnasamy Date: Tue, 4 Jan 2022 09:45:06 +0000 Subject: [PATCH 019/736] Kept the new line as suggested --- .../java/org/apache/jmeter/engine/DistributedRunnerTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/src/test/java/org/apache/jmeter/engine/DistributedRunnerTest.java b/src/core/src/test/java/org/apache/jmeter/engine/DistributedRunnerTest.java index 6aa30b8faf8..172b94d1691 100644 --- a/src/core/src/test/java/org/apache/jmeter/engine/DistributedRunnerTest.java +++ b/src/core/src/test/java/org/apache/jmeter/engine/DistributedRunnerTest.java @@ -188,4 +188,4 @@ public void setHost(String host) { this.host = host; } } -} \ No newline at end of file +} From 51507ea138dddcdb997b5d2c6626a894901ee468 Mon Sep 17 00:00:00 2001 From: Sampath Kumar Krishnasamy Date: Tue, 4 Jan 2022 14:51:41 +0000 Subject: [PATCH 020/736] Logger and string usage warning fix Closes #689 --- .../java/org/apache/jmeter/functions/StringFromFile.java | 5 ++--- xdocs/changes.xml | 2 ++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/functions/src/main/java/org/apache/jmeter/functions/StringFromFile.java b/src/functions/src/main/java/org/apache/jmeter/functions/StringFromFile.java index e1b221da7fa..fc2207feeeb 100644 --- a/src/functions/src/main/java/org/apache/jmeter/functions/StringFromFile.java +++ b/src/functions/src/main/java/org/apache/jmeter/functions/StringFromFile.java @@ -122,7 +122,7 @@ public class StringFromFile extends AbstractFunction implements TestStateListene public StringFromFile() { if (log.isDebugEnabled()) { - log.debug("++++++++ Construct {}" + this); + log.debug("++++++++ Construct {}", this); } } @@ -147,9 +147,8 @@ private synchronized void openFile() { String tn = Thread.currentThread().getName(); fileName = ((CompoundVariable) values[0]).execute(); - String start = ""; if (values.length >= PARAM_START) { - start = ((CompoundVariable) values[PARAM_START - 1]).execute(); + String start = ((CompoundVariable) values[PARAM_START - 1]).execute(); try { // Low chances to be non numeric, we parse myStart = Integer.parseInt(start); diff --git a/xdocs/changes.xml b/xdocs/changes.xml index 33606f2ab5a..15ce9515889 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -194,6 +194,7 @@ however, the profile can't be updated while the test is running.
    • 654Try do give better feedback while loading keystores
    • 672Add more details to documentation for timeShift function. Contributed by Mariusz (mawasak at gmail.com)
    • Updated Gradle to 7.3 (from 7.2)
    • +
    • 689Code clean up in StringFromFile. Contributed by Sampath Kumar Krishnasamy (sampathkumar.krishnasamykuppusamy at aexp.com)
    @@ -291,6 +292,7 @@ however, the profile can't be updated while the test is running.
  • Chromico Rek (atech5122 at gmail.com)
  • Magnus Spångdal (magnus.spangdal as avanza.se)
  • Piotr Smietana (piotrsmietana1998 at gmail.com)
  • +
  • Sampath Kumar Krishnasamy (sampathkumar.krishnasamykuppusamy at aexp.com)
  • We also thank bug reporters who helped us improve JMeter.

      From 00834652d0ee8857d2976616eb60f52062fd5694 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Tue, 4 Jan 2022 18:27:15 +0100 Subject: [PATCH 021/736] Use correct message format for MessageFormat in HTMLAssertion Regression introduced by code clean up in commit af3958b3cd5172bc60ca2d3f440febf173f45f8e Bugzilla Id: 65782 --- .../main/java/org/apache/jmeter/assertions/HTMLAssertion.java | 2 +- xdocs/changes.xml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/src/main/java/org/apache/jmeter/assertions/HTMLAssertion.java b/src/components/src/main/java/org/apache/jmeter/assertions/HTMLAssertion.java index 8fc41ea1cdd..6e93c7e82c8 100644 --- a/src/components/src/main/java/org/apache/jmeter/assertions/HTMLAssertion.java +++ b/src/components/src/main/java/org/apache/jmeter/assertions/HTMLAssertion.java @@ -124,7 +124,7 @@ private AssertionResult runTidy(SampleResult inResponse) { log.debug("Errors/warnings detected while parsing with tidy: {}", errbuf); result.setFailure(true); result.setFailureMessage(MessageFormat.format( - "Tidy Parser errors: {} (allowed {}) Tidy Parser warnings: {} (allowed {})", + "Tidy Parser errors: {0} (allowed {1}) Tidy Parser warnings: {2} (allowed {3})", tidy.getParseErrors(), getErrorThreshold(), tidy.getParseWarnings(), getWarningThreshold())); // return with an error diff --git a/xdocs/changes.xml b/xdocs/changes.xml index 15ce9515889..c6cbeb9a215 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -234,6 +234,7 @@ however, the profile can't be updated while the test is running.
    • 65352Warning logged when Boundary Extractor doesn't find any match
    • 65681Use default values for null values when extracting with JSONPostProcessor
    • Allow setters in ConstantThroughputTimer to updating the values during the run time
    • +
    • 65782Use correct message format for MessageFormat in HTMLAssertion

    Functions

    From a16df4bcc86453b122a5ff9ad5e640d036ad0673 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Tue, 4 Jan 2022 20:03:26 +0100 Subject: [PATCH 022/736] Convert links to mail archives to the new lists.apache.org counterparts --- xdocs/mail2.xml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/xdocs/mail2.xml b/xdocs/mail2.xml index 5311853b86f..520e6d4f08a 100644 --- a/xdocs/mail2.xml +++ b/xdocs/mail2.xml @@ -62,7 +62,7 @@ For old postings, please see the Jakarta JMeter User list, below.
  • Subscribe at user-subscribe@jmeter.apache.org
  • Send your message to: user@jmeter.apache.org (after the subscription process)
  • Unsubscribe at user-unsubscribe@jmeter.apache.org
  • -
  • Archives at jmeter-user Archive
  • +
  • Archives at jmeter-user Archive
  • @@ -81,7 +81,7 @@ For earlier postings, please see below.
  • Subscribe at dev-subscribe@jmeter.apache.org
  • Send your message to: dev@jmeter.apache.org (after the subscription process)
  • Unsubscribe at dev-unsubscribe@jmeter.apache.org
  • -
  • Archives at jmeter-dev Archive
  • +
  • Archives at jmeter-dev Archive
  • @@ -92,7 +92,7 @@ Prior to Nov 2011, they were sent to the Jakarta Notifications list, see below. @@ -106,31 +106,31 @@ Prior to Nov 2011, they were sent to the Jakarta Notifications list, see below.

    Combined Jakarta developer list, April 2010 to November 2011

    This is the old JMeter user list from when JMeter was a sub-project of Apache Jakarta. +
  • Archives at jakarta-jmeter-user Archive
  • Historical list, up to April 2010. Combined Jakarta notifications to November 2011. Includes Bugzilla, SVN and Wiki commit mails for JMeter. From 37be72fc48121c142c0a4be1c634373e0f929882 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Wed, 5 Jan 2022 16:23:01 +0100 Subject: [PATCH 023/736] No Graphs displayed in Aggregate Report/Response Time Graph Make sure, that we scale away from zero (which is in our case mostly up). Otherwise we might end up with a scaling factor of zero, which would result in really small images. Bugzilla Id: 65784 --- .../main/java/org/apache/jmeter/visualizers/AxisGraph.java | 2 +- .../org/apache/jmeter/visualizers/RespTimeGraphChart.java | 4 ++-- xdocs/changes.xml | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/src/main/java/org/apache/jmeter/visualizers/AxisGraph.java b/src/components/src/main/java/org/apache/jmeter/visualizers/AxisGraph.java index c241a4f4793..5725557a00f 100644 --- a/src/components/src/main/java/org/apache/jmeter/visualizers/AxisGraph.java +++ b/src/components/src/main/java/org/apache/jmeter/visualizers/AxisGraph.java @@ -399,7 +399,7 @@ private void drawSample(String _title, int _maxLength, String[] _xAxisLabels, // Y Axis try { BigDecimal round = BigDecimal.valueOf(max / 1000d); - round = round.setScale(0, RoundingMode.HALF_EVEN); + round = round.setScale(0, RoundingMode.UP); double topValue = round.doubleValue() * 1000; yaxis.setUserDefinedScale(0, 500); yaxis.setNumItems((int) (topValue / 500)+1); diff --git a/src/components/src/main/java/org/apache/jmeter/visualizers/RespTimeGraphChart.java b/src/components/src/main/java/org/apache/jmeter/visualizers/RespTimeGraphChart.java index 02ab8f09f6d..bc1af59f487 100644 --- a/src/components/src/main/java/org/apache/jmeter/visualizers/RespTimeGraphChart.java +++ b/src/components/src/main/java/org/apache/jmeter/visualizers/RespTimeGraphChart.java @@ -282,7 +282,7 @@ private void drawSample(String _title, String[] _xAxisLabels, double[][] _data, int _width, int _height, int _incrScaleYAxis, Color[] _color, Font legendFont, Graphics g) { - double max = maxYAxisScale > 0 ? maxYAxisScale : getTopValue(findMax(_data), RoundingMode.HALF_EVEN); // define max scale y axis + double max = maxYAxisScale > 0 ? maxYAxisScale : getTopValue(findMax(_data), RoundingMode.UP); // define max scale y axis try { // if the title graph is empty, we can assume some default if (_title.length() == 0 ) { @@ -332,7 +332,7 @@ private void drawSample(String _title, String[] _xAxisLabels, double incrYAxis = max / numInterval; double incrTopValue = _incrScaleYAxis; if (_incrScaleYAxis == 0) { - incrTopValue = getTopValue(incrYAxis, RoundingMode.HALF_EVEN); + incrTopValue = getTopValue(incrYAxis, RoundingMode.HALF_UP); } if (incrTopValue < 1) { incrTopValue = 1.0d; // Increment cannot be < 1 diff --git a/xdocs/changes.xml b/xdocs/changes.xml index c6cbeb9a215..79c70d79a24 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -224,6 +224,7 @@ however, the profile can't be updated while the test is running.

    Listeners

    • 64962Save CSV sub-results recursively from View Results Tree
    • +
    • 65784No Graphs displayed in Aggregate Report/Response Time Graph

    Timers, Assertions, Config, Pre- & Post-Processors

    From af7fc4d56bffab352843cc87514ab9ed19bdad32 Mon Sep 17 00:00:00 2001 From: Sampath Kumar Krishnasamy Date: Thu, 6 Jan 2022 14:49:05 +0000 Subject: [PATCH 024/736] Split function test refactor with failure and different success scenarios separately Closes #690 --- .../jmeter/functions/SplitFunctionTest.java | 56 +++++++++++++------ xdocs/changes.xml | 1 + 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/src/functions/src/test/java/org/apache/jmeter/functions/SplitFunctionTest.java b/src/functions/src/test/java/org/apache/jmeter/functions/SplitFunctionTest.java index 177b85ef7df..69169bb8d8a 100644 --- a/src/functions/src/test/java/org/apache/jmeter/functions/SplitFunctionTest.java +++ b/src/functions/src/test/java/org/apache/jmeter/functions/SplitFunctionTest.java @@ -17,15 +17,16 @@ package org.apache.jmeter.functions; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.fail; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import java.util.Collection; import java.util.LinkedList; import org.apache.jmeter.engine.util.CompoundVariable; import org.apache.jmeter.junit.JMeterTestCase; +import org.apache.jmeter.samplers.SampleResult; import org.apache.jmeter.threads.JMeterContext; import org.apache.jmeter.threads.JMeterContextService; import org.apache.jmeter.threads.JMeterVariables; @@ -34,27 +35,30 @@ public class SplitFunctionTest extends JMeterTestCase { - private JMeterContext jmctx = null; private JMeterVariables vars = null; @BeforeEach public void setUp() { - jmctx = JMeterContextService.getContext(); - jmctx.setVariables(new JMeterVariables()); - vars = jmctx.getVariables(); + JMeterContext jmeterContext = JMeterContextService.getContext(); + jmeterContext.setVariables(new JMeterVariables()); + vars = jmeterContext.getVariables(); } @Test - public void splitTest1() throws Exception { - String src = ""; - - try { - splitParams("a,b,c", null, null); - fail("Expected InvalidVariableException (wrong number of parameters)"); - } catch (InvalidVariableException e) { - // OK - } - src = "a,b,c"; + public void shouldThrowExceptionWhenParameterCountIsInvalid() { + InvalidVariableException invalidVariableException = assertThrows(InvalidVariableException.class, () -> + splitParams("a,b,c", null, null), + "" + ); + assertEquals( + "__split called with wrong number of parameters. Actual: 1. Expected: >= 2 and <= 3", + invalidVariableException.getMessage() + ); + } + + @Test + public void shouldSplitWithoutAnyArguments() throws Exception { + String src = "a,b,c"; SplitFunction split; split = splitParams(src, "VAR1", null); assertEquals(src, split.execute()); @@ -134,6 +138,24 @@ public void splitTest1() throws Exception { assertNull(vars.get("VAR5_5")); } + @Test + public void shouldSplitWithPreviousResultOnly() throws Exception { + String src = "a,,c,"; + vars.put("VAR", src); + SplitFunction split = splitParams("${VAR}", "VAR5", null); + + SampleResult previousResult = new SampleResult(); + previousResult.setResponseData("Some data", null); + + assertEquals(src, split.execute(previousResult, null)); + assertEquals("4", vars.get("VAR5_n")); + assertEquals("a", vars.get("VAR5_1")); + assertEquals("?", vars.get("VAR5_2")); + assertEquals("c", vars.get("VAR5_3")); + assertEquals("?", vars.get("VAR5_4")); + assertNull(vars.get("VAR5_5")); + } + // Create the SplitFile function and set its parameters. private static SplitFunction splitParams(String p1, String p2, String p3) throws Exception { SplitFunction split = new SplitFunction(); diff --git a/xdocs/changes.xml b/xdocs/changes.xml index 79c70d79a24..e80edad1dcb 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -195,6 +195,7 @@ however, the profile can't be updated while the test is running.
  • 672Add more details to documentation for timeShift function. Contributed by Mariusz (mawasak at gmail.com)
  • Updated Gradle to 7.3 (from 7.2)
  • 689Code clean up in StringFromFile. Contributed by Sampath Kumar Krishnasamy (sampathkumar.krishnasamykuppusamy at aexp.com)
  • +
  • 690Refactor a few unit tests. Contributed by Sampath Kumar Krishnasamy (sampathkumar.krishnasamykuppusamy at aexp.com)
  • From abb069cc8e72c8e57eb8835bf3ceb26e4bb91416 Mon Sep 17 00:00:00 2001 From: Vladimir Sitnikov Date: Sat, 15 Jan 2022 22:18:30 +0300 Subject: [PATCH 025/736] ci: terminate stale GitHub CI jobs early For instance, when several commits are pushed to PR in short sequence, older CI jobs would be terminated immediately so the newer commits are tested faster. --- .github/workflows/main.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3c65a5412ed..de80c5e9eec 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,6 +10,13 @@ on: # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/software-installed-on-github-hosted-runners +concurrency: + # On master/release, we don't want any jobs cancelled so the sha is used to name the group + # On PR branches, we cancel the job if new commits are pushed + # More info: https://stackoverflow.com/a/68422069/253468 + group: ${{ (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/release' ) && format('ci-main-{0}', github.sha) || format('ci-main-{0}', github.ref) }} + cancel-in-progress: true + jobs: windows: name: 'Windows (JDK 17)' From 6a5cac0ad75e72d5313f3c795845c6cea9ff6520 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Tue, 18 Jan 2022 17:36:49 +0100 Subject: [PATCH 026/736] JSON Assertion always successful with indefinite paths Add a note to the component reference for JSON Path Assertions Bugzilla Id: 65794 --- xdocs/changes.xml | 2 ++ xdocs/usermanual/component_reference.xml | 3 +++ 2 files changed, 5 insertions(+) diff --git a/xdocs/changes.xml b/xdocs/changes.xml index e80edad1dcb..6f56b600c49 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -253,6 +253,7 @@ however, the profile can't be updated while the test is running.

    Documentation

      +
    • 65794JSON Assertion always successful with indefinite paths

    General

    @@ -300,6 +301,7 @@ however, the profile can't be updated while the test is running.

    We also thank bug reporters who helped us improve JMeter.

    • Nikola Aleksic (nalexic at gmail.com)
    • +
    • Vladimir Rosu (rosuvladimir at gmail.com)

    Apologies if we have omitted anyone else. diff --git a/xdocs/usermanual/component_reference.xml b/xdocs/usermanual/component_reference.xml index 02b9cf90b05..985918c93ff 100644 --- a/xdocs/usermanual/component_reference.xml +++ b/xdocs/usermanual/component_reference.xml @@ -5035,6 +5035,9 @@ please ensure that you select "Store the message using MIME (raw)" Second, it will search for specified path, using syntax from Jayway JsonPath 1.2.0. If the path is not found, it will fail. Third, if JSON path was found in the document, and validation against expected value was requested, it will perform validation. For the null value there is special checkbox in the GUI. Note that if the path will return array object, it will be iterated and if expected value is found, the assertion will succeed. To validate empty array use [] string. Also, if patch will return dictionary object, it will be converted to string before comparison. + When using indefinite JSON Paths + you must assert the value due to the existing JSON library implementation, otherwise the assertion could always + return successful

    From 278255de85829c850d36ad1655d1541e66d5368f Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Sat, 15 Jan 2022 18:11:36 +0100 Subject: [PATCH 027/736] Fail JSONPath Assertion on indefinite paths and no assertion value The docs for JSONPath Assertion state, that it will fail the assertion, when no element is found with the given JSON path. This was currently not followed, when an indefinite path was used. In such a case, the JSONPath library would return an empty list, which the assertion logic would log as OK. With this change we let the assertion fail, when * an indefinite path was given * and an empty list is extracted * and no assertion value is given Bugzilla Id: 65794 --- .../apache/jmeter/assertions/JSONPathAssertion.java | 10 ++++++++-- .../jmeter/assertions/TestJSONPathAssertion.java | 6 +++++- xdocs/changes.xml | 2 +- xdocs/usermanual/component_reference.xml | 4 +++- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/components/src/main/java/org/apache/jmeter/assertions/JSONPathAssertion.java b/src/components/src/main/java/org/apache/jmeter/assertions/JSONPathAssertion.java index 2e135b46b21..c2986df1cd8 100644 --- a/src/components/src/main/java/org/apache/jmeter/assertions/JSONPathAssertion.java +++ b/src/components/src/main/java/org/apache/jmeter/assertions/JSONPathAssertion.java @@ -30,12 +30,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.jayway.jsonpath.JsonPath; + import net.minidev.json.JSONArray; import net.minidev.json.JSONObject; import net.minidev.json.JSONValue; -import com.jayway.jsonpath.JsonPath; - /** * This is main class for JSONPath Assertion which verifies assertion on * previous sample result using JSON path expression @@ -112,6 +112,12 @@ private void doAssert(String jsonString) { Object value = JsonPath.read(jsonString, getJsonPath()); if (!isJsonValidationBool()) { + if (value instanceof JSONArray) { + JSONArray arrayValue = (JSONArray) value; + if (arrayValue.isEmpty() && !JsonPath.isPathDefinite(getJsonPath())) { + throw new IllegalStateException("JSONPath is indefinite and the extracted Value is an empty Array. Please use an assertion value, to be sure to get a correct result. " + getExpectedValue()); + } + } return; } diff --git a/src/components/src/test/java/org/apache/jmeter/assertions/TestJSONPathAssertion.java b/src/components/src/test/java/org/apache/jmeter/assertions/TestJSONPathAssertion.java index f4245f21638..a6738c30a43 100644 --- a/src/components/src/test/java/org/apache/jmeter/assertions/TestJSONPathAssertion.java +++ b/src/components/src/test/java/org/apache/jmeter/assertions/TestJSONPathAssertion.java @@ -22,6 +22,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; +import java.nio.charset.Charset; import java.util.Locale; import org.apache.jmeter.samplers.SampleResult; @@ -270,6 +271,9 @@ void testGetResult_list_negative() { @Test void testGetResult_list_empty_novalidate() { + // With bug 65794 the outcome of this test has changed + // we now consider an indefinite path with no assertion value + // an error and set the AssertionResult to failure SampleResult samplerResult = new SampleResult(); samplerResult.setResponseData("{\"myval\": []}".getBytes()); @@ -279,7 +283,7 @@ void testGetResult_list_empty_novalidate() { AssertionResult expResult = new AssertionResult(""); AssertionResult result = instance.getResult(samplerResult); assertEquals(expResult.getName(), result.getName()); - assertFalse(result.isFailure()); + assertTrue(result.isFailure()); } @Test diff --git a/xdocs/changes.xml b/xdocs/changes.xml index 6f56b600c49..89c936b95b2 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -237,6 +237,7 @@ however, the profile can't be updated while the test is running.
  • 65681Use default values for null values when extracting with JSONPostProcessor
  • Allow setters in ConstantThroughputTimer to updating the values during the run time
  • 65782Use correct message format for MessageFormat in HTMLAssertion
  • +
  • 65794JSON Assertion always successful with indefinite paths
  • Functions

    @@ -253,7 +254,6 @@ however, the profile can't be updated while the test is running.

    Documentation

      -
    • 65794JSON Assertion always successful with indefinite paths

    General

    diff --git a/xdocs/usermanual/component_reference.xml b/xdocs/usermanual/component_reference.xml index 985918c93ff..d1fdfb8d216 100644 --- a/xdocs/usermanual/component_reference.xml +++ b/xdocs/usermanual/component_reference.xml @@ -5037,7 +5037,9 @@ please ensure that you select "Store the message using MIME (raw)" Note that if the path will return array object, it will be iterated and if expected value is found, the assertion will succeed. To validate empty array use [] string. Also, if patch will return dictionary object, it will be converted to string before comparison. When using indefinite JSON Paths you must assert the value due to the existing JSON library implementation, otherwise the assertion could always - return successful + return successful.
    + Since JMeter version 5.5 the assertion will fail, if an indefinite path is given, an empty list is extracted and + no assertion value is set.

    From 3e54034a25f2ce0582fb52b00322fdbbc6591136 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Wed, 19 Jan 2022 19:33:04 +0100 Subject: [PATCH 028/736] Fix markup for components reference Broken with last commit for JSON Path Assertion Bugzilla Id: 65794 --- xdocs/usermanual/component_reference.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xdocs/usermanual/component_reference.xml b/xdocs/usermanual/component_reference.xml index d1fdfb8d216..5aff4f054cd 100644 --- a/xdocs/usermanual/component_reference.xml +++ b/xdocs/usermanual/component_reference.xml @@ -5037,7 +5037,7 @@ please ensure that you select "Store the message using MIME (raw)" Note that if the path will return array object, it will be iterated and if expected value is found, the assertion will succeed. To validate empty array use [] string. Also, if patch will return dictionary object, it will be converted to string before comparison. When using indefinite JSON Paths you must assert the value due to the existing JSON library implementation, otherwise the assertion could always - return successful.
    + return successful.

    Since JMeter version 5.5 the assertion will fail, if an indefinite path is given, an empty list is extracted and no assertion value is set.

    From 980e5b8975948bb0dab45b735d88901c185b00a4 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Wed, 19 Jan 2022 19:53:12 +0100 Subject: [PATCH 029/736] Apply autostyle to imports changed with last commit Bugzilla Id: 65794 --- .../java/org/apache/jmeter/assertions/JSONPathAssertion.java | 4 ++-- .../org/apache/jmeter/assertions/TestJSONPathAssertion.java | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/components/src/main/java/org/apache/jmeter/assertions/JSONPathAssertion.java b/src/components/src/main/java/org/apache/jmeter/assertions/JSONPathAssertion.java index c2986df1cd8..91325dc15a8 100644 --- a/src/components/src/main/java/org/apache/jmeter/assertions/JSONPathAssertion.java +++ b/src/components/src/main/java/org/apache/jmeter/assertions/JSONPathAssertion.java @@ -30,12 +30,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.jayway.jsonpath.JsonPath; - import net.minidev.json.JSONArray; import net.minidev.json.JSONObject; import net.minidev.json.JSONValue; +import com.jayway.jsonpath.JsonPath; + /** * This is main class for JSONPath Assertion which verifies assertion on * previous sample result using JSON path expression diff --git a/src/components/src/test/java/org/apache/jmeter/assertions/TestJSONPathAssertion.java b/src/components/src/test/java/org/apache/jmeter/assertions/TestJSONPathAssertion.java index a6738c30a43..8447977d687 100644 --- a/src/components/src/test/java/org/apache/jmeter/assertions/TestJSONPathAssertion.java +++ b/src/components/src/test/java/org/apache/jmeter/assertions/TestJSONPathAssertion.java @@ -22,7 +22,6 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import java.nio.charset.Charset; import java.util.Locale; import org.apache.jmeter.samplers.SampleResult; From b953b45099351cc13e0a07afe0c8ba43fc420f10 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Wed, 19 Jan 2022 19:58:37 +0100 Subject: [PATCH 030/736] Line too long Bugzilla Id: 65794 --- .../java/org/apache/jmeter/assertions/JSONPathAssertion.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/src/main/java/org/apache/jmeter/assertions/JSONPathAssertion.java b/src/components/src/main/java/org/apache/jmeter/assertions/JSONPathAssertion.java index 91325dc15a8..98aeca67250 100644 --- a/src/components/src/main/java/org/apache/jmeter/assertions/JSONPathAssertion.java +++ b/src/components/src/main/java/org/apache/jmeter/assertions/JSONPathAssertion.java @@ -115,7 +115,8 @@ private void doAssert(String jsonString) { if (value instanceof JSONArray) { JSONArray arrayValue = (JSONArray) value; if (arrayValue.isEmpty() && !JsonPath.isPathDefinite(getJsonPath())) { - throw new IllegalStateException("JSONPath is indefinite and the extracted Value is an empty Array. Please use an assertion value, to be sure to get a correct result. " + getExpectedValue()); + throw new IllegalStateException("JSONPath is indefinite and the extracted Value is an empty Array." + + " Please use an assertion value, to be sure to get a correct result. " + getExpectedValue()); } } return; From d87a25bb1908293322a523d91050f30a459139d7 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Mon, 24 Jan 2022 19:02:10 +0100 Subject: [PATCH 031/736] Fix typo (mainly to trigger buildbot) --- xdocs/usermanual/include_controller_tutorial.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xdocs/usermanual/include_controller_tutorial.xml b/xdocs/usermanual/include_controller_tutorial.xml index 065b3561de1..145dfdebaa7 100644 --- a/xdocs/usermanual/include_controller_tutorial.xml +++ b/xdocs/usermanual/include_controller_tutorial.xml @@ -38,7 +38,7 @@ in a couple of ways.

      -
    • the Include Controller loads a simple controller with all it's samples, where as the Module +
    • the Include Controller loads a simple controller with all its samples, where as the Module Controller can use any controller
    • the Include Controller doesn't use the workbench
    • the Module Controller doesn't load from a file
    • From 160ec244b7da7e8dd35fa1ca1d2591218375ec0a Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Mon, 24 Jan 2022 19:08:52 +0100 Subject: [PATCH 032/736] Correct more typos (it's vs. its) --- xdocs/usermanual/component_reference.xml | 4 ++-- xdocs/usermanual/jmeter_tutorial.xml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/xdocs/usermanual/component_reference.xml b/xdocs/usermanual/component_reference.xml index 5aff4f054cd..00b8ed21cda 100644 --- a/xdocs/usermanual/component_reference.xml +++ b/xdocs/usermanual/component_reference.xml @@ -1211,7 +1211,7 @@ props.put("PROP1","1234"); Name of a file to be used as a JSR223 script, if a relative file path is used, then it will be relative to directory referenced by "user.dir" System property List of parameters to be passed to the script file or the script. - If checked (advised) and the language used supports Compilable interface (Groovy is one of these, java, beanshell and javascript are not), JMeter will compile the Script and cache it using it's MD5 hash as unique cache key + If checked (advised) and the language used supports Compilable interface (Groovy is one of these, java, beanshell and javascript are not), JMeter will compile the Script and cache it using its MD5 hash as unique cache key Script to be passed to JSR223 language

      @@ -6044,7 +6044,7 @@ extracting the node as text or attribute value and store the result into the giv use namespaces than with the old XPathExtractor version.

      To allow for use in a , it works exactly the same as the above XPath Extractor

      -

      XPath2 Extractor provides some interestings tools such as an improved syntax and much more functions than in it's first version.

      +

      XPath2 Extractor provides some interestings tools such as an improved syntax and much more functions than in its first version.

      Here are some exemples:

      abs(/book/page[2])
      diff --git a/xdocs/usermanual/jmeter_tutorial.xml b/xdocs/usermanual/jmeter_tutorial.xml index fe5e7f0b425..f32a8d0f887 100644 --- a/xdocs/usermanual/jmeter_tutorial.xml +++ b/xdocs/usermanual/jmeter_tutorial.xml @@ -768,7 +768,7 @@ JMeter's src/components directory). attention to your properties. These properties will become the basis of a GUI form by which users will configure the CSVDataSet element. -
    • Your element will be cloned by JMeter when the test starts. Each thread will get it's +
    • Your element will be cloned by JMeter when the test starts. Each thread will get its own instance. However, you will have a chance to control how the cloning is done, if you need it.
    • @@ -785,7 +785,7 @@ JMeter's src/components directory).
    • I then implemented the IterationStart method of the LoopIterationListener interface. The point of this "event" is that your component is notified of when the test has entered - it's parent controller. For our purposes, every time the CSVDataSet's parent controller + its parent controller. For our purposes, every time the CSVDataSet's parent controller is entered, we will read a new line of the data file and set the variables. Thus, for a regular controller, each loop through the test will result in a new set of values being read. For a loop controller, each iteration will do likewise. Every test thread will get From 04548fd2081def422d3756907823406691290c7e Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Mon, 24 Jan 2022 20:35:21 +0100 Subject: [PATCH 033/736] Use English typographic conventions for colons (no space in front) --- xdocs/usermanual/generating-dashboard.xml | 26 +++++++++++------------ 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/xdocs/usermanual/generating-dashboard.xml b/xdocs/usermanual/generating-dashboard.xml index 912b9255792..49ee7fc1763 100644 --- a/xdocs/usermanual/generating-dashboard.xml +++ b/xdocs/usermanual/generating-dashboard.xml @@ -42,23 +42,23 @@
      • APDEX (Application Performance Index) table that computes for every transaction the APDEX based on configurable values for tolerated and satisfied thresholds
      • A request summary graph showing the Success and failed requests (Transaction Controller Sample Results are not taken into account) percentage:
      • -
      • A Statistics table providing in one table a summary of all metrics per transaction including 3 configurable percentiles :
      • -
      • An error table providing a summary of all errors and their proportion in the total requests :
      • -
      • A Top 5 Errors by Sampler table providing for every Sampler (excluding Transaction Controller by default) the top 5 Errors :
      • +
      • A Statistics table providing in one table a summary of all metrics per transaction including 3 configurable percentiles:
      • +
      • An error table providing a summary of all errors and their proportion in the total requests:
      • +
      • A Top 5 Errors by Sampler table providing for every Sampler (excluding Transaction Controller by default) the top 5 Errors:
      • Zoomable chart where you can check/uncheck every transaction to show/hide it for:
          -
        • Response times Over Time (Includes Transaction Controller Sample Results) :
        • -
        • Response times Percentiles Over Time (successful responses only) :
        • -
        • Active Threads Over Time :
        • -
        • Bytes throughput Over Time (Ignores Transaction Controller Sample Results) :
        • -
        • Latencies Over Time (Includes Transaction Controller Sample Results) :
        • -
        • Connect Time Over Time (Includes Transaction Controller Sample Results) :
        • +
        • Response times Over Time (Includes Transaction Controller Sample Results):
        • +
        • Response times Percentiles Over Time (successful responses only):
        • +
        • Active Threads Over Time:
        • +
        • Bytes throughput Over Time (Ignores Transaction Controller Sample Results):
        • +
        • Latencies Over Time (Includes Transaction Controller Sample Results):
        • +
        • Connect Time Over Time (Includes Transaction Controller Sample Results):
        • Hits per second (Ignores Transaction Controller Sample Results):
        • Response codes per second (Ignores Transaction Controller Sample Results):
        • Transactions per second (Includes Transaction Controller Sample Results):
        • Response Time vs Request per second (Ignores Transaction Controller Sample Results):
        • Latency vs Request per second (Ignores Transaction Controller Sample Results):
        • -
        • Response time Overview (Excludes Transaction Controller Sample Results) :
        • +
        • Response time Overview (Excludes Transaction Controller Sample Results):
        • Response times percentiles (Includes Transaction Controller Sample Results):
        • Times vs Threads (Includes Transaction Controller Sample Results):
          In distributed mode, this graph shows a horizontal axis the number of threads for 1 server. It's a current limitation @@ -215,9 +215,9 @@ jmeter.save.saveservice.timestamp_format = ms Percentiles used by Summary table and Percentile graphs can be adjusted to different values by using the 3 properties:
            -
          • aggregate_rpt_pct1 : Defaults to 90
          • -
          • aggregate_rpt_pct2 : Defaults to 95
          • -
          • aggregate_rpt_pct3 : Defaults to 99
          • +
          • aggregate_rpt_pct1: Defaults to 90
          • +
          • aggregate_rpt_pct2: Defaults to 95
          • +
          • aggregate_rpt_pct3: Defaults to 99
          Relative paths are built from the JMeter working directory From 85580b49ee2f06505129ebccac5d382e412c58e2 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Mon, 24 Jan 2022 20:51:01 +0100 Subject: [PATCH 034/736] Whitespace change (remove tab, as we normally use spaces here) --- xdocs/usermanual/properties_reference.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xdocs/usermanual/properties_reference.xml b/xdocs/usermanual/properties_reference.xml index d4b05a2166b..e373627838d 100644 --- a/xdocs/usermanual/properties_reference.xml +++ b/xdocs/usermanual/properties_reference.xml @@ -117,7 +117,7 @@ defined in the system.properties file or on the command-line. The JVM does not support the specified cipher suites, or if the cipher suites supported by the HTTPS server do not overlap this list. See the JSSE - Reference Guide.
          + Reference Guide.
          For example: https.cipherSuites=TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256 If not specified, JMeter will use the default list of cipher suites supported by the JVM. From 25932ff6b7b1364a27c46bd0f1e35dc7fac0a209 Mon Sep 17 00:00:00 2001 From: Stefan Seide Date: Tue, 25 Jan 2022 13:35:41 +0100 Subject: [PATCH 035/736] Update tika-parsers to 1.28, jackson to 2.13.1 and jsoup to 1.14.3 Detailed version updates are: Updated jsoup from 1.14.1 (in nightlies), from 1.13.1 (last released) Updated Apache Tika from 1.27 (in nightlies), from 1.26 (last released) Updated jackson to 2.13.1 (from 2.10.5) Closes #695 --- gradle.properties | 8 ++++---- src/dist/src/dist/expected_release_jars.csv | 12 ++++++------ xdocs/changes.xml | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/gradle.properties b/gradle.properties index df7baa176cc..23207fddbef 100644 --- a/gradle.properties +++ b/gradle.properties @@ -98,8 +98,8 @@ httpclient.version=4.5.13 httpcore-nio.version=4.4.14 httpcore.version=4.4.14 httpmime.version=4.5.13 -jackson.version=2.10.5 -jackson-databind.version=2.10.5 +jackson.version=2.13.1 +jackson-databind.version=2.13.1 javax.activation.version=1.2.0 jcharts.version=0.7.5 jdom.version=1.1.3 @@ -109,7 +109,7 @@ jmespath-jackson.version=0.5.0 jodd.version=5.0.13 json-path.version=2.6.0 json-smart.version=2.4.7 -jsoup.version=1.14.1 +jsoup.version=1.14.3 jtidy.version=r938 junit4.version=4.13.2 junit5.version=5.8.1 @@ -132,7 +132,7 @@ slf4j.version=1.7.32 spock-core.version=2.0-M2-groovy-3.0 springframework.version=4.3.17.RELEASE svgSalamander.version=1.1.2.4 -tika.version=1.27 +tika.version=1.28 xalan.version=2.7.2 xercesImpl.version=2.12.1 xml-apis.version=1.4.01 diff --git a/src/dist/src/dist/expected_release_jars.csv b/src/dist/src/dist/expected_release_jars.csv index 3cd09108c19..a43c8d348bf 100644 --- a/src/dist/src/dist/expected_release_jars.csv +++ b/src/dist/src/dist/expected_release_jars.csv @@ -69,9 +69,9 @@ 328436,httpcore-4.4.14.jar 369365,httpcore-nio-4.4.14.jar 41790,httpmime-4.5.13.jar -68080,jackson-annotations-2.10.5.jar -349331,jackson-core-2.10.5.jar -1404939,jackson-databind-2.10.5.jar +75717,jackson-annotations-2.13.1.jar +374588,jackson-core-2.13.1.jar +1534017,jackson-databind-2.13.1.jar 78030,javax.activation-1.2.0.jar 142391,jcharts-0.7.5.jar 16630,jcl-over-slf4j-1.7.32.jar @@ -83,7 +83,7 @@ 26047,jodd-props-5.0.13.jar 238605,json-path-2.6.0.jar 119227,json-smart-2.4.7.jar -415074,jsoup-1.14.1.jar +423395,jsoup-1.14.3.jar 249924,jtidy-r938.jar 384581,junit-4.13.2.jar 32033,kotlin-logging-jvm-2.0.5.jar @@ -121,8 +121,8 @@ 301279,svgSalamander-1.1.2.4.jar 10192,swing-extensions-laf-support-0.1.3.jar 2539,swing-extensions-visual-padding-0.1.3.jar -734528,tika-core-1.27.jar -1397879,tika-parsers-1.27.jar +735635,tika-core-1.28.jar +1585374,tika-parsers-1.28.jar 174661,vis-svg-portable-jvm-2.2.1.jar 3154938,xalan-2.7.2.jar 1386502,xercesImpl-2.12.1.jar diff --git a/xdocs/changes.xml b/xdocs/changes.xml index 89c936b95b2..e45c4afcd95 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -167,13 +167,12 @@ however, the profile can't be updated while the test is running.
        • Updated Apache commons-pool2 to 2.11.0 (from 2.9.0).
        • Updated equalsverifier to 3.7 (from 3.4.2).
        • Updated Apache Freemarker to 2.3.31 (from 2.3.30).
        • -
        • Updated hsqldb to 2.5.2 (from 2.5.0).
        • Updated hsqldb to 2.6.0 (from 2.5.0).
        • Updated Apache HttpClient to 4.5.13 (from 4.5.12).
        • Updated Apache HttpCore to 4.4.14 (from 4.4.13).
        • Updated jacoco to 0.8.7 (from 0.8.5).
        • Updated json-path to 2.6.0 (from 2.4.0).
        • -
        • Updated jsoup to 1.14.1 (from 1.13.1).
        • +
        • Updated jsoup to 1.14.3 (from 1.13.1).
        • Updated JUnit to 4.13.2 and 5.8.1 (from 4.13.1 and 5.7.0).
        • Updated Apache log4j2 to 2.17.1 (from 2.13.3).
        • Updated Miglayout to 5.3 (from 5.2).
        • @@ -184,9 +183,10 @@ however, the profile can't be updated while the test is running.
        • Updated RSyntaxTextArea to 3.1.3 (from 3.1.1).
        • Updated SLF4J to 1.7.32 (from 1.7.30).
        • Updated SvgSalamander to 1.1.2.4 (from 1.1.2.1).
        • -
        • Updated Apache Tika to 1.27 (from 1.26).
        • +
        • Updated Apache Tika to 1.28 (from 1.26).
        • Updated WireMock-JRE8 to 2.30.0 (from 2.24.1).
        • Updated com.github.vlsi.vlsi-release-plugins 1.76 (from 1.74).
        • +
        • Updated jackson to 2.13.1 (from 2.10.5)
        • 671Move example definition of property jmeter.reportgenerator.statistic_window to user.properties, as it is read from that place. Contributed by Rithvik Patibandla (rithvikp98 at gmail.com)
        • From 6196e403091c2d9cf2f7d1ea6aa1610efab73e37 Mon Sep 17 00:00:00 2001 From: Sampath Kumar Krishnasamy Date: Thu, 13 Jan 2022 18:14:26 +0000 Subject: [PATCH 036/736] Fixed the deprecation warnings in build file Closes #692 --- build.gradle.kts | 6 +++--- xdocs/changes.xml | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 19944b72401..97eccfa8262 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -207,7 +207,7 @@ fun SonarQubeProperties.add(name: String, valueProvider: () -> String) { } if (jacocoEnabled) { - val mergedCoverage = jacocoReport.get().reports.xml.destination.toString() + val mergedCoverage = jacocoReport.get().reports.xml.outputLocation.toString() // For every module we pass merged coverage report // That enables to see ":src:core" lines covered even in case they are covered from @@ -493,8 +493,8 @@ allprojects { tasks.withType().configureEach { reports { - html.isEnabled = reportsForHumans() - xml.isEnabled = !reportsForHumans() + html.required.set(reportsForHumans()) + xml.required.set(!reportsForHumans()) } } // Add each project to combined report diff --git a/xdocs/changes.xml b/xdocs/changes.xml index e45c4afcd95..3877b556b1a 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -196,6 +196,7 @@ however, the profile can't be updated while the test is running.
        • Updated Gradle to 7.3 (from 7.2)
        • 689Code clean up in StringFromFile. Contributed by Sampath Kumar Krishnasamy (sampathkumar.krishnasamykuppusamy at aexp.com)
        • 690Refactor a few unit tests. Contributed by Sampath Kumar Krishnasamy (sampathkumar.krishnasamykuppusamy at aexp.com)
        • +
        • 692>Fix a few deprecation warnings for Gradle. Contributed by Sampath Kumar Krishnasamy (sampathkumar.krishnasamykuppusamy at aexp.com)
        From 97c969865abdb0c7e01731b856a234441367b499 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Wed, 2 Feb 2022 12:06:07 +0100 Subject: [PATCH 037/736] Use isEmtpy instead of checking length --- .../apache/jmeter/protocol/http/proxy/FormCharSetFinder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/proxy/FormCharSetFinder.java b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/proxy/FormCharSetFinder.java index 84b595a227b..9588cde061e 100644 --- a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/proxy/FormCharSetFinder.java +++ b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/proxy/FormCharSetFinder.java @@ -67,7 +67,7 @@ public void addFormActionsAndCharSet(String html, Map formEncodi // Just use the first one of the possible many charsets if(charSets.length > 0) { formCharSet = charSets[0].trim(); - if(formCharSet.length() == 0) { + if (formCharSet.isEmpty()) { formCharSet = null; } } From 48dc723d22c52b5605022a8739c9bf65fd0be1ca Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Wed, 2 Feb 2022 12:07:17 +0100 Subject: [PATCH 038/736] Use space between if and parenthesis if is not a function. --- .../jmeter/protocol/http/proxy/FormCharSetFinder.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/proxy/FormCharSetFinder.java b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/proxy/FormCharSetFinder.java index 9588cde061e..77b3fe22fb7 100644 --- a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/proxy/FormCharSetFinder.java +++ b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/proxy/FormCharSetFinder.java @@ -62,17 +62,17 @@ public void addFormActionsAndCharSet(String html, Map formEncodi String formCharSet = pageEncoding; String acceptCharSet = element.attr("accept-charset"); // Check if we found an accept-charset attribute on the form - if(acceptCharSet != null) { + if (acceptCharSet != null) { String[] charSets = JOrphanUtils.split(acceptCharSet, ","); // Just use the first one of the possible many charsets - if(charSets.length > 0) { + if (charSets.length > 0) { formCharSet = charSets[0].trim(); if (formCharSet.isEmpty()) { formCharSet = null; } } } - if(formCharSet != null) { + if (formCharSet != null) { formEncodings.put(action, formCharSet); } } From a1b170de57f7f32a333aec2db9bb4d1823f44258 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Wed, 2 Feb 2022 16:49:57 +0100 Subject: [PATCH 039/736] Catch NullPointerException from JSoup when recording a test plan As reported in the bug issue, JSoup throws a NPE on some input. When we know more about that input, we might be able to do better, for now, let us wrap the exception into the declared HTMLParseException and hope, that we can continue. Bugzilla Id: 65864 --- .../jmeter/protocol/http/proxy/FormCharSetFinder.java | 6 +++++- xdocs/changes.xml | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/proxy/FormCharSetFinder.java b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/proxy/FormCharSetFinder.java index 77b3fe22fb7..43e3395aaaa 100644 --- a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/proxy/FormCharSetFinder.java +++ b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/proxy/FormCharSetFinder.java @@ -52,7 +52,11 @@ public void addFormActionsAndCharSet(String html, Map formEncodi throws HTMLParseException { log.debug("Parsing html of: {}", html); - Document document = Jsoup.parse(html); + try { + Document document = Jsoup.parse(html); + } catch (RuntimeException e) { + throw new HTMLParseException("Could not parse HTML to look for forms charsets", e); + } Elements forms = document.select("form"); for (Element element : forms) { String action = element.attr("action"); diff --git a/xdocs/changes.xml b/xdocs/changes.xml index 3877b556b1a..2f86ec86bde 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -210,6 +210,7 @@ however, the profile can't be updated while the test is running.
      • 65363NullPointerException in HTTPHC4Impl$ManagedCredentialsProvider.getAuthorizationForAuthScope when 401 response from remote and httpclient4.auth.preemptive=false
      • 65692HTTP(s) Test Script Recorder: Enable setting enabled cipher suite and enabled protocols on SSLContext/ Align ssl properties between Java and HC4 impl
      • 65108Support JMeter variables in GraphQL HTTP Request
      • +
      • 65864Catch NullPointerException from JSoup when recording a test plan

      Other Samplers

      From 3a74a92b298b0d32cfc96a689c8fc95125201dde Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Wed, 2 Feb 2022 16:56:54 +0100 Subject: [PATCH 040/736] Catch NullPointerException from JSoup when recording a test plan Fix stupid bug, where I placed the declaration of the method variable inside the try-catch block. Bugzilla Id: 65864 --- .../apache/jmeter/protocol/http/proxy/FormCharSetFinder.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/proxy/FormCharSetFinder.java b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/proxy/FormCharSetFinder.java index 43e3395aaaa..d577f320284 100644 --- a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/proxy/FormCharSetFinder.java +++ b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/proxy/FormCharSetFinder.java @@ -52,8 +52,9 @@ public void addFormActionsAndCharSet(String html, Map formEncodi throws HTMLParseException { log.debug("Parsing html of: {}", html); + Document document; try { - Document document = Jsoup.parse(html); + document = Jsoup.parse(html); } catch (RuntimeException e) { throw new HTMLParseException("Could not parse HTML to look for forms charsets", e); } From 755302aacda5468d8c1631b78607a900073fb961 Mon Sep 17 00:00:00 2001 From: Vladimir Sitnikov Date: Sun, 13 Feb 2022 12:59:35 +0300 Subject: [PATCH 041/736] Add a checksum for gradle-enterprise-gradle-plugin-3.8.1.jar for Gradle 7.4+ --- settings.gradle.kts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/settings.gradle.kts b/settings.gradle.kts index e27df11c67c..8fce3cdecca 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -151,6 +151,8 @@ val expectedSha512 = mapOf( to "gradle-enterprise-gradle-plugin-3.7.2.jar", "24A1722CB574BA3126C3C6EBEB3D4A39D2A86ECCEDD378BA96A5508626D1AEAC7BB5FFBC189929E16900B94C1D016AFA83A462DCB2BB03F634FCA9C7FDE9EBA5" to "gradle-enterprise-gradle-plugin-3.8.jar", + "11BED06D6ECD5669DE3F32A0B386A223C2B2BA532A3C80D3E1613B29A1A264E1A75CDF142273F17EE1845287C76CF1F9D68CD97542318B1A9126104CE958824A" + to "gradle-enterprise-gradle-plugin-3.8.1.jar", "FA305ACAAF45D005F5032D93C4F37CD097936C802943885A8F2B9EC27DA24F148DB41748655347C9A707C62614087432B3D32CC1B297381D45F3D8063BFFFA6D" to "bcpg-jdk15on-1.62.jar", "2BA6A5DEC9C8DAC2EB427A65815EB3A9ADAF4D42D476B136F37CD57E6D013BF4E9140394ABEEA81E42FBDB8FC59228C7B85C549ED294123BF898A7D048B3BD95" From dbbe8e6e353dc996f57b776b5948fc6b0cfde5a4 Mon Sep 17 00:00:00 2001 From: Vladimir Sitnikov Date: Mon, 17 Jan 2022 12:03:52 +0300 Subject: [PATCH 042/736] [Bug 63620] Fix GUI freeze when viewing response body with long lines GUI gets unresponsive when the response contains long lines (e.g lines exceeding 100K chars). The workaround is to add artificial line breaks. We try to break on word boundaries first, and if not possible, we break on char boundaries (e.g. large chunks of base64 data). view.results.tree.max_line_size=110000 (defaults to 110K) view.results.tree.soft_wrap_line_size=100000 (defaults to max_line_size/1.1) CPU spin trace looks as follows: "AWT-EventQue... ... at sun.font.GlyphLayout.layout(Unknown Source) ... at java.awt.font.TextLine.(Unknown Source) at java.awt.font.TextMeasurer.makeTextLineOnRange(Unknown Source) at java.awt.font.TextMeasurer.getLayout(Unknown Source) ... at javax.swing.text.JTextComponent.setDocument(Unknown Source) at org.apache.jmeter.visualizers.SamplerResultTab.setTextOptimized(SamplerResultTab.java:695) ... --- bin/jmeter.properties | 7 + .../RenderAsBoundaryExtractor.java | 1 + .../jmeter/visualizers/RenderAsCssJQuery.java | 1 + .../jmeter/visualizers/RenderAsRegexp.java | 1 + .../jmeter/visualizers/RenderAsXPath.java | 1 + .../jmeter/visualizers/RenderAsXPath2.java | 1 + .../jmeter/visualizers/SamplerResultTab.java | 1 + .../ViewResultsFullVisualizer.java | 23 +++ .../org/apache/jorphan/util/StringWrap.java | 166 ++++++++++++++++++ .../apache/jorphan/util/StringWrapTest.java | 61 +++++++ xdocs/changes.xml | 1 + xdocs/usermanual/properties_reference.xml | 12 ++ 12 files changed, 276 insertions(+) create mode 100644 src/jorphan/src/main/java/org/apache/jorphan/util/StringWrap.java create mode 100644 src/jorphan/src/test/java/org/apache/jorphan/util/StringWrapTest.java diff --git a/bin/jmeter.properties b/bin/jmeter.properties index 447b3649f0e..c77877efa6e 100644 --- a/bin/jmeter.properties +++ b/bin/jmeter.properties @@ -1180,6 +1180,13 @@ cookies=cookies # Set to 0 to disable the size check and display the whole response #view.results.tree.max_size=10485760 +# UI gets unresponsive when response contains very long lines, +# So we break lines by adding artificial line breaks +# The break is introduced somewhere in between soft_wrap_line_size..max_line_size +# We try to break on word boundaries first +#view.results.tree.max_line_size=110000 +#view.results.tree.soft_wrap_line_size=100000 + # Order of Renderers in View Results Tree # Note full class names should be used for non JMeter core renderers # For JMeter core renderers, class names start with '.' and are automatically diff --git a/src/components/src/main/java/org/apache/jmeter/visualizers/RenderAsBoundaryExtractor.java b/src/components/src/main/java/org/apache/jmeter/visualizers/RenderAsBoundaryExtractor.java index 0af0cdacf17..e48002e246f 100644 --- a/src/components/src/main/java/org/apache/jmeter/visualizers/RenderAsBoundaryExtractor.java +++ b/src/components/src/main/java/org/apache/jmeter/visualizers/RenderAsBoundaryExtractor.java @@ -212,6 +212,7 @@ public void setSamplerResult(Object userObject) { public void renderResult(SampleResult sampleResult) { clearData(); String response = ViewResultsFullVisualizer.getResponseAsString(sampleResult); + response = ViewResultsFullVisualizer.wrapLongLines(response); boundaryExtractorDataField.setText(response); boundaryExtractorDataField.setCaretPosition(0); } diff --git a/src/components/src/main/java/org/apache/jmeter/visualizers/RenderAsCssJQuery.java b/src/components/src/main/java/org/apache/jmeter/visualizers/RenderAsCssJQuery.java index eff86a9be55..e802246feab 100644 --- a/src/components/src/main/java/org/apache/jmeter/visualizers/RenderAsCssJQuery.java +++ b/src/components/src/main/java/org/apache/jmeter/visualizers/RenderAsCssJQuery.java @@ -145,6 +145,7 @@ private String process(String textToParse) { public void renderResult(SampleResult sampleResult) { clearData(); String response = ViewResultsFullVisualizer.getResponseAsString(sampleResult); + response = ViewResultsFullVisualizer.wrapLongLines(response); cssJqueryDataField.setText(response); cssJqueryDataField.setCaretPosition(0); } diff --git a/src/components/src/main/java/org/apache/jmeter/visualizers/RenderAsRegexp.java b/src/components/src/main/java/org/apache/jmeter/visualizers/RenderAsRegexp.java index 66d74fb0021..f598e0a1efa 100644 --- a/src/components/src/main/java/org/apache/jmeter/visualizers/RenderAsRegexp.java +++ b/src/components/src/main/java/org/apache/jmeter/visualizers/RenderAsRegexp.java @@ -143,6 +143,7 @@ private String process(String textToParse) { public void renderResult(SampleResult sampleResult) { clearData(); String response = ViewResultsFullVisualizer.getResponseAsString(sampleResult); + response = ViewResultsFullVisualizer.wrapLongLines(response); regexpDataField.setText(response); regexpDataField.setCaretPosition(0); } diff --git a/src/components/src/main/java/org/apache/jmeter/visualizers/RenderAsXPath.java b/src/components/src/main/java/org/apache/jmeter/visualizers/RenderAsXPath.java index 2399f56db2c..f8e6ea51e8e 100644 --- a/src/components/src/main/java/org/apache/jmeter/visualizers/RenderAsXPath.java +++ b/src/components/src/main/java/org/apache/jmeter/visualizers/RenderAsXPath.java @@ -180,6 +180,7 @@ private Document parseResponse(String unicodeData, XPathExtractor extractor) @Override public void renderResult(SampleResult sampleResult) { String response = ViewResultsFullVisualizer.getResponseAsString(sampleResult); + response = ViewResultsFullVisualizer.wrapLongLines(response); try { xmlDataField.setText(response == null ? "" : response); xmlDataField.setCaretPosition(0); diff --git a/src/components/src/main/java/org/apache/jmeter/visualizers/RenderAsXPath2.java b/src/components/src/main/java/org/apache/jmeter/visualizers/RenderAsXPath2.java index b55ffcbac01..4dd8acf151a 100644 --- a/src/components/src/main/java/org/apache/jmeter/visualizers/RenderAsXPath2.java +++ b/src/components/src/main/java/org/apache/jmeter/visualizers/RenderAsXPath2.java @@ -164,6 +164,7 @@ private String getDocumentNamespaces(String textToParse) { @Override public void renderResult(SampleResult sampleResult) { String response = ViewResultsFullVisualizer.getResponseAsString(sampleResult); + response = ViewResultsFullVisualizer.wrapLongLines(response); try { xmlDataField.setText(response == null ? "" : response); xmlDataField.setCaretPosition(0); diff --git a/src/components/src/main/java/org/apache/jmeter/visualizers/SamplerResultTab.java b/src/components/src/main/java/org/apache/jmeter/visualizers/SamplerResultTab.java index 3828c2a571d..f6d17f6e2a9 100644 --- a/src/components/src/main/java/org/apache/jmeter/visualizers/SamplerResultTab.java +++ b/src/components/src/main/java/org/apache/jmeter/visualizers/SamplerResultTab.java @@ -688,6 +688,7 @@ protected void setTextOptimized(String data) { Document blank = new DefaultStyledDocument(); results.setDocument(blank); try { + data = ViewResultsFullVisualizer.wrapLongLines(data); document.insertString(0, data == null ? "" : data, null); } catch (BadLocationException ex) { LOGGER.error("Error inserting text", ex); diff --git a/src/components/src/main/java/org/apache/jmeter/visualizers/ViewResultsFullVisualizer.java b/src/components/src/main/java/org/apache/jmeter/visualizers/ViewResultsFullVisualizer.java index d4520d55820..3a549ba9c1e 100644 --- a/src/components/src/main/java/org/apache/jmeter/visualizers/ViewResultsFullVisualizer.java +++ b/src/components/src/main/java/org/apache/jmeter/visualizers/ViewResultsFullVisualizer.java @@ -74,6 +74,8 @@ import org.apache.jmeter.util.JMeterUtils; import org.apache.jmeter.visualizers.gui.AbstractVisualizer; import org.apache.jorphan.gui.JMeterUIDefaults; +import org.apache.jorphan.util.StringWrap; +import org.apiguardian.api.API; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -103,6 +105,14 @@ public class ViewResultsFullVisualizer extends AbstractVisualizer private static final int MAX_DISPLAY_SIZE = JMeterUtils.getPropDefault("view.results.tree.max_size", 10485760); // $NON-NLS-1$ + // Default limited to 110K + private static final int MAX_LINE_SIZE = + JMeterUtils.getPropDefault("view.results.tree.max_line_size", 110000); // $NON-NLS-1$ + + // Limit the soft wrap to 100K (hard limit divided by 1.1) + private static final int SOFT_WRAP_LINE_SIZE = + JMeterUtils.getPropDefault("view.results.tree.soft_wrap_line_size", (int) (MAX_LINE_SIZE / 1.1f)); // $NON-NLS-1$ + // default display order private static final String VIEWERS_ORDER = JMeterUtils.getPropDefault("view.results.tree.renderers_order", ""); // $NON-NLS-1$ //$NON-NLS-2$ @@ -563,6 +573,19 @@ public static String getResponseAsString(SampleResult res) { return response; } + @API(status = API.Status.INTERNAL, since = "5.5") + public static String wrapLongLines(String input) { + if (input == null || input.isEmpty()) { + return input; + } + if (SOFT_WRAP_LINE_SIZE > 0 && MAX_LINE_SIZE > 0) { + StringWrap stringWrap = new StringWrap(SOFT_WRAP_LINE_SIZE, MAX_LINE_SIZE); + return stringWrap.wrap(input, "\n"); + } + return input; + } + + private static class ResultsNodeRenderer extends DefaultTreeCellRenderer { private static final long serialVersionUID = 4159626601097711565L; diff --git a/src/jorphan/src/main/java/org/apache/jorphan/util/StringWrap.java b/src/jorphan/src/main/java/org/apache/jorphan/util/StringWrap.java new file mode 100644 index 00000000000..b36f66ad490 --- /dev/null +++ b/src/jorphan/src/main/java/org/apache/jorphan/util/StringWrap.java @@ -0,0 +1,166 @@ +/* + * 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.jorphan.util; + +import java.text.BreakIterator; + +import org.apiguardian.api.API; + +/** + * Wraps text in such a way so the lines do not exceed given maximum length. + */ +@API(since = "5.5", status = API.Status.EXPERIMENTAL) +public class StringWrap { + private final int minWrap; + private final int maxWrap; + + private final BreakCursor wordCursor = new BreakCursor(BreakIterator.getLineInstance()); + private final BreakCursor charCursor = new BreakCursor(BreakIterator.getCharacterInstance()); + + /** + * Stores the current and the next position for a given {@link BreakIterator}. + * It allows reducing the number of calls to {@link BreakIterator}. + */ + private static class BreakCursor { + private static final int UNINITIALIZED = -2; + + private final BreakIterator iterator; + private int pos; + private int next; + + BreakCursor(BreakIterator iterator) { + this.iterator = iterator; + } + + void setText(String text) { + iterator.setText(text); + pos = 0; + next = UNINITIALIZED; + } + + public int getPos() { + return pos; + } + + /** + * Advances the cursor if possible. + * @param startWrap the start index of the wrap to consider + * @param endWrap the end index of the wrap to consider + * @return true if the next break is detected within startWrap..endWrap boundaries + */ + public boolean advance(int startWrap, int endWrap) { + if (pos == BreakIterator.DONE || pos > endWrap) { + return false; + } + pos = next != UNINITIALIZED ? next : iterator.following(startWrap); + if (pos == BreakIterator.DONE || pos > endWrap) { + return false; + } + // Try adding more items up to endWrap + while (true) { + next = iterator.next(); + if (next == BreakIterator.DONE || next > endWrap) { + break; + } + pos = next; + } + return true; + } + } + + /** + * Creates string wrapper instance. + * + * @param minWrap minimal word length for the wrap + * @param maxWrap maximum word length for the wrap + */ + public StringWrap(int minWrap, int maxWrap) { + this.minWrap = minWrap; + this.maxWrap = maxWrap; + } + + public int getMinWrap() { + return minWrap; + } + + public int getMaxWrap() { + return maxWrap; + } + + /** + * Wraps given {@code input} text accoding to + * + * @param input input text + * @param delimiter delimiter when inserting soft wraps + * @return modified text with added soft wraps, or input if wraps are not needed + */ + public String wrap(String input, String delimiter) { + if (input.length() <= minWrap) { + return input; + } + wordCursor.setText(input); + charCursor.setText(input); + int pos = 0; + StringBuilder sb = new StringBuilder(input.length() + input.length() / minWrap * delimiter.length()); + boolean hasChanges = false; + int nextLineSeparator = BreakCursor.UNINITIALIZED; + // Wrap long lines + while (input.length() - pos > maxWrap) { + if (nextLineSeparator != BreakIterator.DONE && nextLineSeparator < pos) { + nextLineSeparator = input.indexOf('\n', pos); + } + // Try adding the next line if it does not exceed maxWrap + int next = nextLineSeparator; + if (next != -1 && pos - next <= maxWrap) { + // The existing lines do not exceed maxWrap, just reuse them + next++; // include newline + sb.append(input, pos, next); + pos = next; + continue; + } + int startWrap = pos + minWrap - 1; + int endWrap = pos + maxWrap; + // Try breaking on word boundaries first + if (wordCursor.advance(startWrap, endWrap)) { + next = wordCursor.getPos(); + } else { + // If char advances at least once, add it with the break even if it exceeds maxWrap + // Note: single "char break" might consume multiple Java chars in case like emojis. + charCursor.advance(startWrap, endWrap); + next = charCursor.getPos(); + if (next == BreakIterator.DONE || next == input.length()) { + break; + } + } + sb.append(input, pos, next); + sb.append(delimiter); + hasChanges = true; + pos = next; + } + // Free up the memory + wordCursor.setText(""); + charCursor.setText(""); + if (!hasChanges) { + return input; + } + if (pos != input.length()) { + sb.append(input, pos, input.length()); + } + return sb.toString(); + } +} diff --git a/src/jorphan/src/test/java/org/apache/jorphan/util/StringWrapTest.java b/src/jorphan/src/test/java/org/apache/jorphan/util/StringWrapTest.java new file mode 100644 index 00000000000..12b19e3809b --- /dev/null +++ b/src/jorphan/src/test/java/org/apache/jorphan/util/StringWrapTest.java @@ -0,0 +1,61 @@ +/* + * 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.jorphan.util; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.params.provider.Arguments.arguments; + +import java.util.stream.Stream; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +public class StringWrapTest { + static Stream data() { + return Stream.of( + arguments(2, 2, "0123456789", "01|23|45|67|89"), + arguments(2, 5, "0123456789", "01234|56789"), + arguments(3, 3, "0123456789", "012|345|678|9"), + arguments(2, 5, "01-2-3-4-56-789-", "01-2-|3-4-|56-|789-"), + arguments(2, 5, "012\n345\n6\n7\n8\n9", null), + arguments(2, 5, "012\n3456789", "012\n34567|89"), + // Single-char symbols + arguments(2, 5, "丈丈丈丈丈a丈丈a 丈丈丈 b 丈丈", "丈丈丈丈丈|a丈丈a |丈丈丈 |b 丈丈"), + // Two-char symbols + arguments(2, 5, "निनिनिनिनिनिनdनिनिनिनि3निनिनिनिनिनि1 नि", "निनि|निनि|निनिन|dनिनि|निनि3|निनि|निनि|निनि1| नि"), + // Two-char symbols + arguments(2, 5, "😃😃😃😃😃😃😃😃a😃aa😃😃 😃😃 b 😃", "😃😃|😃😃|😃😃|😃😃a|😃aa|😃😃 |😃😃 |b 😃"), + arguments(1, 1, "😃", null), + // Multi-char symbols + arguments(2, 5, "rè̑ͧ̌aͨl̘̝̙̃ͤ͂̾̆rè̑ͧ̌aͨl̘̝̙̃ͤ͂̾̆rè̑ͧ", "rè̑ͧ̌|aͨ|l̘̝̙̃ͤ͂̾̆|r|è̑ͧ̌|aͨ|l̘̝̙̃ͤ͂̾̆|rè̑ͧ"), + arguments(2, 9, "rè̑ͧ̌aͨl̘̝̙̃ͤ͂̾̆rè̑ͧ̌aͨl̘̝̙̃ͤ͂̾̆rè̑ͧ", "rè̑ͧ̌aͨ|l̘̝̙̃ͤ͂̾̆|rè̑ͧ̌aͨ|l̘̝̙̃ͤ͂̾̆|rè̑ͧ") + ); + } + + @ParameterizedTest + @MethodSource("data") + void wrap(int minWrap, int maxWrap, String input, String expected) { + if (expected == null) { + expected = input; + } + StringWrap stringWrap = new StringWrap(minWrap, maxWrap); + String output = stringWrap.wrap(input, "|"); + assertEquals(expected, output, () -> "minWrap=" + minWrap + ", maxWrap=" + maxWrap + ", input=" + input); + } +} diff --git a/xdocs/changes.xml b/xdocs/changes.xml index 2f86ec86bde..1666936dc13 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -143,6 +143,7 @@ however, the profile can't be updated while the test is running.
    • 61805663Add simple HTTP request template. Contributed by Ori Marko (orimarko at gmail.com)
    • 65611673Add support for IPv6 addresses when specifying a remote worker node. Based on a patch by Peter Wong (peter.wong at csexperts.com)
    • Reduce memory consumption by the logging panel (disable undo events for it)
    • +
    • 63620694Fix GUI freeze when viewing response body with long line breaks
    Non-functional changes diff --git a/xdocs/usermanual/properties_reference.xml b/xdocs/usermanual/properties_reference.xml index e373627838d..c4452ecfe26 100644 --- a/xdocs/usermanual/properties_reference.xml +++ b/xdocs/usermanual/properties_reference.xml @@ -1510,6 +1510,18 @@ JMETER-SERVER Set to zero to disable the size check and display the whole response.
    Defaults to: 10485760 + + Maximum size (in characters) of the line in the displayed.
    + This property works around Bug 63620 since Swing hangs when displaying very long lines.
    + Set to zero to disable line wrapping.
    + Defaults to: 110000 +
    + + Line size (in characters) to consider wrapping to make UI faster.
    + This property works around Bug 63620 since Swing hangs when displaying very long lines.
    + Set to zero to disable line wrapping.
    + Defaults to: view.results.tree.max_line_size / 1.1f +
    Order of Renderers in View Results Tree.
    Note full class names should be used for non JMeter core renderers From d4f637130db35cec7993094357290236ffef4497 Mon Sep 17 00:00:00 2001 From: Vladimir Sitnikov Date: Sun, 6 Feb 2022 13:38:49 +0300 Subject: [PATCH 043/736] [Bug 63620] Disable kerning when document lenght exceeds 10K The treshold can be configured via text.kerning.max_document_size --- bin/jmeter.properties | 3 + .../jmeter/visualizers/SamplerResultTab.java | 2 + .../main/java/org/apache/jmeter/JMeter.java | 4 + .../jorphan/gui/ui/KerningOptimizer.java | 200 ++++++++++++++++++ .../jorphan/gui/ui/TextAreaUIWithUndo.java | 1 + xdocs/usermanual/properties_reference.xml | 4 + 6 files changed, 214 insertions(+) create mode 100644 src/jorphan/src/main/java/org/apache/jorphan/gui/ui/KerningOptimizer.java diff --git a/bin/jmeter.properties b/bin/jmeter.properties index c77877efa6e..8996e4f185d 100644 --- a/bin/jmeter.properties +++ b/bin/jmeter.properties @@ -1201,6 +1201,9 @@ view.results.tree.renderers_order=.RenderAsText,.RenderAsRegexp,.RenderAsBoundar # Set to 0 to disable the size check #document.max_size=0 +# Configures the maximum document length for rendering with kerning enabled +#text.kerning.max_document_size=10000 + #JMS options # Enable the following property to stop JMS Point-to-Point Sampler from using # the properties java.naming.security.[principal|credentials] when creating the queue connection diff --git a/src/components/src/main/java/org/apache/jmeter/visualizers/SamplerResultTab.java b/src/components/src/main/java/org/apache/jmeter/visualizers/SamplerResultTab.java index f6d17f6e2a9..5a9afe4fad2 100644 --- a/src/components/src/main/java/org/apache/jmeter/visualizers/SamplerResultTab.java +++ b/src/components/src/main/java/org/apache/jmeter/visualizers/SamplerResultTab.java @@ -61,6 +61,7 @@ import org.apache.jorphan.gui.GuiUtils; import org.apache.jorphan.gui.ObjectTableModel; import org.apache.jorphan.gui.RendererUtils; +import org.apache.jorphan.gui.ui.KerningOptimizer; import org.apache.jorphan.reflect.Functor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -693,6 +694,7 @@ protected void setTextOptimized(String data) { } catch (BadLocationException ex) { LOGGER.error("Error inserting text", ex); } + KerningOptimizer.INSTANCE.configureKerning(results, document.getLength()); results.setDocument(document); } } diff --git a/src/core/src/main/java/org/apache/jmeter/JMeter.java b/src/core/src/main/java/org/apache/jmeter/JMeter.java index 83a62020036..e5dffc61a99 100644 --- a/src/core/src/main/java/org/apache/jmeter/JMeter.java +++ b/src/core/src/main/java/org/apache/jmeter/JMeter.java @@ -105,6 +105,7 @@ import org.apache.jorphan.collections.SearchByClass; import org.apache.jorphan.gui.ComponentUtil; import org.apache.jorphan.gui.JMeterUIDefaults; +import org.apache.jorphan.gui.ui.KerningOptimizer; import org.apache.jorphan.reflect.ClassTools; import org.apache.jorphan.util.HeapDumper; import org.apache.jorphan.util.JMeterException; @@ -374,6 +375,9 @@ private void startGui(String testFile) { System.out.println("Check : https://jmeter.apache.org/usermanual/best-practices.html");//NOSONAR System.out.println("================================================================================");//NOSONAR + KerningOptimizer.INSTANCE.setMaxTextLengthWithKerning( + JMeterUtils.getPropDefault("text.kerning.max_document_size", 10000) + ); JMeterUIDefaults.INSTANCE.install(); String jMeterLaf = LookAndFeelCommand.getPreferredLafCommand(); diff --git a/src/jorphan/src/main/java/org/apache/jorphan/gui/ui/KerningOptimizer.java b/src/jorphan/src/main/java/org/apache/jorphan/gui/ui/KerningOptimizer.java new file mode 100644 index 00000000000..a414cae47d5 --- /dev/null +++ b/src/jorphan/src/main/java/org/apache/jorphan/gui/ui/KerningOptimizer.java @@ -0,0 +1,200 @@ +/* + * 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.jorphan.gui.ui; + +import java.awt.Font; +import java.awt.font.TextAttribute; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.lang.ref.WeakReference; +import java.util.Collections; + +import javax.swing.JComponent; +import javax.swing.SwingUtilities; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.text.Document; +import javax.swing.text.JTextComponent; + +import org.apiguardian.api.API; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Text rendering might be slow for long lines when kerning is enabled, so it is worth disabling kerning for long + * texts. + */ +@API(since = "5.5", status = API.Status.INTERNAL) +public class KerningOptimizer { + private final static Logger log = LoggerFactory.getLogger(KerningOptimizer.class); + + public static final KerningOptimizer INSTANCE = new KerningOptimizer(); + + private volatile int maxLengthWithKerning = 10000; + + /** + * Cache to avoid repeated calls to {@link Font#getAttributes()} since it copies the map every time. + */ + static class FontKerningCache { + private static final String CLIENT_PROPERTY_KEY = "[jmeter]FontKerningCache"; + WeakReference font; + boolean kerning; + + static Boolean kerningOf(JComponent component) { + Font font = component.getFont(); + if (font == null) { + return null; + } + if (!font.hasLayoutAttributes()) { + return false; + } + FontKerningCache cache = (FontKerningCache) component.getClientProperty(CLIENT_PROPERTY_KEY); + if (cache == null) { + cache = new FontKerningCache(); + component.putClientProperty(CLIENT_PROPERTY_KEY, cache); + } + if (cache.font == null || !font.equals(cache.font.get())) { + cache.font = new WeakReference<>(font); + cache.kerning = TextAttribute.KERNING_ON.equals(font.getAttributes().get(TextAttribute.KERNING)); + } + return cache.kerning; + } + } + + /** + * Configures the maximum document length for rendering with kerning enabled. + * + * @param length maximum document length for rendering with kerning enabled + */ + public void setMaxTextLengthWithKerning(int length) { + maxLengthWithKerning = length; + } + + public int getMaxTextLengthWithKerning() { + return maxLengthWithKerning; + } + + /** + * Configures text kerning according to the expected document length. This might be useful before setting the + * document so the kerning is disabled before updating the document. + * + * @param component text component for kerning configuration + * @param documentLength expected document length + */ + public void configureKerning(JComponent component, int documentLength) { + Boolean kerning = FontKerningCache.kerningOf(component); + if (kerning == null) { + return; + } + boolean desiredKerning = documentLength <= maxLengthWithKerning; + if (kerning != desiredKerning) { + if (log.isDebugEnabled()) { + log.info("Updating kerning (old: {}, new: {}), documentLength={}, component {}, ", kerning, desiredKerning, documentLength, component); + } + Font font = component.getFont(); + Font newFont = font.deriveFont(Collections.singletonMap(TextAttribute.KERNING, desiredKerning ? TextAttribute.KERNING_ON : 0)); + SwingUtilities.invokeLater(() -> component.setFont(newFont)); + } + } + + /** + * Adds a listener that disables kerning if text length reaches a certain threshold. + * + * @param textComponent text component for kerning configuration + */ + public void installKerningListener(JTextComponent textComponent) { + log.debug("Installing KerningOptimizer {} to {}", this, textComponent); + textComponent.addPropertyChangeListener("document", new DisableKerningForLargeTexts(textComponent)); + } + + /** + * Removes the listener that disables kerning if text length reaches a certain threshold. + * + * @param textComponent text component for kerning configuration + */ + public void uninstallKerningListener(JTextComponent textComponent) { + DisableKerningForLargeTexts kerningListener = null; + for (PropertyChangeListener listener : textComponent.getPropertyChangeListeners("document")) { + if (listener instanceof DisableKerningForLargeTexts) { + kerningListener = (DisableKerningForLargeTexts) listener; + } + } + if (kerningListener == null) { + return; + } + log.debug("Uninstalling KerningOptimizer {} from {}", this, textComponent); + Document document = textComponent.getDocument(); + if (document != null) { + document.removeDocumentListener(kerningListener); + } + textComponent.removePropertyChangeListener("document", kerningListener); + } + + static class DisableKerningForLargeTexts implements PropertyChangeListener, DocumentListener { + final JTextComponent component; + + DisableKerningForLargeTexts(JTextComponent component) { + this.component = component; + } + + private void configureKerning(Document e) { + // RSyntaxTextArea and other implementations do not expect setFont called from document change listeners + // It looks like invokeLater fixes that + Boolean kerning = FontKerningCache.kerningOf(component); + if (kerning == null) { + return; + } + boolean desiredKerning = e.getLength() <= INSTANCE.getMaxTextLengthWithKerning(); + if (kerning != desiredKerning) { + SwingUtilities.invokeLater(() -> INSTANCE.configureKerning(component, e.getLength())); + } + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (!"document".equals(evt.getPropertyName())) { + return; + } + Document oldDocument = (Document) evt.getOldValue(); + if (oldDocument != null) { + oldDocument.removeDocumentListener(this); + } + Document newDocument = (Document) evt.getNewValue(); + if (newDocument != null) { + newDocument.addDocumentListener(this); + configureKerning(newDocument); + } + } + + + @Override + public void insertUpdate(DocumentEvent e) { + configureKerning(e.getDocument()); + } + + @Override + public void removeUpdate(DocumentEvent e) { + configureKerning(e.getDocument()); + } + + @Override + public void changedUpdate(DocumentEvent e) { + configureKerning(e.getDocument()); + } + } +} diff --git a/src/jorphan/src/main/java/org/apache/jorphan/gui/ui/TextAreaUIWithUndo.java b/src/jorphan/src/main/java/org/apache/jorphan/gui/ui/TextAreaUIWithUndo.java index 75dd190a058..8cc94e061f6 100644 --- a/src/jorphan/src/main/java/org/apache/jorphan/gui/ui/TextAreaUIWithUndo.java +++ b/src/jorphan/src/main/java/org/apache/jorphan/gui/ui/TextAreaUIWithUndo.java @@ -60,6 +60,7 @@ public static void install(UIDefaults defaults) { */ @SuppressWarnings("unused") public static ComponentUI createUI(JComponent component) { + KerningOptimizer.INSTANCE.installKerningListener((JTextComponent) component); TextComponentUI.INSTANCE.installUndo((JTextComponent) component); if (component.getClass() == JTextArea.class) { component.addPropertyChangeListener("UI", diff --git a/xdocs/usermanual/properties_reference.xml b/xdocs/usermanual/properties_reference.xml index c4452ecfe26..fb53cd2e1e2 100644 --- a/xdocs/usermanual/properties_reference.xml +++ b/xdocs/usermanual/properties_reference.xml @@ -1535,6 +1535,10 @@ JMETER-SERVER Set to zero to disable the size check.
    Defaults to: 10485760
    + + Configures the maximum document length for rendering with kerning enabled.
    + Defaults to: 10000 +
    JMS options.
    Enable the following property to stop JMS Point-to-Point Sampler from using From 8546e2372ac08eecc27f56a5bfc24a6c4ecc7135 Mon Sep 17 00:00:00 2001 From: pmouawad Date: Tue, 15 Feb 2022 23:09:16 +0100 Subject: [PATCH 044/736] Bug 65885 - HTML Report: Error report displays wrong failure message when Response Assertion checks Ignore Status and response code is not 200 --- .../report/processor/ErrorsSummaryConsumer.java | 9 ++++++--- .../report/processor/ErrorsSummaryConsumerTest.java | 13 +++++++++++-- xdocs/changes.xml | 1 + 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/core/src/main/java/org/apache/jmeter/report/processor/ErrorsSummaryConsumer.java b/src/core/src/main/java/org/apache/jmeter/report/processor/ErrorsSummaryConsumer.java index f0175730aaf..3b8d3b5ae92 100644 --- a/src/core/src/main/java/org/apache/jmeter/report/processor/ErrorsSummaryConsumer.java +++ b/src/core/src/main/java/org/apache/jmeter/report/processor/ErrorsSummaryConsumer.java @@ -88,17 +88,20 @@ protected String getKeyFromSample(Sample sample) { * @return String Error key for sample */ static String getErrorKey(Sample sample) { + if (sample.getSuccess()) { + return ""; + } String responseCode = sample.getResponseCode(); String responseMessage = sample.getResponseMessage(); String key = responseCode + (!StringUtils.isEmpty(responseMessage) ? "/" + escapeJson(responseMessage) : ""); + if (MetricUtils.isSuccessCode(responseCode) || - (StringUtils.isEmpty(responseCode) && - !StringUtils.isEmpty(sample.getFailureMessage()))) { + StringUtils.isNotBlank(sample.getFailureMessage())) { key = MetricUtils.ASSERTION_FAILED; if (ASSERTION_RESULTS_FAILURE_MESSAGE) { String msg = sample.getFailureMessage(); - if (!StringUtils.isEmpty(msg)) { + if (StringUtils.isNotBlank(msg)) { key = escapeJson(msg); } } diff --git a/src/core/src/test/java/org/apache/jmeter/report/processor/ErrorsSummaryConsumerTest.java b/src/core/src/test/java/org/apache/jmeter/report/processor/ErrorsSummaryConsumerTest.java index ab43b8e964f..9a41be978e4 100644 --- a/src/core/src/test/java/org/apache/jmeter/report/processor/ErrorsSummaryConsumerTest.java +++ b/src/core/src/test/java/org/apache/jmeter/report/processor/ErrorsSummaryConsumerTest.java @@ -38,6 +38,9 @@ public void testGetErrorKey() { sample = new Sample(0, metadata, new String[] { "false", "200", "", "FailureMessage" }); assertEquals("FailureMessage", ErrorsSummaryConsumer.getErrorKey(sample)); + sample = new Sample(0, metadata, new String[] { "false", "200", "", "" }); + assertEquals(MetricUtils.ASSERTION_FAILED, ErrorsSummaryConsumer.getErrorKey(sample)); + sample = new Sample(0, metadata, new String[] { "false", "200", "", "Test failed: text expected to contain /Some html text/" }); assertEquals("Test failed: text expected to contain /<title>Some html text</title>/", @@ -49,9 +52,15 @@ public void testGetErrorKey() { ErrorsSummaryConsumer.getErrorKey(sample)); sample = new Sample(0, metadata, new String[] { "true", "200", "", "" }); - assertEquals(MetricUtils.ASSERTION_FAILED, ErrorsSummaryConsumer.getErrorKey(sample)); + assertEquals("", ErrorsSummaryConsumer.getErrorKey(sample)); + + sample = new Sample(0, metadata, new String[] { "false", "403", "", "" }); + assertEquals("403", ErrorsSummaryConsumer.getErrorKey(sample)); + + sample = new Sample(0, metadata, new String[] { "false", "403", "", "FailureMessage" }); + assertEquals("FailureMessage", ErrorsSummaryConsumer.getErrorKey(sample)); - sample = new Sample(0, metadata, new String[] { "false", "500", "Server Error", "FailureMessage" }); + sample = new Sample(0, metadata, new String[] { "false", "500", "Server Error", "" }); assertEquals("500/Server Error", ErrorsSummaryConsumer.getErrorKey(sample)); } diff --git a/xdocs/changes.xml b/xdocs/changes.xml index 1666936dc13..ced05b19f21 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -136,6 +136,7 @@ however, the profile can't be updated while the test is running.

    Report / Dashboard

    • 65353Make the estimator used for calculating percentiles on the dashboard configurable
    • +
    • 65885HTML Report: Error report displays wrong failure message when Response Assertion checks Ignore Status and response code is not 200

    General

    From efe50ca5b150cdbdb578886f8b4d98d3f1ea264f Mon Sep 17 00:00:00 2001 From: sseide Date: Wed, 16 Feb 2022 13:39:36 +0100 Subject: [PATCH 045/736] update tika-parsers to 1.28.1 (from 1.28) and xstreams to 1.4.19 (from 1.4.18) (#698) * update tika-parsers to 1.28.1 (from 1.28) and xstreams to 1.4.19 (from 1.4.18) * update xercesImpl to 2.12.2 (from 2.12.1) and add new gpg key from xerces maintainer (ref XERCESJ-1735) * add pr number to changes.xml * update expected_release_jars.csv --- checksum.xml | 1 + gradle.properties | 6 +++--- src/dist/src/dist/expected_release_jars.csv | 8 ++++---- xdocs/changes.xml | 7 +++---- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/checksum.xml b/checksum.xml index c335c72277a..c860213a819 100644 --- a/checksum.xml +++ b/checksum.xml @@ -198,6 +198,7 @@ + diff --git a/gradle.properties b/gradle.properties index 23207fddbef..376c3298fd6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -132,12 +132,12 @@ slf4j.version=1.7.32 spock-core.version=2.0-M2-groovy-3.0 springframework.version=4.3.17.RELEASE svgSalamander.version=1.1.2.4 -tika.version=1.28 +tika.version=1.28.1 xalan.version=2.7.2 -xercesImpl.version=2.12.1 +xercesImpl.version=2.12.2 xml-apis.version=1.4.01 xmlgraphics-commons.version=2.6 xmlpull.version=1.1.3.1 xpp3_min.version=1.1.4c -xstream.version=1.4.18 +xstream.version=1.4.19 wiremock-jre8.version=2.30.0 diff --git a/src/dist/src/dist/expected_release_jars.csv b/src/dist/src/dist/expected_release_jars.csv index a43c8d348bf..9caa9b8281f 100644 --- a/src/dist/src/dist/expected_release_jars.csv +++ b/src/dist/src/dist/expected_release_jars.csv @@ -121,13 +121,13 @@ 301279,svgSalamander-1.1.2.4.jar 10192,swing-extensions-laf-support-0.1.3.jar 2539,swing-extensions-visual-padding-0.1.3.jar -735635,tika-core-1.28.jar -1585374,tika-parsers-1.28.jar +735645,tika-core-1.28.1.jar +1585382,tika-parsers-1.28.1.jar 174661,vis-svg-portable-jvm-2.2.1.jar 3154938,xalan-2.7.2.jar -1386502,xercesImpl-2.12.1.jar +1446149,xercesImpl-2.12.2.jar 220536,xml-apis-1.4.01.jar 85686,xml-apis-ext-1.3.04.jar 674607,xmlgraphics-commons-2.6.jar 7188,xmlpull-1.1.3.1.jar -629707,xstream-1.4.18.jar +633140,xstream-1.4.19.jar diff --git a/xdocs/changes.xml b/xdocs/changes.xml index ced05b19f21..44a09ceef70 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -152,7 +152,7 @@ however, the profile can't be updated while the test is running.
  • Added Kotlin 1.6.0 for JMeter engine implementation (apiVersion=1.5). The set of JSR 223 languages is intact.
  • 65128643Add missing documentation about Same user on each iteration for Thread Groups. Contributed by njkuzas.
  • 648Updated xmlgraphics-commons to 2.6 (from 2.3). Contributed by Stefan Seide (stefan at trilobyte-se.de)
  • -
  • 655667675Updated x-stream to 1.4.18 (from 1.4.15). Contributed by Stefan Seide (stefan at trilobyte-se.de)
  • +
  • 655667675698Updated x-stream to 1.4.19 (from 1.4.15). Contributed by Stefan Seide (stefan at trilobyte-se.de)
  • 656668Updated json-smart to 2.4.7 (from 2.3), accessors-smart to 2.4.7 (from 1.2) and asm 9.1 (from 9.0). Contributed by Stefan Seide (stefan at trilobyte-se.de)
  • 64831Log truststore entries in debug level for logger org.apache.jmeter.util.keystore.JmeterKeyStore
  • 65232Hide splash screen when an error is displayed because the test plan could not be parsed.
  • @@ -185,7 +185,7 @@ however, the profile can't be updated while the test is running.
  • Updated RSyntaxTextArea to 3.1.3 (from 3.1.1).
  • Updated SLF4J to 1.7.32 (from 1.7.30).
  • Updated SvgSalamander to 1.1.2.4 (from 1.1.2.1).
  • -
  • Updated Apache Tika to 1.28 (from 1.26).
  • +
  • 698Updated Apache Tika to 1.28.1 (from 1.26).
  • Updated WireMock-JRE8 to 2.30.0 (from 2.24.1).
  • Updated com.github.vlsi.vlsi-release-plugins 1.76 (from 1.74).
  • Updated jackson to 2.13.1 (from 2.10.5)
  • @@ -263,10 +263,9 @@ however, the profile can't be updated while the test is running.

    General

    • 64318DNS Cache Manager - custom DNS resolver does not use system resolver by default
    • -
    • 641Updated xercesImpl to 2.12.1 (from 2.12.0). Based on patch by Stefan Seide (stefan at trilobyte-se.de).
    • +
    • 641698Updated xercesImpl to 2.12.2 (from 2.12.0). Based on patch by Stefan Seide (stefan at trilobyte-se.de).
    • 645Add escaping for new lines in AbstractInfluxdbMetricsSender. Contributed by David Getzlaff (david.getzlaff at t-systems.com>)
    • 65198Can't copy generated function from FunctionHelper
    • -
    • Updated Apache Tika to 1.26 (from 1.24.1)
    • 658Improve javadoc. Contributed by Ori Marko (orimarko at gmail.com)
    • 661Fix wording in doc. Contributed by BugKing (wangzhen at fit2cloud.com)
    • 664Allow whitespace in path. Contributed by Till Neunast (github.com/tilln)
    • From 33ad9306b2fbe823fd9fd1bd207262cd7a0ec4a6 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Wed, 16 Feb 2022 21:54:44 +0100 Subject: [PATCH 046/736] Allow unquoted tokens for values in content-disposition header Use httpcomponents BasicHeaderValueParser instead of our simple parser, as we were assuming parameters would always be surrounded by quotes. Bugzilla Id: 65884 --- .../http/config/MultipartUrlConfig.java | 47 ++++++++--- .../http/config/MultipartUrlConfigTest.java | 82 ++++++++++++++++++- xdocs/changes.xml | 1 + 3 files changed, 114 insertions(+), 16 deletions(-) diff --git a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/config/MultipartUrlConfig.java b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/config/MultipartUrlConfig.java index e420fdefbd8..f4eeae90d16 100644 --- a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/config/MultipartUrlConfig.java +++ b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/config/MultipartUrlConfig.java @@ -20,6 +20,10 @@ import java.io.Serializable; import org.apache.commons.lang3.StringUtils; +import org.apache.http.HeaderElement; +import org.apache.http.NameValuePair; +import org.apache.http.ParseException; +import org.apache.http.message.BasicHeaderValueParser; import org.apache.jmeter.config.Arguments; import org.apache.jmeter.protocol.http.util.HTTPArgument; import org.apache.jmeter.protocol.http.util.HTTPFileArgs; @@ -28,6 +32,8 @@ import org.apache.oro.text.regex.Pattern; import org.apache.oro.text.regex.Perl5Compiler; import org.apache.oro.text.regex.Perl5Matcher; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Configuration element which handles HTTP Parameters and files to be uploaded @@ -46,6 +52,8 @@ public class MultipartUrlConfig implements Serializable { private final Arguments args; + private static final Logger log = LoggerFactory.getLogger(MultipartUrlConfig.class); + /** * HTTPFileArgs list to be uploaded with http request. */ @@ -129,20 +137,25 @@ public void parseArguments(String queryString) { // Check if it is form data if (contentDisposition != null && contentDisposition.contains("form-data")) { //$NON-NLS-1$ // Get the form field name - final String namePrefix = "name=\""; //$NON-NLS-1$ - int index = contentDisposition.indexOf(namePrefix) + namePrefix.length(); - String name = contentDisposition.substring(index, contentDisposition.indexOf('\"', index)); //$NON-NLS-1$ - - // Check if it is a file being uploaded - final String filenamePrefix = "filename=\""; //$NON-NLS-1$ - if (contentDisposition.contains(filenamePrefix)) { - // Get the filename - index = contentDisposition.indexOf(filenamePrefix) + filenamePrefix.length(); - String path = contentDisposition.substring(index, contentDisposition.indexOf('\"', index)); //$NON-NLS-1$ - if (path != null && path.length() > 0) { - // Set the values retrieved for the file upload - files.addHTTPFileArg(path, name, contentType); + HeaderElement[] headerElements = null; + try { + headerElements = BasicHeaderValueParser.parseElements( + contentDisposition, + BasicHeaderValueParser.INSTANCE); + } catch (ParseException e) { + log.info("Can't parse header {}", contentDisposition, e); + } + String name = ""; + String path = null; + if (headerElements != null) { + for (HeaderElement element : headerElements) { + name = getParameterValue(element, "name", ""); + path = getParameterValue(element, "filename", null); } + } + if (path != null && !path.isEmpty()) { + // Set the values retrieved for the file upload + files.addHTTPFileArg(path, name, contentType); } else { // Find the first empty line of the multipart, it signals end of headers for multipart // Agents are supposed to terminate lines in CRLF: @@ -160,6 +173,14 @@ public void parseArguments(String queryString) { } } + private static String getParameterValue(HeaderElement element, String name, String defaultValue) { + NameValuePair parameter = element.getParameterByName(name); + if (parameter == null) { + return defaultValue; + } + return parameter.getValue(); + } + private static String getHeaderValue(String headerName, String multiPart) { String regularExpression = headerName + "\\s*:\\s*(.*)$"; //$NON-NLS-1$ Perl5Matcher localMatcher = JMeterUtils.getMatcher(); diff --git a/src/protocol/http/src/test/java/org/apache/jmeter/protocol/http/config/MultipartUrlConfigTest.java b/src/protocol/http/src/test/java/org/apache/jmeter/protocol/http/config/MultipartUrlConfigTest.java index 214d3eca52a..e31cebe27f0 100644 --- a/src/protocol/http/src/test/java/org/apache/jmeter/protocol/http/config/MultipartUrlConfigTest.java +++ b/src/protocol/http/src/test/java/org/apache/jmeter/protocol/http/config/MultipartUrlConfigTest.java @@ -19,17 +19,24 @@ import static org.junit.Assert.assertEquals; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Stream; + import org.apache.jmeter.config.Argument; import org.apache.jmeter.config.Arguments; import org.apache.jmeter.protocol.http.util.HTTPFileArg; import org.apache.jmeter.protocol.http.util.HTTPFileArgs; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; public class MultipartUrlConfigTest { @Test @SuppressWarnings("deprecation") - public void testConstructors() { + void testConstructors() { MultipartUrlConfig muc = new MultipartUrlConfig(); assertEquals(0, muc.getArguments().getArgumentCount()); assertEquals(0, muc.getHTTPFileArgs().getHTTPFileArgCount()); @@ -41,7 +48,7 @@ public void testConstructors() { // TODO - should LF-only EOL be allowed? @Test - public void testParseArgumentsLF() { + void testParseArgumentsLF() { String queryString = "Content-Disposition: form-data; name=\"aa\"\n" + "Content-Type: text/plain; charset=ISO-8859-1\n" @@ -90,7 +97,7 @@ public void testParseArgumentsLF() { } @Test - public void testParseArgumentsCRLF() { + void testParseArgumentsCRLF() { String queryString = "Content-Disposition: form-data; name=\"aa\"\r\n" + "Content-Type: text/plain; charset=ISO-8859-1\r\n" @@ -137,4 +144,73 @@ public void testParseArgumentsCRLF() { assertEquals("abc", arg.getName()); assertEquals("xyz \r\nxyz ", arg.getValue()); } + + private static Stream quotedMultiPartArgs() { + String boundary = "7d159c1302d0y0"; + HTTPFileArgs fileArgs = new HTTPFileArgs(); + List args = new ArrayList<>(); + List queryLines = new ArrayList<>(); + int counter = 1; + for (boolean quoteName: Arrays.asList(true, false)) { + String paramName = "abc" + counter; + counter++; + String quoteStringName = quoteName ? '"' + paramName + '"' : paramName; + String value = "some value for " + paramName; + queryLines.add(String.format("Content-Disposition: form-data; name=%s", quoteStringName)); + queryLines.add("Content-Type: text/plain; charset=ISO-8859-1"); + queryLines.add("Content-Transfer-Encoding: 8bit"); + queryLines.add(""); + queryLines.add(value); + queryLines.add("--" + boundary); + args.add(new Argument(paramName, value)); + for (boolean quoteFilename: Arrays.asList(true, false)) { + String filenameName = "def" + counter; + counter++; + String quoteStringFile = quoteFilename ? '"' +filenameName + '"' : filenameName ; + String content = "some value for " + paramName + " and " + filenameName ; + queryLines.add(String.format("Content-Disposition: form-data; name=%s; filename=%s", + quoteStringName, + quoteStringFile + )); + queryLines.add("Content-Type: text/plain"); + queryLines.add("Content-Transfer-Encoding: binary"); + queryLines.add(""); + queryLines.add(content); + queryLines.add(""); + queryLines.add("--" + boundary); + fileArgs.addHTTPFileArg(filenameName, paramName, "text/plain"); + } + } + queryLines.remove(queryLines.size()-1); + queryLines.add(""); + return Stream.of( + org.junit.jupiter.params.provider.Arguments.of( + boundary, String.join("\n", queryLines), fileArgs, args), + org.junit.jupiter.params.provider.Arguments.of( + boundary, String.join("\r\n", queryLines), fileArgs, args)); + } + + @ParameterizedTest() + @MethodSource("quotedMultiPartArgs") + void testParseArgumentsQuotingStyle(String boundary, String queryString, HTTPFileArgs expectedFiles, List expectedArgs) { + MultipartUrlConfig muc = new MultipartUrlConfig(boundary); + muc.parseArguments(queryString); + HTTPFileArgs files = muc.getHTTPFileArgs(); + assertEquals(expectedFiles.getHTTPFileArgCount(), files.getHTTPFileArgCount()); + for (int i=0; i
    • 64962Save CSV sub-results recursively from View Results Tree
    • 65784No Graphs displayed in Aggregate Report/Response Time Graph
    • +
    • 65884GUI doesn't display response for multipart request manually encoded

    Timers, Assertions, Config, Pre- & Post-Processors

    From bc0d31de7b06b4b2666637e8fdcee74548e3e79f Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Thu, 17 Feb 2022 21:19:14 +0100 Subject: [PATCH 047/736] Fix generated Content-disposition header for failing test After fixing issue 65884, the parser for the content-disposition header is more lenient on the usage of quotes, but less forgiving about missing seperators between the parameters. Part of Bugzilla Id: 65884 --- .../apache/jmeter/protocol/http/proxy/TestHttpRequestHdr.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocol/http/src/test/java/org/apache/jmeter/protocol/http/proxy/TestHttpRequestHdr.java b/src/protocol/http/src/test/java/org/apache/jmeter/protocol/http/proxy/TestHttpRequestHdr.java index 2c2c2d9ec74..82c5b46bcfa 100644 --- a/src/protocol/http/src/test/java/org/apache/jmeter/protocol/http/proxy/TestHttpRequestHdr.java +++ b/src/protocol/http/src/test/java/org/apache/jmeter/protocol/http/proxy/TestHttpRequestHdr.java @@ -612,7 +612,7 @@ private String createMultipartFileUploadBody(String fileField, String fileName, String fileMimeType, String fileContent, String boundary, String endOfLine) { // File upload multipart String postBody = "--" + boundary + endOfLine - + "Content-Disposition: form-data; name=\"" + fileField + "\" filename=\"" + fileName + "\"" + endOfLine + + "Content-Disposition: form-data; name=\"" + fileField + "\"; filename=\"" + fileName + "\"" + endOfLine + "Content-Type: " + fileMimeType + endOfLine + "Content-Transfer-Encoding: binary" + endOfLine + endOfLine From c2f29ccfd1e2619ae2960c96bd54e76e2ba0e03b Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Sat, 19 Feb 2022 19:41:27 +0100 Subject: [PATCH 048/736] Setup GUI in Swing thread This seems to be the right thing to do and it fixes an exception, that happens on startup after the code for Bug 63620 has been incorporated. The exception was: ERROR o.a.j.g.u.JSyntaxTextArea: Dubious problem while setting text to SOMETHING java.lang.NullPointerException: null at org.fife.ui.rsyntaxtextarea.WrappedSyntaxView.updateMetrics(WrappedSyntaxView.java:1081) ~[rsyntaxtextarea-3.1.3.jar:3.1.3] at org.fife.ui.rsyntaxtextarea.WrappedSyntaxView.getPreferredSpan(WrappedSyntaxView.java:618) ~[rsyntaxtextarea-3.1.3.jar:3.1.3] at org.fife.ui.rsyntaxtextarea.WrappedSyntaxView.calculateBreakPosition(WrappedSyntaxView.java:114) ~[rsyntaxtextarea-3.1.3.jar:3.1.3] at org.fife.ui.rsyntaxtextarea.WrappedSyntaxView$WrappedLine.calculateLineCount(WrappedSyntaxView.java:1191) ~[rsyntaxtextarea-3.1.3.jar:3.1.3] at org.fife.ui.rsyntaxtextarea.WrappedSyntaxView$WrappedLine.handleDocumentEvent(WrappedSyntaxView.java:1440) ~[rsyntaxtextarea-3.1.3.jar:3.1.3] at org.fife.ui.rsyntaxtextarea.WrappedSyntaxView$WrappedLine.insertUpdate(WrappedSyntaxView.java:1464) ~[rsyntaxtextarea-3.1.3.jar:3.1.3] at org.fife.ui.rsyntaxtextarea.WrappedSyntaxView.insertUpdate(WrappedSyntaxView.java:705) ~[rsyntaxtextarea-3.1.3.jar:3.1.3] at javax.swing.plaf.basic.BasicTextUI$RootView.insertUpdate(BasicTextUI.java:1706) ~[?:?] at javax.swing.plaf.basic.BasicTextUI$UpdateHandler.insertUpdate(BasicTextUI.java:1965) ~[?:?] at javax.swing.text.AbstractDocument.fireInsertUpdate(AbstractDocument.java:203) ~[?:?] at org.fife.ui.rsyntaxtextarea.RSyntaxDocument.fireInsertUpdate(RSyntaxDocument.java:187) ~[rsyntaxtextarea-3.1.3.jar:3.1.3] at javax.swing.text.AbstractDocument.handleInsertString(AbstractDocument.java:757) ~[?:?] at javax.swing.text.AbstractDocument.insertString(AbstractDocument.java:716) ~[?:?] at javax.swing.text.PlainDocument.insertString(PlainDocument.java:131) ~[?:?] at javax.swing.text.AbstractDocument.replace(AbstractDocument.java:675) ~[?:?] at javax.swing.text.JTextComponent.setText(JTextComponent.java:1729) ~[?:?] at org.apache.jmeter.gui.util.JSyntaxTextArea.setInitialText(JSyntaxTextArea.java:296) [ApacheJMeter_core.jar:5.5-SNAPSHOT] at org.apache.jmeter.testbeans.gui.TextAreaEditor.setValue(TextAreaEditor.java:112) [ApacheJMeter_core.jar:5.5-SNAPSHOT] at org.apache.jmeter.testbeans.gui.GenericTestBeanCustomizer.setEditorValue(GenericTestBeanCustomizer.java:479) [ApacheJMeter_core.jar:5.5-SNAPSHOT] at org.apache.jmeter.testbeans.gui.GenericTestBeanCustomizer.setObject(GenericTestBeanCustomizer.java:511) [ApacheJMeter_core.jar:5.5-SNAPSHOT] at org.apache.jmeter.testbeans.gui.TestBeanGUI.setValues(TestBeanGUI.java:323) [ApacheJMeter_core.jar:5.5-SNAPSHOT] at org.apache.jmeter.testbeans.gui.TestBeanGUI.configure(TestBeanGUI.java:307) [ApacheJMeter_core.jar:5.5-SNAPSHOT] at org.apache.jmeter.gui.tree.JMeterTreeModel.addComponent(JMeterTreeModel.java:162) [ApacheJMeter_core.jar:5.5-SNAPSHOT] at org.apache.jmeter.gui.tree.JMeterTreeModel.addSubTree(JMeterTreeModel.java:131) [ApacheJMeter_core.jar:5.5-SNAPSHOT] at org.apache.jmeter.gui.tree.JMeterTreeModel.addSubTree(JMeterTreeModel.java:123) [ApacheJMeter_core.jar:5.5-SNAPSHOT] at org.apache.jmeter.gui.GuiPackage.addSubTree(GuiPackage.java:554) [ApacheJMeter_core.jar:5.5-SNAPSHOT] at org.apache.jmeter.gui.action.Load.insertLoadedTree(Load.java:199) [ApacheJMeter_core.jar:5.5-SNAPSHOT] at org.apache.jmeter.gui.action.Load.insertLoadedTree(Load.java:235) [ApacheJMeter_core.jar:5.5-SNAPSHOT] at org.apache.jmeter.JMeter.startGui(JMeter.java:431) [ApacheJMeter_core.jar:5.5-SNAPSHOT] at org.apache.jmeter.JMeter.start(JMeter.java:566) [ApacheJMeter_core.jar:5.5-SNAPSHOT] at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?] at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:?] at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?] at java.lang.reflect.Method.invoke(Method.java:564) ~[?:?] at org.apache.jmeter.NewDriver.main(NewDriver.java:257) Which seemed to happen on the main thread. Part of [Bug 63620] Fix GUI freeze when viewing response body with long lines Bugzilla Id: 63620 --- src/core/src/main/java/org/apache/jmeter/JMeter.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/core/src/main/java/org/apache/jmeter/JMeter.java b/src/core/src/main/java/org/apache/jmeter/JMeter.java index e5dffc61a99..3fa0d81f511 100644 --- a/src/core/src/main/java/org/apache/jmeter/JMeter.java +++ b/src/core/src/main/java/org/apache/jmeter/JMeter.java @@ -54,6 +54,7 @@ import javax.script.ScriptEngineManager; import javax.script.ScriptException; import javax.swing.JTree; +import javax.swing.SwingUtilities; import javax.swing.tree.TreePath; import org.apache.commons.cli.avalon.CLArgsParser; @@ -563,7 +564,8 @@ public void start(String[] args) { ReportGenerator generator = new ReportGenerator(reportFile, null); generator.generate(); } else if (parser.getArgumentById(NONGUI_OPT) == null) { // not non-GUI => GUI - startGui(testFile); + String initialTestFile = testFile; + SwingUtilities.invokeAndWait(() -> startGui(initialTestFile)); startOptionalServers(); } else { // NON-GUI must be true extractAndSetReportOutputFolder(parser, deleteResultFile); From 1d573158f2af7be882674e59c02490836abd0cde Mon Sep 17 00:00:00 2001 From: KING76169835 Date: Sat, 26 Feb 2022 12:29:01 +0800 Subject: [PATCH 049/736] =?UTF-8?q?CSV=E6=96=87=E4=BB=B6=E4=B8=AD=E5=85=B1?= =?UTF-8?q?=E4=BA=AB=E6=A8=A1=E5=BC=8F=E6=B1=89=E5=8C=96=E7=BF=BB=E8=AF=91?= =?UTF-8?q?=E6=9C=89=E8=AF=AF=EF=BC=9A=E6=89=80=E6=9C=89=E7=8E=B0=E5=9C=BA?= =?UTF-8?q?-->=E6=89=80=E6=9C=89=E7=BA=BF=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apache/jmeter/config/CSVDataSetResources_zh_CN.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/src/main/resources/org/apache/jmeter/config/CSVDataSetResources_zh_CN.properties b/src/components/src/main/resources/org/apache/jmeter/config/CSVDataSetResources_zh_CN.properties index 1e05c25dde4..e4b72cac502 100644 --- a/src/components/src/main/resources/org/apache/jmeter/config/CSVDataSetResources_zh_CN.properties +++ b/src/components/src/main/resources/org/apache/jmeter/config/CSVDataSetResources_zh_CN.properties @@ -36,6 +36,6 @@ stopThread.displayName=遇到文件结束符停止线程? stopThread.shortDescription=当文件结束时是否停止线程(只有当再次循环关闭情况下)? shareMode.displayName=线程共享模式 shareMode.shortDescription=选择哪些线程会共享同一个文件句柄 -shareMode.all=所有现场 +shareMode.all=所有线程 shareMode.group=当前线程组 shareMode.thread=当前线程 From 576a281e8d4a4d0fce8dc88c6726313bb81d98dc Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Fri, 4 Mar 2022 19:41:18 +0100 Subject: [PATCH 050/736] Update to log4j2 2.17.2 --- gradle.properties | 2 +- src/dist/src/dist/expected_release_jars.csv | 8 ++++---- xdocs/changes.xml | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/gradle.properties b/gradle.properties index 376c3298fd6..64a38484c7f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -115,7 +115,7 @@ junit4.version=4.13.2 junit5.version=5.8.1 lets-plot-batik.version=2.2.1 lets-plot-kotlin-jvm.version=3.1.1 -log4j.version=2.17.1 +log4j.version=2.17.2 mail.version=1.5.0-b01 miglayout.version=5.3 mina-core.version=2.0.19 diff --git a/src/dist/src/dist/expected_release_jars.csv b/src/dist/src/dist/expected_release_jars.csv index 9caa9b8281f..bc024803e97 100644 --- a/src/dist/src/dist/expected_release_jars.csv +++ b/src/dist/src/dist/expected_release_jars.csv @@ -94,10 +94,10 @@ 792176,kotlinx-html-jvm-0.7.3.jar 181223,lets-plot-batik-2.2.1.jar 4025480,lets-plot-common-2.2.1.jar -208006,log4j-1.2-api-2.17.1.jar -301872,log4j-api-2.17.1.jar -1790452,log4j-core-2.17.1.jar -24279,log4j-slf4j-impl-2.17.1.jar +303443,log4j-1.2-api-2.17.2.jar +302511,log4j-api-2.17.2.jar +1811089,log4j-core-2.17.2.jar +24248,log4j-slf4j-impl-2.17.2.jar 519087,mail-1.5.0-b01.jar 106949,miglayout-core-5.3.jar 22576,miglayout-swing-5.3.jar diff --git a/xdocs/changes.xml b/xdocs/changes.xml index 8a3aaeb5543..1164896d197 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -61,7 +61,7 @@ Summary New and Noteworthy

    JMeter now supports Java 17

    -

    JMeter 5.5 ships with log4j2 2.17.1

    +

    JMeter 5.5 ships with log4j2 2.17.2

    New component: Open Model Thread Group allows creating load profiles with variable load.

    @@ -176,7 +176,7 @@ however, the profile can't be updated while the test is running.
  • Updated json-path to 2.6.0 (from 2.4.0).
  • Updated jsoup to 1.14.3 (from 1.13.1).
  • Updated JUnit to 4.13.2 and 5.8.1 (from 4.13.1 and 5.7.0).
  • -
  • Updated Apache log4j2 to 2.17.1 (from 2.13.3).
  • +
  • Updated Apache log4j2 to 2.17.2 (from 2.13.3).
  • Updated Miglayout to 5.3 (from 5.2).
  • Updated Neo4j Java driver to 4.3.3 (from 4.2.0).
  • Updated Objenesis to 3.2 (from 2.6).
  • From 303f355293c3c685a17f073f968e3755a4f9e0f4 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Fri, 4 Mar 2022 20:54:52 +0100 Subject: [PATCH 051/736] Update json-smart and accessors-smart to 2.4.8 --- checksum.xml | 12 +++++++++--- gradle.properties | 4 ++-- src/dist/src/dist/expected_release_jars.csv | 4 ++-- xdocs/changes.xml | 2 +- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/checksum.xml b/checksum.xml index c860213a819..af317ecd33a 100644 --- a/checksum.xml +++ b/checksum.xml @@ -51,10 +51,10 @@ - - + + @@ -197,8 +197,8 @@ - + @@ -238,9 +238,15 @@ 6DAAF2FE1B278599D6D0BBD3F157096F8BCCF3D25616099C128139CE164B29461860EB2786F3D3728937A0D0505DF73F1C9673B0766F946C50878E5F60305736 + + 45405C083334B05EFA07572497B9D510CA771AF32CE93D960BE802216A9714FFFF8418384EA48E197D3DFB6EBEC4EC3E610155841E8A257A7FB9A4BD6A1B668F + 3E9E1EE9A44EA15044B588B06A956AC150A37B63C161BF9B08A60539F5C90EFC7718DEB24FD084F503B68092516AAC3349DBB74049777EA4C6619AC26090A1D + + 13F4609FE72DF98C81F86D25616E5B0CE1426688AA5A9DD953733FA98A8DEADB87B3E69A77741DC9D31DD4485265D3B9E4EC71D99346E4A7558F2500F3677714 + 16D30BE564723B74F312B4E7D06F349370FB6726B3162778C869CD723ECA2A40C4972C2757B3E107E1820CEC0D70B0BD2B96EFCD466518FC64495F7AEF97967A diff --git a/gradle.properties b/gradle.properties index 64a38484c7f..d8d1cfa04eb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -56,7 +56,7 @@ org.nosphere.apache.rat.version=0.7.0 org.sonarqube.version=3.0 # Dependencies -accessors-smart.version=2.4.7 +accessors-smart.version=2.4.8 activemq.version=5.16.2 apache-rat.version=0.13 apiguardian-api.version=1.1.0 @@ -108,7 +108,7 @@ jmespath-core.version=0.5.0 jmespath-jackson.version=0.5.0 jodd.version=5.0.13 json-path.version=2.6.0 -json-smart.version=2.4.7 +json-smart.version=2.4.8 jsoup.version=1.14.3 jtidy.version=r938 junit4.version=4.13.2 diff --git a/src/dist/src/dist/expected_release_jars.csv b/src/dist/src/dist/expected_release_jars.csv index bc024803e97..15f17c4db6a 100644 --- a/src/dist/src/dist/expected_release_jars.csv +++ b/src/dist/src/dist/expected_release_jars.csv @@ -1,4 +1,4 @@ -29489,accessors-smart-2.4.7.jar +29524,accessors-smart-2.4.8.jar 29371,annotations-23.0.0.jar 2387,apiguardian-api-1.1.0.jar 122004,asm-9.2.jar @@ -82,7 +82,7 @@ 19858,jodd-log-5.0.13.jar 26047,jodd-props-5.0.13.jar 238605,json-path-2.6.0.jar -119227,json-smart-2.4.7.jar +119545,json-smart-2.4.8.jar 423395,jsoup-1.14.3.jar 249924,jtidy-r938.jar 384581,junit-4.13.2.jar diff --git a/xdocs/changes.xml b/xdocs/changes.xml index 1164896d197..28ed31160ac 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -153,7 +153,7 @@ however, the profile can't be updated while the test is running.
  • 65128643Add missing documentation about Same user on each iteration for Thread Groups. Contributed by njkuzas.
  • 648Updated xmlgraphics-commons to 2.6 (from 2.3). Contributed by Stefan Seide (stefan at trilobyte-se.de)
  • 655667675698Updated x-stream to 1.4.19 (from 1.4.15). Contributed by Stefan Seide (stefan at trilobyte-se.de)
  • -
  • 656668Updated json-smart to 2.4.7 (from 2.3), accessors-smart to 2.4.7 (from 1.2) and asm 9.1 (from 9.0). Contributed by Stefan Seide (stefan at trilobyte-se.de)
  • +
  • 656668Updated json-smart to 2.4.8 (from 2.3), accessors-smart to 2.4.8 (from 1.2) and asm 9.1 (from 9.0). Contributed by Stefan Seide (stefan at trilobyte-se.de)
  • 64831Log truststore entries in debug level for logger org.apache.jmeter.util.keystore.JmeterKeyStore
  • 65232Hide splash screen when an error is displayed because the test plan could not be parsed.
  • Updated Groovy to 3.0.9 (from 3.0.7).
  • From d5640f7169a80c287d596e5b07ea215cb040df14 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Sat, 5 Mar 2022 10:48:50 +0100 Subject: [PATCH 052/736] Update ActiveMQ to 5.16.4 --- gradle.properties | 2 +- xdocs/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index d8d1cfa04eb..f111edf9748 100644 --- a/gradle.properties +++ b/gradle.properties @@ -57,7 +57,7 @@ org.sonarqube.version=3.0 # Dependencies accessors-smart.version=2.4.8 -activemq.version=5.16.2 +activemq.version=5.16.4 apache-rat.version=0.13 apiguardian-api.version=1.1.0 asm.version=9.2 diff --git a/xdocs/changes.xml b/xdocs/changes.xml index 28ed31160ac..81bd4da610f 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -158,7 +158,7 @@ however, the profile can't be updated while the test is running.
  • 65232Hide splash screen when an error is displayed because the test plan could not be parsed.
  • Updated Groovy to 3.0.9 (from 3.0.7).
  • Updated Darklaf to 2.7.3 (from 2.5.4).
  • -
  • Updated Apache ActiveMQ to 15.6.2 (from 15.6.0).
  • +
  • Updated Apache ActiveMQ to 15.6.4 (from 15.6.0).
  • Updated Asm to 9.2 (from 9.1).
  • Updated Bouncycastle to 1.69 (from 1.67).
  • Updated Caffeine to 2.9.2 (from 2.8.8).
  • From 19fdf6a45721e3983431aaa850c776a176b1d90f Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Sat, 5 Mar 2022 11:00:25 +0100 Subject: [PATCH 053/736] Add checksum of key for xbean --- checksum.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/checksum.xml b/checksum.xml index af317ecd33a..68e7a0920e9 100644 --- a/checksum.xml +++ b/checksum.xml @@ -132,6 +132,7 @@ + From 75d5ad688fabd35dcac8b9538b8604e145bbf802 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Sat, 5 Mar 2022 11:08:10 +0100 Subject: [PATCH 054/736] Updated Caffeine to 2.9.3 --- gradle.properties | 2 +- xdocs/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index f111edf9748..72c4d9a06a8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -64,7 +64,7 @@ asm.version=9.2 bouncycastle.version=1.69 bsf.version=2.4.0 bsh.version=2.0b6 -caffeine.version=2.9.2 +caffeine.version=2.9.3 cglib-nodep.version=3.2.12 commons-codec.version=1.15 commons-collections.version=3.2.2 diff --git a/xdocs/changes.xml b/xdocs/changes.xml index 81bd4da610f..04522e7db83 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -161,7 +161,7 @@ however, the profile can't be updated while the test is running.
  • Updated Apache ActiveMQ to 15.6.4 (from 15.6.0).
  • Updated Asm to 9.2 (from 9.1).
  • Updated Bouncycastle to 1.69 (from 1.67).
  • -
  • Updated Caffeine to 2.9.2 (from 2.8.8).
  • +
  • Updated Caffeine to 2.9.3 (from 2.8.8).
  • Updated Apache commons-dbcp2 to 2.9.0 (from 2.8.0).
  • Updated Apache commons-io to 2.11.0 (from 2.8.0).
  • Updated Apache commons-lang3 to 3.12.0 (from 3.11).
  • From 1228254494a09a0aec93bc83bd51ce712f789cfb Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Sat, 5 Mar 2022 11:15:54 +0100 Subject: [PATCH 055/736] Updated commons-pool2 to 2.11.1 --- gradle.properties | 2 +- xdocs/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 72c4d9a06a8..33b83262b08 100644 --- a/gradle.properties +++ b/gradle.properties @@ -78,7 +78,7 @@ commons-lang3.version=3.12.0 commons-logging.version=1.2 commons-math3.version=3.6.1 commons-net.version=3.8.0 -commons-pool2.version=2.11.0 +commons-pool2.version=2.11.1 commons-text.version=1.9 darklaf.version=2.7.3 darklaf.extensions.version=0.3.4 diff --git a/xdocs/changes.xml b/xdocs/changes.xml index 04522e7db83..7cc6a07ee43 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -166,7 +166,7 @@ however, the profile can't be updated while the test is running.
  • Updated Apache commons-io to 2.11.0 (from 2.8.0).
  • Updated Apache commons-lang3 to 3.12.0 (from 3.11).
  • Updated Apache commons-net to 3.8.0 (from 3.7.2).
  • -
  • Updated Apache commons-pool2 to 2.11.0 (from 2.9.0).
  • +
  • Updated Apache commons-pool2 to 2.11.1 (from 2.9.0).
  • Updated equalsverifier to 3.7 (from 3.4.2).
  • Updated Apache Freemarker to 2.3.31 (from 2.3.30).
  • Updated hsqldb to 2.6.0 (from 2.5.0).
  • From 1c325d6309bba2f69a36404f973610403a9ab91b Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Sat, 5 Mar 2022 11:20:21 +0100 Subject: [PATCH 056/736] Updates equalsverifier to 3.9 --- gradle.properties | 2 +- xdocs/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 33b83262b08..ba601cb6422 100644 --- a/gradle.properties +++ b/gradle.properties @@ -84,7 +84,7 @@ darklaf.version=2.7.3 darklaf.extensions.version=0.3.4 dec.version=0.1.2 dnsjava.version=2.1.9 -equalsverifier.version=3.7 +equalsverifier.version=3.9 freemarker.version=2.3.31 ftplet-api.version=1.1.1 ftpserver-core.version=1.1.1 diff --git a/xdocs/changes.xml b/xdocs/changes.xml index 7cc6a07ee43..6bebedb2e50 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -167,7 +167,7 @@ however, the profile can't be updated while the test is running.
  • Updated Apache commons-lang3 to 3.12.0 (from 3.11).
  • Updated Apache commons-net to 3.8.0 (from 3.7.2).
  • Updated Apache commons-pool2 to 2.11.1 (from 2.9.0).
  • -
  • Updated equalsverifier to 3.7 (from 3.4.2).
  • +
  • Updated equalsverifier to 3.9 (from 3.4.2).
  • Updated Apache Freemarker to 2.3.31 (from 2.3.30).
  • Updated hsqldb to 2.6.0 (from 2.5.0).
  • Updated Apache HttpClient to 4.5.13 (from 4.5.12).
  • From 1d164f744cf53b843a8c04eee27d5c6c2ef42fd1 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Sat, 5 Mar 2022 11:23:59 +0100 Subject: [PATCH 057/736] Updated ftplet and ftpserver to 1.1.3 --- gradle.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index ba601cb6422..e915fe4cb66 100644 --- a/gradle.properties +++ b/gradle.properties @@ -86,8 +86,8 @@ dec.version=0.1.2 dnsjava.version=2.1.9 equalsverifier.version=3.9 freemarker.version=2.3.31 -ftplet-api.version=1.1.1 -ftpserver-core.version=1.1.1 +ftplet-api.version=1.1.3 +ftpserver-core.version=1.1.3 geronimo-jms_1.1_spec.version=1.1.1 groovy.version=3.0.9 hamcrest.version=2.2 From ee6d4f06c92de7e4d18b12d83b965d9a407a8d10 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Sat, 5 Mar 2022 11:25:35 +0100 Subject: [PATCH 058/736] Updated hamcrest-date to 2.0.8 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index e915fe4cb66..10031536bbe 100644 --- a/gradle.properties +++ b/gradle.properties @@ -91,7 +91,7 @@ ftpserver-core.version=1.1.3 geronimo-jms_1.1_spec.version=1.1.1 groovy.version=3.0.9 hamcrest.version=2.2 -hamcrest-date.version=2.0.7 +hamcrest-date.version=2.0.8 hsqldb.version=2.5.2 httpasyncclient.version=4.1.4 httpclient.version=4.5.13 From b4c9e671550ae792ff62b13b0a910af67e7e20f0 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Sat, 5 Mar 2022 11:27:09 +0100 Subject: [PATCH 059/736] Updated hsqldb to 2.6.1 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 10031536bbe..4b92e98b015 100644 --- a/gradle.properties +++ b/gradle.properties @@ -92,7 +92,7 @@ geronimo-jms_1.1_spec.version=1.1.1 groovy.version=3.0.9 hamcrest.version=2.2 hamcrest-date.version=2.0.8 -hsqldb.version=2.5.2 +hsqldb.version=2.6.1 httpasyncclient.version=4.1.4 httpclient.version=4.5.13 httpcore-nio.version=4.4.14 From 0d04f1379ed7d7a7ad6999bf69a60d0758030039 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Sat, 5 Mar 2022 11:32:26 +0100 Subject: [PATCH 060/736] Bytebuddy used by Caffeine --- checksum.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/checksum.xml b/checksum.xml index 68e7a0920e9..096e3d67e4e 100644 --- a/checksum.xml +++ b/checksum.xml @@ -93,6 +93,7 @@ + From bcf2c29225abfd05ef7b8b0b43e5966ec7a90f9f Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Sat, 5 Mar 2022 11:36:18 +0100 Subject: [PATCH 061/736] Updated Apache HttpCore to 4.4.15 --- gradle.properties | 6 +++--- xdocs/changes.xml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gradle.properties b/gradle.properties index 4b92e98b015..c30380cecd7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -93,10 +93,10 @@ groovy.version=3.0.9 hamcrest.version=2.2 hamcrest-date.version=2.0.8 hsqldb.version=2.6.1 -httpasyncclient.version=4.1.4 +httpasyncclient.version=4.1.5 httpclient.version=4.5.13 -httpcore-nio.version=4.4.14 -httpcore.version=4.4.14 +httpcore-nio.version=4.4.15 +httpcore.version=4.4.15 httpmime.version=4.5.13 jackson.version=2.13.1 jackson-databind.version=2.13.1 diff --git a/xdocs/changes.xml b/xdocs/changes.xml index 6bebedb2e50..f17be2e8619 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -171,7 +171,7 @@ however, the profile can't be updated while the test is running.
  • Updated Apache Freemarker to 2.3.31 (from 2.3.30).
  • Updated hsqldb to 2.6.0 (from 2.5.0).
  • Updated Apache HttpClient to 4.5.13 (from 4.5.12).
  • -
  • Updated Apache HttpCore to 4.4.14 (from 4.4.13).
  • +
  • Updated Apache HttpCore to 4.4.15 (from 4.4.13).
  • Updated jacoco to 0.8.7 (from 0.8.5).
  • Updated json-path to 2.6.0 (from 2.4.0).
  • Updated jsoup to 1.14.3 (from 1.13.1).
  • From 1564774137506e6eb8283f384324bd51306ca1c1 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Sat, 5 Mar 2022 12:17:01 +0100 Subject: [PATCH 062/736] Update JMESPath to 0.5.1 --- gradle.properties | 4 ++-- xdocs/changes.xml | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index c30380cecd7..d08905ec9ec 100644 --- a/gradle.properties +++ b/gradle.properties @@ -104,8 +104,8 @@ javax.activation.version=1.2.0 jcharts.version=0.7.5 jdom.version=1.1.3 jetbrains-annotations.version=23.0.0 -jmespath-core.version=0.5.0 -jmespath-jackson.version=0.5.0 +jmespath-core.version=0.5.1 +jmespath-jackson.version=0.5.1 jodd.version=5.0.13 json-path.version=2.6.0 json-smart.version=2.4.8 diff --git a/xdocs/changes.xml b/xdocs/changes.xml index f17be2e8619..0dd8dfe65de 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -189,6 +189,7 @@ however, the profile can't be updated while the test is running.
  • Updated WireMock-JRE8 to 2.30.0 (from 2.24.1).
  • Updated com.github.vlsi.vlsi-release-plugins 1.76 (from 1.74).
  • Updated jackson to 2.13.1 (from 2.10.5)
  • +
  • Updated jmespath to 0.5.1
  • 671Move example definition of property jmeter.reportgenerator.statistic_window to user.properties, as it is read from that place. Contributed by Rithvik Patibandla (rithvikp98 at gmail.com)
  • From b93413802408a6d66bc3adbf080ed5edce0dc749 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Sat, 5 Mar 2022 12:29:57 +0100 Subject: [PATCH 063/736] Reverted Update of hsqldb to 2.6.1 (the binary seems to be compiled with Java >8) --- gradle.properties | 2 +- xdocs/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index d08905ec9ec..77db8847699 100644 --- a/gradle.properties +++ b/gradle.properties @@ -92,7 +92,7 @@ geronimo-jms_1.1_spec.version=1.1.1 groovy.version=3.0.9 hamcrest.version=2.2 hamcrest-date.version=2.0.8 -hsqldb.version=2.6.1 +hsqldb.version=2.5.2 httpasyncclient.version=4.1.5 httpclient.version=4.5.13 httpcore-nio.version=4.4.15 diff --git a/xdocs/changes.xml b/xdocs/changes.xml index 0dd8dfe65de..9d88b651c2d 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -169,7 +169,7 @@ however, the profile can't be updated while the test is running.
  • Updated Apache commons-pool2 to 2.11.1 (from 2.9.0).
  • Updated equalsverifier to 3.9 (from 3.4.2).
  • Updated Apache Freemarker to 2.3.31 (from 2.3.30).
  • -
  • Updated hsqldb to 2.6.0 (from 2.5.0).
  • +
  • Updated hsqldb to 2.5.2 (from 2.5.0).
  • Updated Apache HttpClient to 4.5.13 (from 4.5.12).
  • Updated Apache HttpCore to 4.4.15 (from 4.4.13).
  • Updated jacoco to 0.8.7 (from 0.8.5).
  • From 339d66fed0523d7229444a773d94f4e22f48fd1d Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Sat, 5 Mar 2022 12:40:43 +0100 Subject: [PATCH 064/736] Updated JUnit5 to 5.8.2 --- gradle.properties | 2 +- xdocs/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 77db8847699..ca61c5681be 100644 --- a/gradle.properties +++ b/gradle.properties @@ -112,7 +112,7 @@ json-smart.version=2.4.8 jsoup.version=1.14.3 jtidy.version=r938 junit4.version=4.13.2 -junit5.version=5.8.1 +junit5.version=5.8.2 lets-plot-batik.version=2.2.1 lets-plot-kotlin-jvm.version=3.1.1 log4j.version=2.17.2 diff --git a/xdocs/changes.xml b/xdocs/changes.xml index 9d88b651c2d..73639a1363e 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -175,7 +175,7 @@ however, the profile can't be updated while the test is running.
  • Updated jacoco to 0.8.7 (from 0.8.5).
  • Updated json-path to 2.6.0 (from 2.4.0).
  • Updated jsoup to 1.14.3 (from 1.13.1).
  • -
  • Updated JUnit to 4.13.2 and 5.8.1 (from 4.13.1 and 5.7.0).
  • +
  • Updated JUnit to 4.13.2 and 5.8.2 (from 4.13.1 and 5.7.0).
  • Updated Apache log4j2 to 2.17.2 (from 2.13.3).
  • Updated Miglayout to 5.3 (from 5.2).
  • Updated Neo4j Java driver to 4.3.3 (from 4.2.0).
  • From 7c161a2d3c041fd5fd149a1b555a2b5e97878a44 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Sat, 5 Mar 2022 12:55:02 +0100 Subject: [PATCH 065/736] Updated mina-core to 2.1.6 It was already used in this version by dependency --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index ca61c5681be..1e3d3121a4b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -118,7 +118,7 @@ lets-plot-kotlin-jvm.version=3.1.1 log4j.version=2.17.2 mail.version=1.5.0-b01 miglayout.version=5.3 -mina-core.version=2.0.19 +mina-core.version=2.1.6 mongo-java-driver.version=2.11.3 neo4j-java-driver.version=4.3.3 objenesis.version=3.2 From de94417d5d0347d8f6d80d532185498a609c201d Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Sat, 5 Mar 2022 13:02:18 +0100 Subject: [PATCH 066/736] Updated Neo4j Java driver to 4.4.4 --- gradle.properties | 2 +- xdocs/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 1e3d3121a4b..03de6e67c00 100644 --- a/gradle.properties +++ b/gradle.properties @@ -120,7 +120,7 @@ mail.version=1.5.0-b01 miglayout.version=5.3 mina-core.version=2.1.6 mongo-java-driver.version=2.11.3 -neo4j-java-driver.version=4.3.3 +neo4j-java-driver.version=4.4.3 objenesis.version=3.2 oro.version=2.0.8 ph-commons.version=10.1.2 diff --git a/xdocs/changes.xml b/xdocs/changes.xml index 73639a1363e..18c7657ef56 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -178,7 +178,7 @@ however, the profile can't be updated while the test is running.
  • Updated JUnit to 4.13.2 and 5.8.2 (from 4.13.1 and 5.7.0).
  • Updated Apache log4j2 to 2.17.2 (from 2.13.3).
  • Updated Miglayout to 5.3 (from 5.2).
  • -
  • Updated Neo4j Java driver to 4.3.3 (from 4.2.0).
  • +
  • Updated Neo4j Java driver to 4.4.4 (from 4.2.0).
  • Updated Objenesis to 3.2 (from 2.6).
  • Updated ktlint to 0.40.0
  • Updated PH CSS and PH commons to 6.3.4 and 9.5.5 (from 6.2.3 and 9.5.1).
  • From 1c605fd532692318179cac622e1f0fc78aad39fa Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Sat, 5 Mar 2022 13:22:49 +0100 Subject: [PATCH 067/736] Updated PH CSS and PH commons to 6.5.4 and 10.1.6 --- gradle.properties | 4 ++-- xdocs/changes.xml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index 03de6e67c00..b20ebe8371d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -123,8 +123,8 @@ mongo-java-driver.version=2.11.3 neo4j-java-driver.version=4.4.3 objenesis.version=3.2 oro.version=2.0.8 -ph-commons.version=10.1.2 -ph-css.version=6.3.4 +ph-commons.version=10.1.6 +ph-css.version=6.5.0 rhino.version=1.7.13 rsyntaxtextarea.version=3.1.3 Saxon-HE.version=9.9.1-8 diff --git a/xdocs/changes.xml b/xdocs/changes.xml index 18c7657ef56..9bb5ecbeec6 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -181,7 +181,7 @@ however, the profile can't be updated while the test is running.
  • Updated Neo4j Java driver to 4.4.4 (from 4.2.0).
  • Updated Objenesis to 3.2 (from 2.6).
  • Updated ktlint to 0.40.0
  • -
  • Updated PH CSS and PH commons to 6.3.4 and 9.5.5 (from 6.2.3 and 9.5.1).
  • +
  • Updated PH CSS and PH commons to 6.5.4 and 10.1.6 (from 6.2.3 and 9.5.1).
  • Updated RSyntaxTextArea to 3.1.3 (from 3.1.1).
  • Updated SLF4J to 1.7.32 (from 1.7.30).
  • Updated SvgSalamander to 1.1.2.4 (from 1.1.2.1).
  • From 7d2afdc5eca3b9d6847712f79730fcac4c8a99db Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Sat, 5 Mar 2022 15:13:58 +0100 Subject: [PATCH 068/736] Update expected_release_jars and set errorprone to the currently used version --- gradle.properties | 2 +- src/dist/src/dist/expected_release_jars.csv | 26 ++++++++++----------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/gradle.properties b/gradle.properties index b20ebe8371d..042d0f50631 100644 --- a/gradle.properties +++ b/gradle.properties @@ -33,7 +33,7 @@ jmeter.version=5.5 # Tools checkstyle.version=8.35 -errorprone.version=2.4.0 +errorprone.version=2.10.0 jacoco.version=0.8.7 ktlint.version=0.40.0 spotbugs.version=4.1.2 diff --git a/src/dist/src/dist/expected_release_jars.csv b/src/dist/src/dist/expected_release_jars.csv index 15f17c4db6a..9bd2899db78 100644 --- a/src/dist/src/dist/expected_release_jars.csv +++ b/src/dist/src/dist/expected_release_jars.csv @@ -23,8 +23,8 @@ 33866,batik-xml-1.14.jar 113369,bsf-2.4.0.jar 389033,bsh-2.0b6.jar -925272,caffeine-2.9.2.jar -207036,checker-qual-3.10.0.jar +912143,caffeine-2.9.3.jar +222143,checker-qual-3.19.0.jar 353793,commons-codec-1.15.jar 588337,commons-collections-3.2.2.jar 751914,commons-collections4-4.4.jar @@ -36,7 +36,7 @@ 61829,commons-logging-1.2.jar 2213560,commons-math3-3.6.1.jar 307305,commons-net-3.8.0.jar -145267,commons-pool2-2.11.0.jar +145516,commons-pool2-2.11.1.jar 216211,commons-text-1.9.jar 1547509,darklaf-core-2.7.3.jar 20650,darklaf-extensions-rsyntaxarea-0.3.4.jar @@ -49,7 +49,7 @@ 217795,darklaf-windows-2.7.3.jar 98115,dec-0.1.2.jar 320748,dnsjava-2.1.9.jar -13854,error_prone_annotations-2.5.1.jar +15992,error_prone_annotations-2.10.0.jar 1715750,freemarker-2.3.31.jar 32359,geronimo-jms_1.1_spec-1.1.1.jar 8004986,groovy-3.0.9.jar @@ -63,11 +63,11 @@ 296025,groovy-xml-3.0.9.jar 123360,hamcrest-2.2.jar 1499,hamcrest-core-2.2.jar -104518,hamcrest-date-2.0.7.jar -179964,httpasyncclient-4.1.4.jar +109741,hamcrest-date-2.0.8.jar +181512,httpasyncclient-4.1.5.jar 780321,httpclient-4.5.13.jar -328436,httpcore-4.4.14.jar -369365,httpcore-nio-4.4.14.jar +328324,httpcore-4.4.15.jar +369486,httpcore-nio-4.4.15.jar 41790,httpmime-4.5.13.jar 75717,jackson-annotations-2.13.1.jar 374588,jackson-core-2.13.1.jar @@ -75,8 +75,8 @@ 78030,javax.activation-1.2.0.jar 142391,jcharts-0.7.5.jar 16630,jcl-over-slf4j-1.7.32.jar -490565,jmespath-core-0.5.0.jar -7041,jmespath-jackson-0.5.0.jar +490571,jmespath-core-0.5.1.jar +7066,jmespath-jackson-0.5.1.jar 403497,jodd-core-5.0.13.jar 220475,jodd-lagarto-5.0.13.jar 19858,jodd-log-5.0.13.jar @@ -103,10 +103,10 @@ 22576,miglayout-swing-5.3.jar 419054,mongo-java-driver-2.11.3.jar 29680,mxparser-1.2.2.jar -4687205,neo4j-java-driver-4.3.3.jar +4890898,neo4j-java-driver-4.4.3.jar 65261,oro-2.0.8.jar -1307434,ph-commons-10.1.2.jar -506616,ph-css-6.3.4.jar +1308773,ph-commons-10.1.6.jar +530791,ph-css-6.5.0.jar 642167,plot-api-jvm-3.1.1.jar 891618,plot-base-portable-jvm-2.2.1.jar 845777,plot-builder-portable-jvm-2.2.1.jar From 500b6bed818d5be990b4e1f910e2ec160f7864e0 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Sat, 5 Mar 2022 15:17:58 +0100 Subject: [PATCH 069/736] Updated RSyntaxTextArea to 3.1.6 --- gradle.properties | 2 +- src/dist/src/dist/expected_release_jars.csv | 2 +- xdocs/changes.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index 042d0f50631..6231653b6a1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -126,7 +126,7 @@ oro.version=2.0.8 ph-commons.version=10.1.6 ph-css.version=6.5.0 rhino.version=1.7.13 -rsyntaxtextarea.version=3.1.3 +rsyntaxtextarea.version=3.1.6 Saxon-HE.version=9.9.1-8 slf4j.version=1.7.32 spock-core.version=2.0-M2-groovy-3.0 diff --git a/src/dist/src/dist/expected_release_jars.csv b/src/dist/src/dist/expected_release_jars.csv index 9bd2899db78..855ceb18c74 100644 --- a/src/dist/src/dist/expected_release_jars.csv +++ b/src/dist/src/dist/expected_release_jars.csv @@ -114,7 +114,7 @@ 749095,plot-config-portable-jvm-2.2.1.jar 11369,reactive-streams-1.0.3.jar 1315838,rhino-1.7.13.jar -1242230,rsyntaxtextarea-3.1.3.jar +1245900,rsyntaxtextarea-3.1.6.jar 5506669,Saxon-HE-9.9.1-8.jar 276420,serializer-2.7.2.jar 41513,slf4j-api-1.7.32.jar diff --git a/xdocs/changes.xml b/xdocs/changes.xml index 9bb5ecbeec6..3ffe9d2a0c8 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -182,7 +182,7 @@ however, the profile can't be updated while the test is running.
  • Updated Objenesis to 3.2 (from 2.6).
  • Updated ktlint to 0.40.0
  • Updated PH CSS and PH commons to 6.5.4 and 10.1.6 (from 6.2.3 and 9.5.1).
  • -
  • Updated RSyntaxTextArea to 3.1.3 (from 3.1.1).
  • +
  • Updated RSyntaxTextArea to 3.1.6 (from 3.1.1).
  • Updated SLF4J to 1.7.32 (from 1.7.30).
  • Updated SvgSalamander to 1.1.2.4 (from 1.1.2.1).
  • 698Updated Apache Tika to 1.28.1 (from 1.26).
  • From de9d1fd61acce33a96cd609625138e1bbf8214fa Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Sat, 5 Mar 2022 15:26:40 +0100 Subject: [PATCH 070/736] Updated Saxon-HE to 11.2 --- checksum.xml | 2 ++ gradle.properties | 2 +- src/dist/src/dist/expected_release_jars.csv | 4 +++- xdocs/changes.xml | 1 + 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/checksum.xml b/checksum.xml index 096e3d67e4e..03092002e70 100644 --- a/checksum.xml +++ b/checksum.xml @@ -102,6 +102,7 @@ + @@ -197,6 +198,7 @@ + diff --git a/gradle.properties b/gradle.properties index 6231653b6a1..75a7b000585 100644 --- a/gradle.properties +++ b/gradle.properties @@ -127,7 +127,7 @@ ph-commons.version=10.1.6 ph-css.version=6.5.0 rhino.version=1.7.13 rsyntaxtextarea.version=3.1.6 -Saxon-HE.version=9.9.1-8 +Saxon-HE.version=11.2 slf4j.version=1.7.32 spock-core.version=2.0-M2-groovy-3.0 springframework.version=4.3.17.RELEASE diff --git a/src/dist/src/dist/expected_release_jars.csv b/src/dist/src/dist/expected_release_jars.csv index 855ceb18c74..52a4c466637 100644 --- a/src/dist/src/dist/expected_release_jars.csv +++ b/src/dist/src/dist/expected_release_jars.csv @@ -115,7 +115,7 @@ 11369,reactive-streams-1.0.3.jar 1315838,rhino-1.7.13.jar 1245900,rsyntaxtextarea-3.1.6.jar -5506669,Saxon-HE-9.9.1-8.jar +5104409,Saxon-HE-11.2.jar 276420,serializer-2.7.2.jar 41513,slf4j-api-1.7.32.jar 301279,svgSalamander-1.1.2.4.jar @@ -130,4 +130,6 @@ 85686,xml-apis-ext-1.3.04.jar 674607,xmlgraphics-commons-2.6.jar 7188,xmlpull-1.1.3.1.jar +1027759,xmlresolver-4.2.0-data.jar +150259,xmlresolver-4.2.0.jar 633140,xstream-1.4.19.jar diff --git a/xdocs/changes.xml b/xdocs/changes.xml index 3ffe9d2a0c8..d144e20aa0d 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -190,6 +190,7 @@ however, the profile can't be updated while the test is running.
  • Updated com.github.vlsi.vlsi-release-plugins 1.76 (from 1.74).
  • Updated jackson to 2.13.1 (from 2.10.5)
  • Updated jmespath to 0.5.1
  • +
  • Updated Saxon-HE to 11.2 (from 9.9.1-8)
  • 671Move example definition of property jmeter.reportgenerator.statistic_window to user.properties, as it is read from that place. Contributed by Rithvik Patibandla (rithvikp98 at gmail.com)
  • From 9980e47023041414a8194a8bf2c369f373b3d515 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Sat, 5 Mar 2022 15:30:16 +0100 Subject: [PATCH 071/736] Updated SLF4J to 1.7.36 --- gradle.properties | 2 +- src/dist/src/dist/expected_release_jars.csv | 4 ++-- xdocs/changes.xml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gradle.properties b/gradle.properties index 75a7b000585..7d8e1e4420a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -128,7 +128,7 @@ ph-css.version=6.5.0 rhino.version=1.7.13 rsyntaxtextarea.version=3.1.6 Saxon-HE.version=11.2 -slf4j.version=1.7.32 +slf4j.version=1.7.36 spock-core.version=2.0-M2-groovy-3.0 springframework.version=4.3.17.RELEASE svgSalamander.version=1.1.2.4 diff --git a/src/dist/src/dist/expected_release_jars.csv b/src/dist/src/dist/expected_release_jars.csv index 52a4c466637..daecdda5b1c 100644 --- a/src/dist/src/dist/expected_release_jars.csv +++ b/src/dist/src/dist/expected_release_jars.csv @@ -74,7 +74,7 @@ 1534017,jackson-databind-2.13.1.jar 78030,javax.activation-1.2.0.jar 142391,jcharts-0.7.5.jar -16630,jcl-over-slf4j-1.7.32.jar +16555,jcl-over-slf4j-1.7.36.jar 490571,jmespath-core-0.5.1.jar 7066,jmespath-jackson-0.5.1.jar 403497,jodd-core-5.0.13.jar @@ -117,7 +117,7 @@ 1245900,rsyntaxtextarea-3.1.6.jar 5104409,Saxon-HE-11.2.jar 276420,serializer-2.7.2.jar -41513,slf4j-api-1.7.32.jar +41125,slf4j-api-1.7.36.jar 301279,svgSalamander-1.1.2.4.jar 10192,swing-extensions-laf-support-0.1.3.jar 2539,swing-extensions-visual-padding-0.1.3.jar diff --git a/xdocs/changes.xml b/xdocs/changes.xml index d144e20aa0d..708209ee4db 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -183,7 +183,7 @@ however, the profile can't be updated while the test is running.
  • Updated ktlint to 0.40.0
  • Updated PH CSS and PH commons to 6.5.4 and 10.1.6 (from 6.2.3 and 9.5.1).
  • Updated RSyntaxTextArea to 3.1.6 (from 3.1.1).
  • -
  • Updated SLF4J to 1.7.32 (from 1.7.30).
  • +
  • Updated SLF4J to 1.7.36 (from 1.7.30).
  • Updated SvgSalamander to 1.1.2.4 (from 1.1.2.1).
  • 698Updated Apache Tika to 1.28.1 (from 1.26).
  • Updated WireMock-JRE8 to 2.30.0 (from 2.24.1).
  • From a1e9ac7d15792800e39cb1a5307db31574e27b20 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Sat, 5 Mar 2022 15:45:39 +0100 Subject: [PATCH 072/736] Update Apache xmlgraphics commons to 2.7 --- gradle.properties | 2 +- src/dist/src/dist/expected_release_jars.csv | 2 +- xdocs/changes.xml | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/gradle.properties b/gradle.properties index 7d8e1e4420a..7668e03b0b3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -136,7 +136,7 @@ tika.version=1.28.1 xalan.version=2.7.2 xercesImpl.version=2.12.2 xml-apis.version=1.4.01 -xmlgraphics-commons.version=2.6 +xmlgraphics-commons.version=2.7 xmlpull.version=1.1.3.1 xpp3_min.version=1.1.4c xstream.version=1.4.19 diff --git a/src/dist/src/dist/expected_release_jars.csv b/src/dist/src/dist/expected_release_jars.csv index daecdda5b1c..d627e3d9648 100644 --- a/src/dist/src/dist/expected_release_jars.csv +++ b/src/dist/src/dist/expected_release_jars.csv @@ -128,7 +128,7 @@ 1446149,xercesImpl-2.12.2.jar 220536,xml-apis-1.4.01.jar 85686,xml-apis-ext-1.3.04.jar -674607,xmlgraphics-commons-2.6.jar +675889,xmlgraphics-commons-2.7.jar 7188,xmlpull-1.1.3.1.jar 1027759,xmlresolver-4.2.0-data.jar 150259,xmlresolver-4.2.0.jar diff --git a/xdocs/changes.xml b/xdocs/changes.xml index 708209ee4db..833fd2c63ba 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -191,6 +191,7 @@ however, the profile can't be updated while the test is running.
  • Updated jackson to 2.13.1 (from 2.10.5)
  • Updated jmespath to 0.5.1
  • Updated Saxon-HE to 11.2 (from 9.9.1-8)
  • +
  • Updated Apache xmlgraphics commons to 2.7 (from 2.6)
  • 671Move example definition of property jmeter.reportgenerator.statistic_window to user.properties, as it is read from that place. Contributed by Rithvik Patibandla (rithvikp98 at gmail.com)
  • From c8a47113d5316ca5d835c102abb650523ae4e16d Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Sat, 5 Mar 2022 15:54:50 +0100 Subject: [PATCH 073/736] Updated wiremock to 2.32.0 --- checksum.xml | 2 ++ gradle.properties | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/checksum.xml b/checksum.xml index 03092002e70..4d4bd139588 100644 --- a/checksum.xml +++ b/checksum.xml @@ -125,6 +125,8 @@ + + diff --git a/gradle.properties b/gradle.properties index 7668e03b0b3..2e58940a2bd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -140,4 +140,4 @@ xmlgraphics-commons.version=2.7 xmlpull.version=1.1.3.1 xpp3_min.version=1.1.4c xstream.version=1.4.19 -wiremock-jre8.version=2.30.0 +wiremock-jre8.version=2.32.0 From 0b34b4054a9674b6b37dc73f068421ebeda69235 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Sat, 5 Mar 2022 16:07:13 +0100 Subject: [PATCH 074/736] Update checkstyle to 9.3 The 10.x branch is Java 11 and higher, only. Suppress UnnecessaryParentheses for now, as we have quite a few of those and it seems to be new check. --- checksum.xml | 4 ++++ config/checkstyle/checkstyle-suppressions.xml | 1 + gradle.properties | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/checksum.xml b/checksum.xml index 4d4bd139588..f0b151d7995 100644 --- a/checksum.xml +++ b/checksum.xml @@ -82,6 +82,7 @@ + @@ -106,6 +107,7 @@ + @@ -165,6 +167,7 @@ + @@ -192,6 +195,7 @@ + diff --git a/config/checkstyle/checkstyle-suppressions.xml b/config/checkstyle/checkstyle-suppressions.xml index 87101fa1e2c..17e98efbfe3 100644 --- a/config/checkstyle/checkstyle-suppressions.xml +++ b/config/checkstyle/checkstyle-suppressions.xml @@ -28,4 +28,5 @@ files="test[\\/].*"/> + diff --git a/gradle.properties b/gradle.properties index 2e58940a2bd..6caea8bcf3b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -32,7 +32,7 @@ kotlin.code.style=official jmeter.version=5.5 # Tools -checkstyle.version=8.35 +checkstyle.version=9.3 errorprone.version=2.10.0 jacoco.version=0.8.7 ktlint.version=0.40.0 From cc62ec4921c14d6397418cb766b96038e2bb99cd Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Sat, 5 Mar 2022 17:32:22 +0100 Subject: [PATCH 075/736] Add notice for mxparser to README.md According to https://raw.githubusercontent.com/x-stream/mxparser/master/LICENSE.txt we have to put such a notice somewhere in the documentation. --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index a5703ea1cce..1255834304f 100644 --- a/README.md +++ b/README.md @@ -266,3 +266,11 @@ Apache JMeter does not include any implementation of JSSE or JCE. ## Thanks **Thank you for using Apache JMeter.** + +### Third party notices + +* Notice for mxparser: + + > This product includes software developed by the Indiana + > University Extreme! Lab. For further information please visit + > http://www.extreme.indiana.edu/ From d8a169e10f5d79ec1ee24d665f961f5be1972aa9 Mon Sep 17 00:00:00 2001 From: "Y. Z. Chen" <754097987@qq.com> Date: Sat, 5 Mar 2022 00:22:07 +0800 Subject: [PATCH 076/736] ci: use https://www.apache.org instead of http://www.eu.apache.org for downloading Maven --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e2f7c285a46..a10bff12ec7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -88,7 +88,7 @@ matrix: arch: s390x jdk: openjdk11 script: - - wget http://www.eu.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz + - wget https://www.apache.org/dist/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz - tar -xvzf apache-maven-3.6.3-bin.tar.gz - export PATH=`pwd`/apache-maven-3.6.3/bin/:$PATH - ./gradlew -PskipJavadoc publishToMavenLocal -Pjmeter.version=42.0 -PchecksumIgnore From 2bb940e230531cd7f07b6e1932b36b54724af16e Mon Sep 17 00:00:00 2001 From: "Y. Z. Chen" <754097987@qq.com> Date: Fri, 4 Mar 2022 08:12:54 +0800 Subject: [PATCH 077/736] (typo) in zh-CN translation. --- .../org/apache/jmeter/resources/messages_zh_CN.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/src/main/resources/org/apache/jmeter/resources/messages_zh_CN.properties b/src/core/src/main/resources/org/apache/jmeter/resources/messages_zh_CN.properties index 2ff829e4626..9ae4dfaa350 100644 --- a/src/core/src/main/resources/org/apache/jmeter/resources/messages_zh_CN.properties +++ b/src/core/src/main/resources/org/apache/jmeter/resources/messages_zh_CN.properties @@ -759,7 +759,7 @@ web_testing_basic=基本 web_testing_concurrent_download=并行下载. 数量: web_testing_embedded_url_pattern=网址必须匹配: web_testing_retrieve_images=从HTML文件获取所有内含的资源 -web_testing_retrieve_title=从HMTL文件嵌入资源 +web_testing_retrieve_title=从HTML文件嵌入资源 web_testing_source_ip=源地址 web_testing_source_ip_device=设备 web_testing_source_ip_device_ipv4=设备 IPv4 From 5e92589b10480c136f279e52df6873b8190e5cc4 Mon Sep 17 00:00:00 2001 From: "C.C" <709787793@qq.com> Date: Wed, 23 Feb 2022 17:24:34 +0800 Subject: [PATCH 078/736] Updated Chinese Simplified Translation Kept the ordering of the original file and deleted those new entries from #701, that can't be found in any other translation file or the sources. Closes #701 --- .../resources/messages_zh_CN.properties | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/core/src/main/resources/org/apache/jmeter/resources/messages_zh_CN.properties b/src/core/src/main/resources/org/apache/jmeter/resources/messages_zh_CN.properties index 9ae4dfaa350..3ac59dd129f 100644 --- a/src/core/src/main/resources/org/apache/jmeter/resources/messages_zh_CN.properties +++ b/src/core/src/main/resources/org/apache/jmeter/resources/messages_zh_CN.properties @@ -21,7 +21,7 @@ # # Please add new entries in alphabetical order -about=关于Apache JMeter +about=关于 Apache JMeter action_check_message=测试当前正在运行,停止或关闭测试以执行此命令 action_check_title=测试运行中 active_total_threads_tooltip=运行中线程数/运行线程总数 @@ -35,7 +35,7 @@ add_pattern=添加模式: add_test=添加测试 add_think_times=为子线程添加响应时间 add_user=添加用户 -add_value=添加数值 +add_value=添加值 addtest=添加测试 aggregate_graph=统计图表 aggregate_graph_choose_color=选择颜色 @@ -47,7 +47,7 @@ aggregate_graph_column_settings=列设置 aggregate_graph_columns_to_display=列显示: aggregate_graph_dimension=图表大小 aggregate_graph_display=显示图表 -aggregate_graph_draw_outlines=画出轮廓? +aggregate_graph_draw_outlines=绘制轮廓? aggregate_graph_dynamic_size=动态图形大小 aggregate_graph_font=字体: aggregate_graph_height=高度: @@ -56,9 +56,9 @@ aggregate_graph_legend=图例 aggregate_graph_legend.placement.bottom=底部 aggregate_graph_legend.placement.left=左 aggregate_graph_legend.placement.right=右 -aggregate_graph_legend.placement.top=上 +aggregate_graph_legend.placement.top=顶部 aggregate_graph_legend_placement=放置: -aggregate_graph_max_length_xaxis_label=X轴标签最大长度 +aggregate_graph_max_length_xaxis_label=X轴标签的最大长度 aggregate_graph_ms=毫秒 aggregate_graph_no_values_to_graph=没有要绘制的值 aggregate_graph_number_grouping=显示号码分组? @@ -443,7 +443,7 @@ httpmirror_title=HTTP镜像服务器 id_prefix=ID前缀 id_suffix=ID后缀 if_controller_label=条件 -if_controller_title=如果(If)控制器 +if_controller_title=IF 控制器 ignore_subcontrollers=忽略子控制器块 include_controller=Include控制器 include_equals=包含等于? @@ -574,7 +574,7 @@ post_as_parameters=参数 post_body=消息体数据 post_body_raw=消息体数据 post_files_upload=文件上传 -post_thread_group_title=tearDown线程组 +post_thread_group_title=tearDown 线程组 property_default_param=默认值 property_edit=编辑 property_editor.value_is_invalid_title=无效输入 @@ -637,7 +637,7 @@ sampler_on_error_start_next_loop=启动下一进程循环 sampler_on_error_stop_test=停止测试 sampler_on_error_stop_test_now=立即停止测试 sampler_on_error_stop_thread=停止线程 -save=保存测试计划 +save=保存 save?=保存? save_all_as=保存测试计划为 save_as=选中部分保存为... @@ -661,7 +661,7 @@ send_file_param_name_label=参数名称: server=服务器名称或IP: servername=服务器名称: session_argument_name=会话参数名称: -setup_thread_group_title=setUp线程组 +setup_thread_group_title=setUp 线程组 shutdown=关闭 simple_config_element=简单配置元件 simple_data_writer_title=简单数据写入器 @@ -695,7 +695,7 @@ tcp_port=端口号: tcp_request_data=要发送的文本 tcp_sample_title=TCP取样器 tcp_timeout=超时: -teardown_on_shutdown=主线程结束后运行 tearDown线程组 +teardown_on_shutdown=主线程结束后运行 tearDown 线程组 template_field=模板: template_menu=模板... test=测试 @@ -738,13 +738,13 @@ username=用户名 validate_threadgroup=验证 value=值 var_name=引用名称 -view_graph_tree_title=察看结果树 -view_results_in_table=用表格察看结果 +view_graph_tree_title=查看结果树 +view_results_in_table=用表格查看结果 view_results_tab_request=请求 view_results_tab_response=响应数据 view_results_tab_sampler=取样器结果 -view_results_title=察看结果 -view_results_tree_title=察看结果树 +view_results_title=查看结果 +view_results_tree_title=查看结果树 web_proxy_server_title=代理服务器 web_request=HTTP请求 web_server=Web服务器 From 4ea72b5028e3eeac531777496a3a6349064a9fe8 Mon Sep 17 00:00:00 2001 From: shblue21 Date: Mon, 21 Feb 2022 13:32:29 +0900 Subject: [PATCH 079/736] Write graphite guide in realtime section write graphite setting, in realtime section, with simple pickle protocol Closes #699 --- xdocs/changes.xml | 2 ++ .../screenshots/backend_listener_graphite.png | Bin 0 -> 5760 bytes .../backend_listener_graphite_pickle.png | Bin 0 -> 1929 bytes xdocs/usermanual/realtime-results.xml | 16 ++++++++++++++-- 4 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 xdocs/images/screenshots/backend_listener_graphite.png create mode 100644 xdocs/images/screenshots/backend_listener_graphite_pickle.png diff --git a/xdocs/changes.xml b/xdocs/changes.xml index 833fd2c63ba..f72c51cf411 100644 --- a/xdocs/changes.xml +++ b/xdocs/changes.xml @@ -145,6 +145,7 @@ however, the profile can't be updated while the test is running.
  • 65611673Add support for IPv6 addresses when specifying a remote worker node. Based on a patch by Peter Wong (peter.wong at csexperts.com)
  • Reduce memory consumption by the logging panel (disable undo events for it)
  • 63620694Fix GUI freeze when viewing response body with long line breaks
  • +
  • 699Add documentation for Graphite Backend Listener. Contributed by Ji Hun (jihunkimkw at gmail.com)
  • Non-functional changes @@ -304,6 +305,7 @@ however, the profile can't be updated while the test is running.
  • Magnus Spångdal (magnus.spangdal as avanza.se)
  • Piotr Smietana (piotrsmietana1998 at gmail.com)
  • Sampath Kumar Krishnasamy (sampathkumar.krishnasamykuppusamy at aexp.com)
  • +
  • Ji Hun (jihunkimkw at gmail.com)
  • We also thank bug reporters who helped us improve JMeter.

      diff --git a/xdocs/images/screenshots/backend_listener_graphite.png b/xdocs/images/screenshots/backend_listener_graphite.png new file mode 100644 index 0000000000000000000000000000000000000000..d952b22354b79636c888c79df69d1d3aee057141 GIT binary patch literal 5760 zcmaht2|SeDyMqwbkQU0QFNF$2DrUykLS;!2g_(rNF1)r7O15Nt*=a_LEn6aH3@R#A zc*njD2Ju?QZZMcT`o90Y|9kIufA@FZ_x+vooaemHdG_a=$m<4|cL^R8gu!6DbgpO_ z!C*W9494|nI}ZoKG7{qqVB74@Up)_l6~*jWx8miDxd5Zf7hvx|#5iXl;C97~gCyd) z^>X#!JM7B=8ei8p)@HNWgAEL?{g=q^8_@@V(HE5Y$x z^n_!vFc<`LgKs?$>{Tz?EF#JAAtULy-h|ha48HBexQB#21fKVx3uP_>2oZ;^*g(3W zKV)aA z`80OXz7>i` z@e8A&3qSL*I=R=%2{+E(14fo8K0LY6*PK|mlipfs#S3nLKBXS4Rx)D zJuN26Wq7ThfF`1zMq2q!6?+}b?;Oy*YZf2Eqk8L&?lkRtgByl~3vfh{pWduXG>SA$ zy`@aR-n~+he|(M$58?Jp=-_!1c0o23X?oFJN-3cvLa%8eXvwRLQ_|`;6{^v}R?yIF z(NWSbKREpqCOrI*-Sa(gd)hEQ+k$zUbYuA+m2zzm0k4ypAnH-nl#{032P z+$itz?He!09`;0Hh*-#TMf}jE*&AP)3$C{3+%z^EI4a=k*c5ioC|r^!?^#kv^##i~ z>d1T~p+dvoVHj=JR4QfPH>@BA#prcGznv z_YSQuB|I&h@5r^1YB|k{5H$5bG(g$3W7Mk%ly5A`ltl}+ z#W}I>W1_TqUI{=eI@pFO*il6fY1I$<5g7&07v|gcSZ<3G*N$uY)(K49x7Mqo6s&$r zU;Zu^C~}b5d9%Vc;4Yp8%s%P_d|d4&6&}EO=@jsX#tkwZK}T?eMn}NFK}1yscuG<* z;7p+p637anh7~Qt#0Eq-8S7t3>p#2y4de#LUpaf>KDFhT7+4)ctlt3s5a9ext&!sQ zq{)wV{j9%HdI%*mTLzZpm zvx*NDFQ>dXkP{o%B?8f3`ys=Rq!+Xo6Kkbzv=1Vt#t@wVil6FI##c*p zoFf6)Z{2Y||E0sfy0a(1Q`2%)40|Zq+xwHipj9!Vbs_Rj#3{QFxfjSfH#kRxFvtzQ z)xIkcR7H$7q5$AtDxHSwmO+IBC}z);YCijbQt9CB44v-LEF zXof^tg-hxLRbR%B)N4xudm!nzkeh2i4O@q}1ri;%l>?<%ix2s~x(|GqS_gGZsm);? zEA?(zs=K;M2r$WuC>pU@y;t}#Qa<}f1x`9Pmyq5!zp{FBUjK==UKM&PFa2&`IbF`+ zD33ebViIvQs8J`suw#ete2A%neEuDrEP;*GZwhF@@xkshog_b3&L~nXmH4?OV-t zQ(9iiXRkT&WnmOdI*eyBkPVY}ViQv@Nr2^1W2jhJ+X?{ zC{TTNX?ohWAUf%=N%`DYmpFQSqg5qrxDccBX*Z z4|GCDj)4tvwx1H4bka#H!RqtK8c)$Ku|f9;v&wN=-{ZHb`uT8v*`^oZk7b7=DXka2 zdH{U-(F&CWserwR($t^)=!)>@4P%X+G2U$xi)c`&9iqb+Pl7dY!^^!iLk+h$cu^sMFcLg;>lkQBgmQu5fPh|DAC_5_SkDlDC zWFh>p!nPguAcI?C;N>31>#G4l24SaX-lHq8oex-`?y}bN373FI-I0NN@9K^$%SMC) z@Oy<2osJIUINg0OIBZOlzYX}77!1sELw@Dr66HsxzJa_{qXeNvRV6zONCcDsDQne1 z5B=JxhM8LI=!+PYwxD;v-cI}RDgf^$a=bdxNl;_l<+j7vRwX}35PcqE|S7yXPwd&Uzy<1k3G=>&2TO@h4o4zir+ij~oGgIico zxxlSPY(>Lfu@Tp)yRqD0bs8A?av^t)aIuMq@6}?d%0%Nra)_sWD#Q=y`jij10ms(W zKobc__Znpgw`!mAQ$Kp3@@ABEV#dxXEcM4)yoEYHy(jOv4Tc2F-Dr%$jB>rd>4RbW zN_T%M1fn79&OdnJx2awjQQUY6!xP2);)i6gtDnisxVcWN*xh@uS9K{0D`N2rr{mlA zWA|tQWE3EhU|(F#Ci_U6yAGX$wM|uKw1S7auPU+GIV@-7ZJd$#j;x6qz7Pkpq2n>d z3vGZx4unYWx2QsAf7q4O&G0OdcffwR1jRQ0s#IFsKSITp|51A!Ar+pcGn&*xC>VLsI(!sj0^T2ae+VUD`h`nL09V|Bg!oiI9@(P zFruFAC3)iEYBHK>F93t~&yBbIF7gR(*hBHdlsK~dSNG^vQsxeVxXPQVI~}B*{wR5z{tvUG#X^(1}(9}K6C^d@o=+WSew zQ>0I7)PxeTkio&Mo5SI#%-k-zj(R|-PJ>Cc&yDSTli5v zw!c#)3^JHOz?y>KZz20Fi;N?-Hj;T(3^@x z8f8lHUK~(uauO+a@>p5fg9+>G!K}saAH4B%5ON5I(ZPtW+zRC-*Zb&*R`~8#pMN%q zu6+3lvFA)JNGyoK z4Q3|j=RaoZiV|)>W6ynXy|H~>nZuNIm}h+*@ETbB?*9gOrs-o2)gD!Pv5?q5hftqS z>mk{!Qx-7feYXS5gt-KXAyhhU6ehtb3es@Dop2CA0RMKvX3{o7NILOGV7BXb$}brT zeUk~!rT1wQ090oL@FP=Z^X&UgZlr-jD`j)&&-a(H?_bRn)YuBSV8|_ppISRMQE)M& z6yErItxJT?l8pGCchEd?WHZ@=*FzR`z}*CP*yGPk;o97h47BJ{K)TCn4{+Q)=1#Qg z#T*~0GbLCmr7R6t^+Tcxx$9JuoX}t&D%!|#(-#~OqM_1Mzs}Ltx$X1P^e|w}j(CQ7 zL8<((h&c|nizGkj=~5pmts(Uk2nJAfONpW$zm07_fhYJbi~5i!7~-6De;2|3Rzq=>={A1FI2 zuoC|V={;?LUtQ32!Ro<$v(-Gc&~ZCCj^d!QT zXq>~maYZVu1bo0<=CAu)HO zb%W~2JfqhgVbftZQWV zsP|=mwZYAsQl>kPX+D9+^+dBm$!^nscFuCON^fRhHFyV7Zj|3ySI;10b&h{*mwJ_F zwI$r4dQszwY*xujnq7G}qdhB6I!k!dd8Bq2S8~r>)kWe{O|QqwA(n?OQ%^bk@%4QI zV~)QSwW6fn&KP(9{;t2CIoM9h<6-$QW2{IX!|q7)(*+Nityg6>nO#X7l9lRhR0iB6 zv1&!W-|Os_tZ@P8a!2N3vbO@OuEg!D$!s6{!V;;p%a;(4&wJ+T)+>?gz11bk)O2vh`ZHied5hCsO^SiGKdg%IG zO8xq-kn9r^7Nfzg5vtp=7KypHR$(c1Hl`gLQO_xg!=%j&kKxUlWFmWeqQN-47k}sS zhP}T>%VJ!J`l7$n+aotO7gVH$r!rP&9&HiL`^(yF3?Du)kbQkmY46`wSonXy&Hll_ zJ||qcDpvHPdhb`l&kK>Z)pT44xbarY@k_*2c$V0x@qS&o9emJ1Pe$QCSmI{RKOoNh t6Jq}VM#TGP12dlgy6fWjHZ-d#3Ud-NlKtAixgdt=Xd7s~yI}eFKLC*}X{rDK literal 0 HcmV?d00001 diff --git a/xdocs/images/screenshots/backend_listener_graphite_pickle.png b/xdocs/images/screenshots/backend_listener_graphite_pickle.png new file mode 100644 index 0000000000000000000000000000000000000000..a314543b675ba0bcf5ed1142bd0af00de477c720 GIT binary patch literal 1929 zcmV;42X^?0P)Px#32;bRa{vGmbN~PnbOGLGA9w%&01Qw}R7L;)|9Xm< z?(Xh0Gc(0Di&Fpq2L?$*K~#9!?VZnx<2Vq;3+h^+R}tiDP$0KuVNd%A`yTrU%fcRZ zA0dJ6dj@(7bPe=-q+t>CZ7}1llJZBH?vCvt8QFtOkK0LG)-THE(&w_|f%V*$-=QK` zmPf~H+8OsfSAgYC4S3m+gm0c{1@w2CaHIz^7c5CC~C!iakWIYdHs z3Aqz2%Z7a?pLSHuIWitTE68UBEhsC?@m=@;Ikg00Y;V+3(xyTkg(2scV8!yNhe*h& zh#p+_){WyAG_>Yi%VIk%6&d=4!BiMI_sfH{ zEM~qia_*NkVsPj|Hgat&*T;G>Tq-V)_sgYwzwv&#dW`Cqt6#2u*=y#v{~~|cYV5{I zAY;n>_93rg4{3@b=YCnbwC5h*zMKGZ?w2(i%tMeDMUivA95h4OgG`e^KKW%BitGy` zpZ)R>xU81Xet8HoD>4?27-zo>VuE`j#;Th@T&{k(dW`Cqt6%=nwM^&n5V2ot zuf*lJ=JLpw;~}uOmCGXU9JDSU53zG*_i?wqqM$kGmbe_U-pS9$L+I^h`q*5qk|9A; zu$B3Q9LGa+%-4~V`9vy@d>jwKz?}|exrXe5j;1Kz%E$2#z>IyZ3?7OjXX7DY2Evet zVb0?r1lb{7ix_%yLLvs0LmpXRHNOt~=jt)4U#@<+YWc7j?jPJx=nmya$kz5Dub@1# zLlg_V@T>!jnHIde+OPfMgLT&~TfRq!9dmL`BNk&P$c?>@yozR|Y=SEeWYuw{;8BOX zT5qolgLLd`abZMcHw+nD>#!?(`uPJg4?|9NxwMuOviEX%ZTm9JD{6{s+39@;MQ#My za4$0Mibst675678Cf561PF$%Tqx$9Qm#Z*7M2?|NbIde1WS9Z6bY<$7nOoBPtK7QD zBOm;-ri`QG!Rfa$10FMj1pPV9X$T|PBHs~4Va(w4JD5*xUL7Mo2Vr>8@L}@aOtkFa zRaj%hz~EYL%}nC*;M_z-u70`t@iI}@GA-$k<#Z6hFU^4k-dpSwj(gkv! z+n7RrS-L$;^LDHwdPcyohy$4oHu7udq?NNtfD_3tA7)1d_BMz+62k%3hT!AVEjT^h z;MB@f$S*6TYt!R6|nf$V)T+52At?U!|S6ZGxe)(<05G@;J)rcX& z=yus8z-i@|EnMc7aq=B@d@j?xkgF}Ke!2SPV#w4pY5agJQ5+m}VAz#M9yBUh=lg+p zkpUBZ?uPsfEyckY&T2n61lb-s@lwb^6U#OlikPn*)XKgs*~-xtK^m(%VDRb6#K+zt zh=VGJ+zCV%k-L6jEMH~sMtr}qO*v#p51fe)d+TlHWfTveW=Is$a=M%wrDZG~F;E}k zW(GwJjmv77sbE|l*;Gpya(A#ISHE2S@&Ld5&;0%$sft{YD{@8tfsy|QvXu`VJ}D&Y P00000NkvXXu0mjf0G6^h literal 0 HcmV?d00001 diff --git a/xdocs/usermanual/realtime-results.xml b/xdocs/usermanual/realtime-results.xml index 3ba3d7c4254..5fc95380a81 100644 --- a/xdocs/usermanual/realtime-results.xml +++ b/xdocs/usermanual/realtime-results.xml @@ -186,10 +186,22 @@ InfluxDB data can be easily viewed in a browser through Grafana dashboard - -

      HELP WELCOME for this section, see Contributing documentation

      + +

      To make JMeter send metrics to backend, add a BackendListener using the GraphiteBackendListenerClient.

      +

      GraphiteBackendListenerClient section will help you do the configuration.

      +
      Graphite configuration
      + +

      Two types of Senders are available. TextGraphiteMetricsSender, PickleGraphiteMetricsSender

      +
        +
      • For plaintext protocol, set graphiteMetricsSender parameter to org.apache.jmeter.visualizers.backend.graphite.TextGraphiteMetricsSender
      • +
      • For pickle protocol, set graphiteMetricsSender parameter to org.apache.jmeter.visualizers.backend.graphite.PickleGraphiteMetricsSender
      • +
      +

      To send large amounts of data, use the Pickle sender. It is an efficient transmission method compared to textplain. + Read this for more details Graphite documentation.

      +
      Graphite pickle sender
      +
      From 9c16f2fdb32e352efd8dbefb5de1c31390300a7a Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Sat, 5 Mar 2022 20:58:06 +0100 Subject: [PATCH 080/736] Rephrase docs a bit Don't use 'here' or similar as link text. Remove space at the end of line. --- xdocs/usermanual/realtime-results.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xdocs/usermanual/realtime-results.xml b/xdocs/usermanual/realtime-results.xml index 5fc95380a81..ef01051cc29 100644 --- a/xdocs/usermanual/realtime-results.xml +++ b/xdocs/usermanual/realtime-results.xml @@ -197,9 +197,9 @@ InfluxDB data can be easily viewed in a browser through Graphite documentation.

      +
    +

    To send large amounts of data, use the Pickle sender. It is a more efficient transmission method compared to textplain. + Read the Graphite documentation for more details.

    Graphite pickle sender
    From 197b727ffced485376e3f2812b97281390d15f9f Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Mon, 21 Feb 2022 20:40:11 +0100 Subject: [PATCH 081/736] Use isEmpty instead of comparing length to zero --- .../java/org/apache/jmeter/visualizers/RenderAsRegexp.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/src/main/java/org/apache/jmeter/visualizers/RenderAsRegexp.java b/src/components/src/main/java/org/apache/jmeter/visualizers/RenderAsRegexp.java index f598e0a1efa..c3c35483483 100644 --- a/src/components/src/main/java/org/apache/jmeter/visualizers/RenderAsRegexp.java +++ b/src/components/src/main/java/org/apache/jmeter/visualizers/RenderAsRegexp.java @@ -100,8 +100,8 @@ public void actionPerformed(ActionEvent e) { * @param textToParse */ private void executeAndShowRegexpTester(String textToParse) { - if (textToParse != null && textToParse.length() > 0 - && this.regexpField.getText().length() > 0) { + if (textToParse != null && !textToParse.isEmpty() + && !this.regexpField.getText().isEmpty()) { this.regexpResultField.setText(process(textToParse)); this.regexpResultField.setCaretPosition(0); // go to first line } From 18f4da2e65660d0f5f0c8c711213f804e00aef48 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Mon, 21 Feb 2022 20:58:54 +0100 Subject: [PATCH 082/736] Add a switch to decide which regex engine should be used --- .../jmeter/visualizers/RenderAsRegexp.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/components/src/main/java/org/apache/jmeter/visualizers/RenderAsRegexp.java b/src/components/src/main/java/org/apache/jmeter/visualizers/RenderAsRegexp.java index c3c35483483..d3f8f70b7b6 100644 --- a/src/components/src/main/java/org/apache/jmeter/visualizers/RenderAsRegexp.java +++ b/src/components/src/main/java/org/apache/jmeter/visualizers/RenderAsRegexp.java @@ -24,6 +24,8 @@ import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.PatternSyntaxException; import javax.swing.BoxLayout; import javax.swing.JButton; @@ -65,6 +67,8 @@ public class RenderAsRegexp implements ResultRenderer, ActionListener { private JTabbedPane rightSide; + private boolean useJavaRegex = JMeterUtils.getPropDefault("jmeter.use_java_regex", false); + /** {@inheritDoc} */ @Override public void clearData() { @@ -108,7 +112,40 @@ private void executeAndShowRegexpTester(String textToParse) { } private String process(String textToParse) { + if (useJavaRegex) { + return processJavaRegex(textToParse); + } + return processOroRegex(textToParse); + } + private String processJavaRegex(String textToParse) { + java.util.regex.Pattern pattern; + try { + pattern = java.util.regex.Pattern.compile(regexpField.getText()); + } catch (PatternSyntaxException e) { + return e.toString(); + } + Matcher matcher = pattern.matcher(textToParse); + List matches = new ArrayList<>(); + while (matcher.find()) { + matches.add(matcher.toMatchResult()); + } + + // Construct a multi-line string with all matches + StringBuilder sb = new StringBuilder(); + final int size = matches.size(); + sb.append("Match count: ").append(size).append("\n"); + for (int j = 0; j < size; j++) { + java.util.regex.MatchResult mr = matches.get(j); + final int groups = mr.groupCount(); + for (int i = 0; i < groups; i++) { + sb.append("Match[").append(j+1).append("][").append(i).append("]=").append(mr.group(i)).append("\n"); + } + } + return sb.toString(); + } + + private String processOroRegex(String textToParse) { Perl5Matcher matcher = new Perl5Matcher(); PatternMatcherInput input = new PatternMatcherInput(textToParse); @@ -123,6 +160,7 @@ private String process(String textToParse) { while (matcher.contains(input, pattern)) { matches.add(matcher.getMatch()); } + // Construct a multi-line string with all matches StringBuilder sb = new StringBuilder(); final int size = matches.size(); From cc792fb6dc4332571b7300eb9e3075de3d68d3a5 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Mon, 21 Feb 2022 21:04:17 +0100 Subject: [PATCH 083/736] Use isEmpty instead of comparing length to zero --- .../java/org/apache/jmeter/assertions/ResponseAssertion.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/src/main/java/org/apache/jmeter/assertions/ResponseAssertion.java b/src/components/src/main/java/org/apache/jmeter/assertions/ResponseAssertion.java index ce7201398a4..ea559e2b39e 100644 --- a/src/components/src/main/java/org/apache/jmeter/assertions/ResponseAssertion.java +++ b/src/components/src/main/java/org/apache/jmeter/assertions/ResponseAssertion.java @@ -533,7 +533,7 @@ private static StringBuilder equalsComparisonText(final String received, final S String compDeltaSeq; String endingEqSeq = trunc(true, received.substring(lastRecDiff + 1, recLength)); String recDeltaSeq; - if (endingEqSeq.length() == 0) { + if (endingEqSeq.isEmpty()) { recDeltaSeq = trunc(true, received.substring(firstDiff, recLength)); compDeltaSeq = trunc(true, comparison.substring(firstDiff, compLength)); } else { From a9f512732fc3bfa7c75ce711c09dcdb79baa1d5d Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Mon, 21 Feb 2022 21:16:28 +0100 Subject: [PATCH 084/736] Add a switch to decide which regex engine should be used --- .../jmeter/assertions/ResponseAssertion.java | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/src/components/src/main/java/org/apache/jmeter/assertions/ResponseAssertion.java b/src/components/src/main/java/org/apache/jmeter/assertions/ResponseAssertion.java index ea559e2b39e..fa82744777d 100644 --- a/src/components/src/main/java/org/apache/jmeter/assertions/ResponseAssertion.java +++ b/src/components/src/main/java/org/apache/jmeter/assertions/ResponseAssertion.java @@ -21,6 +21,7 @@ import java.net.URL; import java.util.ArrayList; import java.util.List; +import java.util.regex.PatternSyntaxException; import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; @@ -94,6 +95,8 @@ public class ResponseAssertion extends AbstractScopedAssertion implements Serial private static final String DIFF_DELTA_END = JMeterUtils.getPropDefault("assertion.equals_diff_delta_end", "]]]"); + private boolean useJavaRegex = JMeterUtils.getPropDefault("jmeter.use_java_regex", false); + public ResponseAssertion() { setProperty(new CollectionProperty(TEST_STRINGS, new ArrayList())); } @@ -326,19 +329,27 @@ private AssertionResult evaluateResponse(SampleResult response) { List allCheckMessage = new ArrayList<>(); for (JMeterProperty jMeterProperty : getTestStrings()) { String stringPattern = jMeterProperty.getStringValue(); - Pattern pattern = null; - if (contains || matches) { - pattern = JMeterUtils.getPatternCache().getPattern(stringPattern, Perl5Compiler.READ_ONLY_MASK); - } boolean found; if (contains) { - found = localMatcher.contains(toCheck, pattern); + if (useJavaRegex) { + found = containsWithJavaRegex(toCheck, stringPattern); + } else { + Pattern pattern = JMeterUtils.getPatternCache() + .getPattern(stringPattern, Perl5Compiler.READ_ONLY_MASK); + found = localMatcher.contains(toCheck, pattern); + } } else if (equals) { found = toCheck.equals(stringPattern); } else if (substring) { found = toCheck.contains(stringPattern); } else { - found = localMatcher.matches(toCheck, pattern); + if (useJavaRegex) { + found = matchesWithJavaRegex(toCheck, stringPattern); + } else { + Pattern pattern = JMeterUtils.getPatternCache() + .getPattern(stringPattern, Perl5Compiler.READ_ONLY_MASK); + found = localMatcher.matches(toCheck, pattern); + } } boolean pass = notTest ? !found : found; if (orTest) { @@ -375,7 +386,7 @@ private AssertionResult evaluateResponse(SampleResult response) { result.setFailureMessage(customMsg); } } - } catch (MalformedCachePatternException e) { + } catch (MalformedCachePatternException | PatternSyntaxException e) { result.setError(true); result.setFailure(false); result.setFailureMessage("Bad test configuration " + e); @@ -383,6 +394,14 @@ private AssertionResult evaluateResponse(SampleResult response) { return result; } + private static boolean matchesWithJavaRegex(String toCheck, String stringPattern) { + return java.util.regex.Pattern.compile(stringPattern).matcher(toCheck).matches(); + } + + private static boolean containsWithJavaRegex(String toCheck, String stringPattern) { + return java.util.regex.Pattern.compile(stringPattern).matcher(toCheck).find(); + } + private String getStringToCheck(SampleResult response) { String toCheck; // The string to check (Url or data) // What are we testing against? From 046ebacadbd7bc23273fc854661aa02628ad7381 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Mon, 21 Feb 2022 21:20:32 +0100 Subject: [PATCH 085/736] Add a switch to decide which regex engine should be used --- .../apache/jmeter/assertions/JSONPathAssertion.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/components/src/main/java/org/apache/jmeter/assertions/JSONPathAssertion.java b/src/components/src/main/java/org/apache/jmeter/assertions/JSONPathAssertion.java index 98aeca67250..cd9f36538ae 100644 --- a/src/components/src/main/java/org/apache/jmeter/assertions/JSONPathAssertion.java +++ b/src/components/src/main/java/org/apache/jmeter/assertions/JSONPathAssertion.java @@ -51,6 +51,8 @@ public class JSONPathAssertion extends AbstractTestElement implements Serializab public static final String INVERT = "INVERT"; public static final String ISREGEX = "ISREGEX"; + private boolean useJavaRegex = JMeterUtils.getPropDefault("jmeter.use_java_regex", false); + private static ThreadLocal decimalFormatter = ThreadLocal.withInitial(JSONPathAssertion::createDecimalFormat); @@ -164,8 +166,12 @@ private boolean arrayMatched(JSONArray value) { private boolean isEquals(Object subj) { if (isUseRegex()) { String str = objectToString(subj); - Pattern pattern = JMeterUtils.getPatternCache().getPattern(getExpectedValue()); - return JMeterUtils.getMatcher().matches(str, pattern); + if (useJavaRegex) { + return java.util.regex.Pattern.matches(getExpectedValue(), str); + } else { + Pattern pattern = JMeterUtils.getPatternCache().getPattern(getExpectedValue()); + return JMeterUtils.getMatcher().matches(str, pattern); + } } else { Object expected = JSONValue.parse(getExpectedValue()); return Objects.equals(expected, subj); From d69f4b91a96b9a500a835c5a765e2aead6a4a86e Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Mon, 21 Feb 2022 21:23:10 +0100 Subject: [PATCH 086/736] Add a switch to decide which regex engine should be used --- .../jmeter/assertions/jmespath/JMESPathAssertion.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/components/src/main/java/org/apache/jmeter/assertions/jmespath/JMESPathAssertion.java b/src/components/src/main/java/org/apache/jmeter/assertions/jmespath/JMESPathAssertion.java index 0cf46bdab98..4e078c75f86 100644 --- a/src/components/src/main/java/org/apache/jmeter/assertions/jmespath/JMESPathAssertion.java +++ b/src/components/src/main/java/org/apache/jmeter/assertions/jmespath/JMESPathAssertion.java @@ -58,6 +58,8 @@ public class JMESPathAssertion extends AbstractTestElement implements Serializab private static final String ISREGEX = "ISREGEX"; private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + private boolean useJavaRegex = JMeterUtils.getPropDefault("jmeter.use_java_regex", false); + /** * Used to do a JMESPath query and compute result if the expectedValue matches * with the JMESPath query result @@ -177,8 +179,12 @@ public static String objectToString(ObjectMapper mapper, JsonNode element) throw private boolean isEquals(ObjectMapper mapper, JsonNode jsonNode) throws JsonProcessingException { String str = objectToString(mapper, jsonNode); if (isUseRegex()) { - Pattern pattern = JMeterUtils.getPatternCache().getPattern(getExpectedValue()); - return JMeterUtils.getMatcher().matches(str, pattern); + if (useJavaRegex) { + return java.util.regex.Pattern.matches(getExpectedValue(), str); + } else { + Pattern pattern = JMeterUtils.getPatternCache().getPattern(getExpectedValue()); + return JMeterUtils.getMatcher().matches(str, pattern); + } } else { String expectedValueString = getExpectedValue(); // first try to match as a string value, as From 0e22677d83aca8d96b6873ce40cf0fbcf89e2542 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Mon, 21 Feb 2022 21:31:49 +0100 Subject: [PATCH 087/736] Add a switch to decide which regex engine should be used --- .../jmeter/assertions/CompareAssertion.java | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/components/src/main/java/org/apache/jmeter/assertions/CompareAssertion.java b/src/components/src/main/java/org/apache/jmeter/assertions/CompareAssertion.java index 96d78ba6083..dd63482ffc3 100644 --- a/src/components/src/main/java/org/apache/jmeter/assertions/CompareAssertion.java +++ b/src/components/src/main/java/org/apache/jmeter/assertions/CompareAssertion.java @@ -48,6 +48,8 @@ public class CompareAssertion extends AbstractTestElement implements Assertion, private Collection stringsToSkip; + private boolean useJavaRegex = JMeterUtils.getPropDefault("jmeter.use_java_regex", false); + public CompareAssertion() { super(); } @@ -155,17 +157,25 @@ private String filterString(final String content) { return content; } - String result = content; - for (SubstitutionElement regex : stringsToSkip) { - emptySub.setSubstitution(regex.getSubstitute()); - result = Util.substitute( - JMeterUtils.getMatcher(), - JMeterUtils.getPatternCache().getPattern(regex.getRegex()), - emptySub, - result, - Util.SUBSTITUTE_ALL); + if (useJavaRegex) { + String result = content; + for (SubstitutionElement element: stringsToSkip) { + result = result.replaceAll(element.getRegex(), element.getSubstitute()); + } + return result; + } else { + String result = content; + for (SubstitutionElement regex : stringsToSkip) { + emptySub.setSubstitution(regex.getSubstitute()); + result = Util.substitute( + JMeterUtils.getMatcher(), + JMeterUtils.getPatternCache().getPattern(regex.getRegex()), + emptySub, + result, + Util.SUBSTITUTE_ALL); + } + return result; } - return result; } @Override From b73c0c354cb241a5f77da5fdfe3f52fdcab43bd0 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Mon, 21 Feb 2022 21:34:34 +0100 Subject: [PATCH 088/736] Use isEmpty instead of comparing length to zero --- .../java/org/apache/jmeter/extractor/RegexExtractor.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/src/main/java/org/apache/jmeter/extractor/RegexExtractor.java b/src/components/src/main/java/org/apache/jmeter/extractor/RegexExtractor.java index 6513311c6b9..aa3e17c28bb 100644 --- a/src/components/src/main/java/org/apache/jmeter/extractor/RegexExtractor.java +++ b/src/components/src/main/java/org/apache/jmeter/extractor/RegexExtractor.java @@ -49,6 +49,7 @@ public class RegexExtractor extends AbstractScopedTestElement implements PostPro // What to match against. N.B. do not change the string value or test plans will break! private static final String MATCH_AGAINST = "RegexExtractor.useHeaders"; // $NON-NLS-1$ + /* * Permissible values: * true - match against headers @@ -104,7 +105,7 @@ public void process() { int matchNumber = getMatchNumber(); final String defaultValue = getDefaultValue(); - if (defaultValue.length() > 0 || isEmptyDefaultValue()) {// Only replace default if it is provided or empty default value is explicitly requested + if (!defaultValue.isEmpty() || isEmptyDefaultValue()) {// Only replace default if it is provided or empty default value is explicitly requested vars.put(refName, defaultValue); } @@ -479,7 +480,7 @@ public boolean useRequestHeaders() { // Allow for property not yet being set (probably only applies to Test cases) public boolean useBody() { String prop = getPropertyAsString(MATCH_AGAINST); - return prop.length()==0 || USE_BODY.equalsIgnoreCase(prop);// $NON-NLS-1$ + return prop.isEmpty() || USE_BODY.equalsIgnoreCase(prop);// $NON-NLS-1$ } public boolean useUnescapedBody() { From 8768b868242f68e0f4a353b134a6308140973825 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Mon, 21 Feb 2022 21:52:19 +0100 Subject: [PATCH 089/736] Add a switch to decide which regex engine should be used --- .../jmeter/extractor/RegexExtractor.java | 174 ++++++++++++++++++ 1 file changed, 174 insertions(+) diff --git a/src/components/src/main/java/org/apache/jmeter/extractor/RegexExtractor.java b/src/components/src/main/java/org/apache/jmeter/extractor/RegexExtractor.java index aa3e17c28bb..7ec7cdcec78 100644 --- a/src/components/src/main/java/org/apache/jmeter/extractor/RegexExtractor.java +++ b/src/components/src/main/java/org/apache/jmeter/extractor/RegexExtractor.java @@ -21,6 +21,8 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.PatternSyntaxException; import org.apache.commons.text.StringEscapeUtils; import org.apache.jmeter.processor.PostProcessor; @@ -81,6 +83,8 @@ public class RegexExtractor extends AbstractScopedTestElement implements PostPro private static final boolean DEFAULT_VALUE_FOR_DEFAULT_EMPTY_VALUE = false; + private boolean useJavaRegex = JMeterUtils.getPropDefault("jmeter.use_java_regex", false); + private transient List template; /** @@ -109,6 +113,14 @@ public void process() { vars.put(refName, defaultValue); } + if (useJavaRegex) { + extractWithJavaRegex(previousResult, vars, refName, matchNumber); + } else { + extractWithOroRegex(previousResult, vars, refName, matchNumber); + } + } + + private void extractWithOroRegex(SampleResult previousResult, JMeterVariables vars, String refName, int matchNumber) { Perl5Matcher matcher = JMeterUtils.getMatcher(); String regex = getRegex(); Pattern pattern = null; @@ -167,6 +179,62 @@ public void process() { } } + private void extractWithJavaRegex(SampleResult previousResult, JMeterVariables vars, String refName, int matchNumber) { + String regex = getRegex(); + java.util.regex.Pattern pattern = null; + try { + pattern = java.util.regex.Pattern.compile(regex); + List matches = processMatches(pattern, previousResult, matchNumber, vars); + int prevCount = 0; + String prevString = vars.get(refName + REF_MATCH_NR); + if (prevString != null) { + vars.remove(refName + REF_MATCH_NR);// ensure old value is not left defined + try { + prevCount = Integer.parseInt(prevString); + } catch (NumberFormatException nfe) { + log.warn("Could not parse number: '{}'", prevString); + } + } + int matchCount=0;// Number of refName_n variable sets to keep + try { + java.util.regex.MatchResult match; + if (matchNumber >= 0) {// Original match behaviour + match = getCorrectMatchJavaRegex(matches, matchNumber); + if (match != null) { + vars.put(refName, generateResult(match)); + saveGroups(vars, refName, match); + } else { + // refname has already been set to the default (if present) + removeGroups(vars, refName); + } + } else // < 0 means we save all the matches + { + removeGroups(vars, refName); // remove any single matches + matchCount = matches.size(); + vars.put(refName + REF_MATCH_NR, Integer.toString(matchCount));// Save the count + for (int i = 1; i <= matchCount; i++) { + match = getCorrectMatchJavaRegex(matches, i); + if (match != null) { + final String refName_n = refName + UNDERSCORE + i; + vars.put(refName_n, generateResult(match)); + saveGroups(vars, refName_n, match); + } + } + } + // Remove any left-over variables + for (int i = matchCount + 1; i <= prevCount; i++) { + final String refName_n = refName + UNDERSCORE + i; + vars.remove(refName_n); + removeGroups(vars, refName_n); + } + } catch (RuntimeException e) { + log.warn("Error while generating result"); + } + } catch (PatternSyntaxException e) { + log.error("Error in pattern: '{}'", regex); + } + } + private String getInputString(SampleResult result) { String inputString = useUrl() ? result.getUrlAsString() // Bug 39707 : useHeaders() ? result.getResponseHeaders() @@ -213,6 +281,36 @@ private List processMatches(Pattern pattern, String regex, SampleRe return Collections.unmodifiableList(matches); } + private List processMatches( + java.util.regex.Pattern pattern, SampleResult result, int matchNumber, JMeterVariables vars) { + log.debug("Regex = '{}'", pattern.pattern()); + + List matches = new ArrayList<>(); + int found = 0; + + if (isScopeVariable()) { + String inputString=vars.get(getVariableName()); + if(inputString == null) { + if (log.isWarnEnabled()) { + log.warn("No variable '{}' found to process by RegexExtractor '{}', skipping processing", + getVariableName(), getName()); + } + return Collections.emptyList(); + } + matchStrings(matchNumber, pattern, matches, found, inputString); + } else { + List sampleList = getSampleList(result); + for (SampleResult sr : sampleList) { + String inputString = getInputString(sr); + found = matchStrings(matchNumber, pattern, matches, found, inputString); + if (matchNumber > 0 && found == matchNumber) {// no need to process further + break; + } + } + } + return Collections.unmodifiableList(matches); + } + private int matchStrings(int matchNumber, Perl5Matcher matcher, Pattern pattern, List matches, int found, String inputString) { @@ -229,6 +327,22 @@ private int matchStrings(int matchNumber, Perl5Matcher matcher, return found; } + private int matchStrings(int matchNumber, java.util.regex.Pattern pattern, + List matches, int found, + String inputString) { + Matcher matcher = pattern.matcher(inputString); + while (matchNumber <=0 || found != matchNumber) { + if (matcher.find()) { + log.debug("RegexExtractor: Match found!"); + matches.add(matcher.toMatchResult()); + found++; + } else { + break; + } + } + return found; + } + /** * Creates the variables:
    * basename_gn, where n=0...# of groups
    @@ -263,6 +377,35 @@ private void saveGroups(JMeterVariables vars, String basename, MatchResult match } } + private void saveGroups(JMeterVariables vars, String basename, java.util.regex.MatchResult match) { + StringBuilder buf = new StringBuilder(); + buf.append(basename); + buf.append("_g"); // $NON-NLS-1$ + int pfxlen=buf.length(); + String prevString=vars.get(buf.toString()); + int previous=0; + if (prevString!=null){ + try { + previous=Integer.parseInt(prevString); + } catch (NumberFormatException nfe) { + log.warn("Could not parse number: '{}'.", prevString); + } + } + //Note: match.groups() includes group 0 + final int groups = match.groupCount(); + for (int x = 0; x < groups; x++) { + buf.append(x); + vars.put(buf.toString(), match.group(x)); + buf.setLength(pfxlen); + } + vars.put(buf.toString(), Integer.toString(groups-1)); + for (int i = groups; i <= previous; i++){ + buf.append(i); + vars.remove(buf.toString());// remove the remaining _gn vars + buf.setLength(pfxlen); + } + } + /** * Removes the variables:
    * basename_gn, where n=0...# of groups
    @@ -304,6 +447,22 @@ private String generateResult(MatchResult match) { return result.toString(); } + private String generateResult(java.util.regex.MatchResult match) { + StringBuilder result = new StringBuilder(); + for (Object obj : template) { + if(log.isDebugEnabled()) { + log.debug("RegexExtractor: Template piece {} ({})", obj, obj.getClass()); + } + if (obj instanceof Integer) { + result.append(match.group((Integer) obj)); + } else { + result.append(obj); + } + } + log.debug("Regex Extractor result = '{}'", result); + return result.toString(); + } + private void initTemplate() { if (template != null) { return; @@ -368,6 +527,21 @@ private MatchResult getCorrectMatch(List matches, int entry) { return matches.get(entry - 1); } + private java.util.regex.MatchResult getCorrectMatchJavaRegex(List matches, int entry) { + int matchSize = matches.size(); + + if (matchSize <= 0 || entry > matchSize){ + return null; + } + + if (entry == 0) // Random match + { + return matches.get(JMeterUtils.getRandomInt(matchSize)); + } + + return matches.get(entry - 1); + } + /** * Set the regex to be used * @param regex The string representation of the regex From 7d81464d9bada76de0d6435fb2036685d46ca029 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Mon, 21 Feb 2022 21:53:18 +0100 Subject: [PATCH 090/736] Remove unnecessary second argument for substring (we want it all) --- .../main/java/org/apache/jmeter/extractor/RegexExtractor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/src/main/java/org/apache/jmeter/extractor/RegexExtractor.java b/src/components/src/main/java/org/apache/jmeter/extractor/RegexExtractor.java index 7ec7cdcec78..32d8936a0bc 100644 --- a/src/components/src/main/java/org/apache/jmeter/extractor/RegexExtractor.java +++ b/src/components/src/main/java/org/apache/jmeter/extractor/RegexExtractor.java @@ -491,7 +491,7 @@ private void initTemplate() { } if (beginOffset < rawTemplate.length()) { // trailing string is not empty - combined.add(rawTemplate.substring(beginOffset, rawTemplate.length())); + combined.add(rawTemplate.substring(beginOffset)); } if (log.isDebugEnabled()) { log.debug("Template item count: {}", combined.size()); From a28e31b6a4a01111d258b7ac6e6525240e38cdde Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Mon, 21 Feb 2022 22:02:15 +0100 Subject: [PATCH 091/736] Use isEmpty instead of comparing length to zero --- .../org/apache/jmeter/functions/RegexFunction.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/functions/src/main/java/org/apache/jmeter/functions/RegexFunction.java b/src/functions/src/main/java/org/apache/jmeter/functions/RegexFunction.java index 71ffd73cd27..54ea52647e9 100644 --- a/src/functions/src/main/java/org/apache/jmeter/functions/RegexFunction.java +++ b/src/functions/src/main/java/org/apache/jmeter/functions/RegexFunction.java @@ -99,7 +99,7 @@ public String execute(SampleResult previousResult, Sampler currentSampler) if (values.length > 2) { valueIndex = ((CompoundVariable) values[2]).execute(); } - if (valueIndex.length() == 0) { + if (valueIndex.isEmpty()) { valueIndex = "1"; //$NON-NLS-1$ } @@ -109,7 +109,7 @@ public String execute(SampleResult previousResult, Sampler currentSampler) if (values.length > 4) { String dv = ((CompoundVariable) values[4]).execute(); - if (dv.length() != 0) { + if (!dv.isEmpty()) { defaultValue = dv; } } @@ -133,19 +133,19 @@ public String execute(SampleResult previousResult, Sampler currentSampler) return defaultValue; } - if (name.length() > 0) { + if (!name.isEmpty()) { vars.put(name, defaultValue); } String textToMatch=null; - if (inputVariable.length() > 0){ + if (!inputVariable.isEmpty()){ textToMatch=vars.get(inputVariable); } else if (previousResult != null){ textToMatch = previousResult.getResponseDataAsString(); } - if (textToMatch == null || textToMatch.length() == 0) { + if (textToMatch == null || textToMatch.isEmpty()) { return defaultValue; } @@ -160,7 +160,7 @@ public String execute(SampleResult previousResult, Sampler currentSampler) } } } finally { - if (name.length() > 0){ + if (!name.isEmpty()){ vars.put(name + "_matchNr", Integer.toString(collectAllMatches.size())); //$NON-NLS-1$ } } @@ -225,7 +225,7 @@ private String generateResult(MatchResult match, String namep, Object[] template result.append(match.group((Integer) t)); } } - if (namep.length() > 0){ + if (!namep.isEmpty()){ vars.put(namep, result.toString()); } return result.toString(); From ec257dcd150b0e166b5d4b59a7edb136bb55bde6 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Tue, 22 Feb 2022 16:36:47 +0100 Subject: [PATCH 092/736] Remove unused local variable this is the old default else branch, where implicitly is true. --- .../java/org/apache/jmeter/assertions/ResponseAssertion.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/src/main/java/org/apache/jmeter/assertions/ResponseAssertion.java b/src/components/src/main/java/org/apache/jmeter/assertions/ResponseAssertion.java index fa82744777d..664e952b8f2 100644 --- a/src/components/src/main/java/org/apache/jmeter/assertions/ResponseAssertion.java +++ b/src/components/src/main/java/org/apache/jmeter/assertions/ResponseAssertion.java @@ -308,7 +308,6 @@ private AssertionResult evaluateResponse(SampleResult response) { boolean contains = isContainsType(); // do it once outside loop boolean equals = isEqualsType(); boolean substring = isSubstringType(); - boolean matches = isMatchType(); log.debug("Test Type Info: contains={}, notTest={}, orTest={}", contains, notTest, orTest); @@ -342,7 +341,7 @@ private AssertionResult evaluateResponse(SampleResult response) { found = toCheck.equals(stringPattern); } else if (substring) { found = toCheck.contains(stringPattern); - } else { + } else { // this is the old `matches` part which means `isMatchType()` is true if (useJavaRegex) { found = matchesWithJavaRegex(toCheck, stringPattern); } else { From de99883df5db26182126a2bd1c0941a8c9748a83 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Tue, 22 Feb 2022 16:37:13 +0100 Subject: [PATCH 093/736] Use isEmpty instead of comparing length to zero --- .../java/org/apache/jmeter/functions/EscapeOroRegexpChars.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/functions/src/main/java/org/apache/jmeter/functions/EscapeOroRegexpChars.java b/src/functions/src/main/java/org/apache/jmeter/functions/EscapeOroRegexpChars.java index 01a24485ed4..91c8d99641b 100644 --- a/src/functions/src/main/java/org/apache/jmeter/functions/EscapeOroRegexpChars.java +++ b/src/functions/src/main/java/org/apache/jmeter/functions/EscapeOroRegexpChars.java @@ -75,7 +75,7 @@ public String execute(SampleResult previousResult, Sampler currentSampler) String escapedValue = Perl5Compiler.quotemeta(valueToEscape); - if (varName.length() > 0) { + if (!varName.isEmpty()) { JMeterVariables vars = getVariables(); if (vars != null) {// Can be null if called from Config item testEnded() method vars.put(varName, escapedValue); From 2c6bdf45af539cc131255da8bba50422174a24e8 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Tue, 22 Feb 2022 16:43:20 +0100 Subject: [PATCH 094/736] Add a switch to decide which regex engine should be used --- .../jmeter/functions/RegexFunction.java | 213 +++++++++++++++--- 1 file changed, 181 insertions(+), 32 deletions(-) diff --git a/src/functions/src/main/java/org/apache/jmeter/functions/RegexFunction.java b/src/functions/src/main/java/org/apache/jmeter/functions/RegexFunction.java index 54ea52647e9..9163a3e6257 100644 --- a/src/functions/src/main/java/org/apache/jmeter/functions/RegexFunction.java +++ b/src/functions/src/main/java/org/apache/jmeter/functions/RegexFunction.java @@ -18,10 +18,13 @@ package org.apache.jmeter.functions; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.concurrent.ThreadLocalRandom; +import java.util.regex.Matcher; +import java.util.regex.PatternSyntaxException; import org.apache.jmeter.engine.util.CompoundVariable; import org.apache.jmeter.samplers.SampleResult; @@ -60,6 +63,8 @@ public class RegexFunction extends AbstractFunction { private static final String TEMPLATE_PATTERN = "\\$(\\d+)\\$"; //$NON-NLS-1$ /** initialised to the regex \$(\d+)\$ */ private final Pattern templatePattern; + private static final java.util.regex.Pattern templatePatternJava = + java.util.regex.Pattern.compile(TEMPLATE_PATTERN); // Number of parameters expected - used to reject invalid calls private static final int MIN_PARAMETER_COUNT = 2; @@ -75,6 +80,8 @@ public class RegexFunction extends AbstractFunction { desc.add(JMeterUtils.getResString("regexfunc_param_7"));// input variable //$NON-NLS-1$ } + private boolean useJavaRegex = JMeterUtils.getPropDefault("jmeter.use_java_regex", false); + public RegexFunction() { templatePattern = JMeterUtils.getPatternCache().getPattern(TEMPLATE_PATTERN, Perl5Compiler.READ_ONLY_MASK); @@ -89,43 +96,35 @@ public String execute(SampleResult previousResult, Sampler currentSampler) String between = ""; //$NON-NLS-1$ String name = ""; //$NON-NLS-1$ String inputVariable = ""; //$NON-NLS-1$ - Pattern searchPattern; Object[] tmplt; - try { - searchPattern = JMeterUtils.getPatternCache().getPattern(((CompoundVariable) values[0]).execute(), - Perl5Compiler.READ_ONLY_MASK); - tmplt = generateTemplate(((CompoundVariable) values[1]).execute()); - - if (values.length > 2) { - valueIndex = ((CompoundVariable) values[2]).execute(); - } - if (valueIndex.isEmpty()) { - valueIndex = "1"; //$NON-NLS-1$ - } + tmplt = generateTemplate(((CompoundVariable) values[1]).execute()); + if (values.length > 2) { + valueIndex = ((CompoundVariable) values[2]).execute(); + } + if (valueIndex.isEmpty()) { + valueIndex = "1"; //$NON-NLS-1$ + } - if (values.length > 3) { - between = ((CompoundVariable) values[3]).execute(); - } + if (values.length > 3) { + between = ((CompoundVariable) values[3]).execute(); + } - if (values.length > 4) { - String dv = ((CompoundVariable) values[4]).execute(); - if (!dv.isEmpty()) { - defaultValue = dv; - } + if (values.length > 4) { + String dv = ((CompoundVariable) values[4]).execute(); + if (!dv.isEmpty()) { + defaultValue = dv; } + } - if (values.length > 5) { - name = ((CompoundVariable) values[5]).execute(); - } + if (values.length > 5) { + name = ((CompoundVariable) values[5]).execute(); + } - if (values.length > 6) { - inputVariable = ((CompoundVariable) values[6]).execute(); - } - } catch (MalformedCachePatternException e) { - log.error("Malformed cache pattern:{}", values[0], e); - throw new InvalidVariableException("Malformed cache pattern:"+values[0], e); + if (values.length > 6) { + inputVariable = ((CompoundVariable) values[6]).execute(); } + // Relatively expensive operation, so do it once JMeterVariables vars = getVariables(); @@ -149,8 +148,84 @@ public String execute(SampleResult previousResult, Sampler currentSampler) return defaultValue; } + if (useJavaRegex) { + return getResultWithJavaRegex(valueIndex, defaultValue, between, name, tmplt, vars, textToMatch); + } + return getResultWithOroRegex(valueIndex, defaultValue, between, name, tmplt, vars, textToMatch); + + } + + private String getResultWithJavaRegex(String valueIndex, String defaultValue, String between, String name, + Object[] tmplt, JMeterVariables vars, String textToMatch) + throws InvalidVariableException { + List collectAllMatches = new ArrayList<>(); + try { + java.util.regex.Pattern searchPattern = generateJavaPattern(); + Matcher matcher = searchPattern.matcher(textToMatch); + while (matcher.find()) { + java.util.regex.MatchResult match = matcher.toMatchResult(); + collectAllMatches.add(match); + } + } finally { + if (!name.isEmpty()){ + vars.put(name + "_matchNr", Integer.toString(collectAllMatches.size())); //$NON-NLS-1$ + } + } + + if (collectAllMatches.isEmpty()) { + return defaultValue; + } + + if (valueIndex.equals(ALL)) { + StringBuilder value = new StringBuilder(); + Iterator it = collectAllMatches.iterator(); + boolean first = true; + while (it.hasNext()) { + if (!first) { + value.append(between); + } else { + first = false; + } + value.append(generateResult(it.next(), name, tmplt, vars)); + } + return value.toString(); + } else if (valueIndex.equals(RAND)) { + java.util.regex.MatchResult result = collectAllMatches.get( + ThreadLocalRandom.current().nextInt(collectAllMatches.size())); + return generateResult(result, name, tmplt, vars); + } else { + try { + int index = Integer.parseInt(valueIndex) - 1; + if(index >= collectAllMatches.size()) { + return defaultValue; + } + java.util.regex.MatchResult result = collectAllMatches.get(index); + return generateResult(result, name, tmplt, vars); + } catch (NumberFormatException e) { + float ratio = Float.parseFloat(valueIndex); + java.util.regex.MatchResult result = collectAllMatches + .get((int) (collectAllMatches.size() * ratio + .5) - 1); + return generateResult(result, name, tmplt, vars); + } + } + } + + private java.util.regex.Pattern generateJavaPattern() throws InvalidVariableException { + try { + return java.util.regex.Pattern.compile(((CompoundVariable) values[0]).execute()); + + } catch (PatternSyntaxException e) { + log.error("Malformed regex pattern:{}", values[0], e); + throw new InvalidVariableException("Malformed regex pattern:" + values[0], e); + } + } + + private String getResultWithOroRegex(String valueIndex, String defaultValue, String between, String name, + Object[] tmplt, JMeterVariables vars, String textToMatch) + throws InvalidVariableException { List collectAllMatches = new ArrayList<>(); try { + Pattern searchPattern = generateOroPattern(); PatternMatcher matcher = JMeterUtils.getMatcher(); PatternMatcherInput input = new PatternMatcherInput(textToMatch); while (matcher.contains(input, searchPattern)) { @@ -200,7 +275,23 @@ public String execute(SampleResult previousResult, Sampler currentSampler) return generateResult(result, name, tmplt, vars); } } + } + private Pattern generateOroPattern() throws InvalidVariableException { + try { + return JMeterUtils.getPatternCache().getPattern(((CompoundVariable) values[0]).execute(), + Perl5Compiler.READ_ONLY_MASK); + + } catch (MalformedCachePatternException e) { + log.error("Malformed cache pattern:{}", values[0], e); + throw new InvalidVariableException("Malformed cache pattern:" + values[0], e); + } + } + + private void saveGroups(java.util.regex.MatchResult result, String namep, JMeterVariables vars) { + for (int x = 0; x < result.groupCount(); x++) { + vars.put(namep + "_g" + x, result.group(x)); //$NON-NLS-1$ + } } private void saveGroups(MatchResult result, String namep, JMeterVariables vars) { @@ -231,6 +322,23 @@ private String generateResult(MatchResult match, String namep, Object[] template return result.toString(); } + private String generateResult(java.util.regex.MatchResult match, String namep, Object[] template, + JMeterVariables vars) { + saveGroups(match, namep, vars); + StringBuilder result = new StringBuilder(); + for (Object t : template) { + if (t instanceof String) { + result.append(t); + } else { + result.append(match.group((Integer) t)); + } + } + if (!namep.isEmpty()){ + vars.put(namep, result.toString()); + } + return result.toString(); + } + /** {@inheritDoc} */ @Override public String getReferenceKey() { @@ -245,6 +353,43 @@ public void setParameters(Collection parameters) throws Invali } private Object[] generateTemplate(String rawTemplate) { + if (useJavaRegex) { + return generateTemplateWithJavaRegex(rawTemplate); + } + return generateTemplateWithOroRegex(rawTemplate); + } + + private Object[] generateTemplateWithJavaRegex(String rawTemplate) { + // String or Integer + List combined = new ArrayList<>(); + List pieces = Arrays.asList(templatePatternJava.split(rawTemplate)); + Matcher matcher = templatePatternJava.matcher(rawTemplate); + boolean startsWith = isFirstElementGroup(rawTemplate); + if (startsWith) { + pieces.remove(0);// Remove initial empty entry + } + Iterator iter = pieces.iterator(); + while (iter.hasNext()) { + boolean matchExists = matcher.find(); + if (startsWith) { + if (matchExists) { + combined.add(Integer.valueOf(matcher.group(1))); + } + combined.add(iter.next()); + } else { + combined.add(iter.next()); + if (matchExists) { + combined.add(Integer.valueOf(matcher.group(1))); + } + } + } + if (matcher.find()) { + combined.add(Integer.valueOf(matcher.group(1))); + } + return combined.toArray(); + } + + private Object[] generateTemplateWithOroRegex(String rawTemplate) { List pieces = new ArrayList<>(); // String or Integer List combined = new ArrayList<>(); @@ -277,9 +422,13 @@ private Object[] generateTemplate(String rawTemplate) { } private boolean isFirstElementGroup(String rawData) { - Pattern pattern = JMeterUtils.getPatternCache().getPattern("^\\$\\d+\\$", //$NON-NLS-1$ - Perl5Compiler.READ_ONLY_MASK); - return JMeterUtils.getMatcher().contains(rawData, pattern); + if (useJavaRegex) { + return java.util.regex.Pattern.compile("^\\$\\d+\\$").matcher(rawData).find(); + } else { + Pattern pattern = JMeterUtils.getPatternCache().getPattern("^\\$\\d+\\$", //$NON-NLS-1$ + Perl5Compiler.READ_ONLY_MASK); + return JMeterUtils.getMatcher().contains(rawData, pattern); + } } } From eb7c88c6cc15c7eb3c476d1b2d2b420361db6128 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Wed, 23 Feb 2022 18:44:44 +0100 Subject: [PATCH 095/736] Add a switch to decide which regex engine should be used --- .../util/ReplaceFunctionsWithStrings.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/core/src/main/java/org/apache/jmeter/engine/util/ReplaceFunctionsWithStrings.java b/src/core/src/main/java/org/apache/jmeter/engine/util/ReplaceFunctionsWithStrings.java index 8ac37b9f58a..9f55cf800fb 100644 --- a/src/core/src/main/java/org/apache/jmeter/engine/util/ReplaceFunctionsWithStrings.java +++ b/src/core/src/main/java/org/apache/jmeter/engine/util/ReplaceFunctionsWithStrings.java @@ -18,6 +18,7 @@ package org.apache.jmeter.engine.util; import java.util.Map; +import java.util.regex.PatternSyntaxException; import org.apache.jmeter.functions.InvalidVariableException; import org.apache.jmeter.testelement.property.JMeterProperty; @@ -53,6 +54,8 @@ public class ReplaceFunctionsWithStrings extends AbstractTransformer { private final boolean regexMatch;// Should we match using regexes? + private boolean useJavaRegex = JMeterUtils.getPropDefault("jmeter.use_java_regex", false); + public ReplaceFunctionsWithStrings(CompoundVariable masterFunction, Map variables) { this(masterFunction, variables, false); } @@ -66,6 +69,13 @@ public ReplaceFunctionsWithStrings(CompoundVariable masterFunction, Map entry : getVariables().entrySet()){ + String key = entry.getKey(); + String value = entry.getValue(); + if (regexMatch) { + try { + java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(constructPattern(value)); + input = pattern.matcher(input).replaceAll(FUNCTION_REF_PREFIX + key + FUNCTION_REF_SUFFIX); + } catch (PatternSyntaxException e) { + log.warn("Malformed pattern: {}", value); + } + } else { + input = StringUtilities.substitute(input, value, FUNCTION_REF_PREFIX + key + FUNCTION_REF_SUFFIX); + } + } + return new StringProperty(prop.getName(), input); + } + /** * Normal regexes will be surrounded by boundary character matches to make life easier for users. * If a user doesn't want that behaviour, they can prevent the modification by giving a regex, that From e746871640e67b9c5bd6b859ab2f8ef3ab917941 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Wed, 23 Feb 2022 20:14:59 +0100 Subject: [PATCH 096/736] Add a switch to decide which regex engine should be used --- .../apache/jmeter/save/CSVSaveService.java | 60 ++++++++++++++----- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/src/core/src/main/java/org/apache/jmeter/save/CSVSaveService.java b/src/core/src/main/java/org/apache/jmeter/save/CSVSaveService.java index 0b29926a6e9..e439fb938ae 100644 --- a/src/core/src/main/java/org/apache/jmeter/save/CSVSaveService.java +++ b/src/core/src/main/java/org/apache/jmeter/save/CSVSaveService.java @@ -35,6 +35,7 @@ import java.util.Arrays; import java.util.Date; import java.util.List; +import java.util.regex.Matcher; import javax.swing.table.DefaultTableModel; @@ -116,6 +117,8 @@ public final class CSVSaveService { private static final String LINE_SEP = System.getProperty("line.separator"); // $NON-NLS-1$ + private static boolean useJavaRegex = JMeterUtils.getPropDefault("jmeter.use_java_regex", false); + /** * Private constructor to prevent instantiation. */ @@ -510,20 +513,9 @@ public static SampleSaveConfiguration getSampleSaveConfiguration( String delim = null; if (parts == null) { - Perl5Matcher matcher = JMeterUtils.getMatcher(); - PatternMatcherInput input = new PatternMatcherInput(headerLine); - Pattern pattern = JMeterUtils.getPatternCache() - // This assumes the header names are all single words with no spaces - // word followed by 0 or more repeats of (non-word char + word) - // where the non-word char (\2) is the same - // e.g. abc|def|ghi but not abd|def~ghi - .getPattern("\\w+((\\W)\\w+)?(\\2\\w+)*(\\2\"\\w+\")*", // $NON-NLS-1$ - // last entries may be quoted strings - Perl5Compiler.READ_ONLY_MASK); - if (matcher.matches(input, pattern)) { - delim = matcher.getMatch().group(2); - parts = splitHeader(headerLine, delim);// now validate the - // result + delim = extractDelimiter(headerLine); + if (delim != null) { + parts = splitHeader(headerLine, delim);// now validate the result } } @@ -557,6 +549,46 @@ public static SampleSaveConfiguration getSampleSaveConfiguration( return saveConfig; } + private static String extractDelimiter(String headerLine) { + if (useJavaRegex) { + return extractDelimWithJavaRegex(headerLine); + } + return extractDelimWithOroRegex(headerLine); + } + + private static String extractDelimWithJavaRegex(String headerLine) { + java.util.regex.Pattern pattern = java.util.regex.Pattern + // This assumes the header names are all single words with no spaces + // word followed by 0 or more repeats of (non-word char + word) + // where the non-word char (\2) is the same + // e.g. abc|def|ghi but not abd|def~ghi + .compile("\\w+((\\W)\\w+)?(\\2\\w+)*(\\2\"\\w+\")*" // $NON-NLS-1$ + // last entries may be quoted strings + ); + Matcher matcher = pattern.matcher(headerLine); + if (matcher.matches()) { + return matcher.group(2); + } + return null; + } + + private static String extractDelimWithOroRegex(String headerLine) { + Perl5Matcher matcher = JMeterUtils.getMatcher(); + PatternMatcherInput input = new PatternMatcherInput(headerLine); + Pattern pattern = JMeterUtils.getPatternCache() + // This assumes the header names are all single words with no spaces + // word followed by 0 or more repeats of (non-word char + word) + // where the non-word char (\2) is the same + // e.g. abc|def|ghi but not abd|def~ghi + .getPattern("\\w+((\\W)\\w+)?(\\2\\w+)*(\\2\"\\w+\")*", // $NON-NLS-1$ + // last entries may be quoted strings + Perl5Compiler.READ_ONLY_MASK); + if (matcher.matches(input, pattern)) { + return matcher.getMatch().group(2); + } + return null; + } + private static String[] splitHeader(String headerLine, String delim) { String[] parts = headerLine.split("\\Q" + delim);// $NON-NLS-1$ int previous = -1; From c7b4b764079342bdd83458565423640805876469 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Wed, 23 Feb 2022 20:27:48 +0100 Subject: [PATCH 097/736] Add a switch to decide which regex engine should be used --- .../report/dashboard/ReportGenerator.java | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/core/src/main/java/org/apache/jmeter/report/dashboard/ReportGenerator.java b/src/core/src/main/java/org/apache/jmeter/report/dashboard/ReportGenerator.java index f66cf7b3be0..36034583dc2 100644 --- a/src/core/src/main/java/org/apache/jmeter/report/dashboard/ReportGenerator.java +++ b/src/core/src/main/java/org/apache/jmeter/report/dashboard/ReportGenerator.java @@ -103,6 +103,8 @@ public class ReportGenerator { private final File testFile; private final ReportGeneratorConfiguration configuration; + private boolean useJavaRegex = JMeterUtils.getPropDefault("jmeter.use_java_regex", false); + /** * ResultCollector used */ @@ -439,9 +441,7 @@ private ApdexSummaryConsumer createApdexSummaryConsumer() { // by property jmeter.reportgenerator.apdex_per_transaction // key in entry below can be a hardcoded name or a regex for (Map.Entry entry : configuration.getApdexPerTransaction().entrySet()) { - org.apache.oro.text.regex.Pattern regex = JMeterUtils.getPatternCache().getPattern(entry.getKey()); - PatternMatcher matcher = JMeterUtils.getMatcher(); - if (sampleName != null && matcher.matches(sampleName, regex)) { + if (isMatching(sampleName, entry.getKey())) { Long satisfied = entry.getValue()[0]; Long tolerated = entry.getValue()[1]; if(log.isDebugEnabled()) { @@ -458,6 +458,19 @@ private ApdexSummaryConsumer createApdexSummaryConsumer() { return apdexSummaryConsumer; } + private boolean isMatching(String sampleName, String keyName) { + if (sampleName == null) { + return false; + } + if (useJavaRegex) { + java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(keyName); + return pattern.matcher(sampleName).matches(); + } + org.apache.oro.text.regex.Pattern regex = JMeterUtils.getPatternCache().getPattern(keyName); + PatternMatcher matcher = JMeterUtils.getMatcher(); + return matcher.matches(sampleName, regex); + } + /** * @return a {@link FilterConsumer} that filters samplers based on their name */ From a699d2bcd6ac155382e0d4a399d82706b3223140 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Wed, 23 Feb 2022 20:42:13 +0100 Subject: [PATCH 098/736] Use isEmpty instead of comparing length to zero --- .../apache/jmeter/protocol/http/parser/HtmlParsingUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/parser/HtmlParsingUtils.java b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/parser/HtmlParsingUtils.java index d692b02c073..a245e84c7e4 100644 --- a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/parser/HtmlParsingUtils.java +++ b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/parser/HtmlParsingUtils.java @@ -89,7 +89,7 @@ public static boolean isAnchorMatched(HTTPSamplerBase newLink, HTTPSamplerBase c } final String domain = config.getDomain(); - if (domain != null && domain.length() > 0) { + if (domain != null && !domain.isEmpty()) { if (!isEqualOrMatches(newLink.getDomain(), domain, matcher, patternCache)){ return false; } From 432cda4f12b5bd3fdb6fef926b6baa944b499ae9 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Wed, 23 Feb 2022 20:47:54 +0100 Subject: [PATCH 099/736] Use isEmpty instead of comparing length to zero --- .../protocol/http/proxy/ProxyControl.java | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/proxy/ProxyControl.java b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/proxy/ProxyControl.java index cda7adadaa8..6819c185215 100644 --- a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/proxy/ProxyControl.java +++ b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/proxy/ProxyControl.java @@ -794,18 +794,18 @@ public String[] getCertificateDetails() { // Package protected to allow test case access boolean filterUrl(HTTPSamplerBase sampler) { String domain = sampler.getDomain(); - if (domain == null || domain.length() == 0) { + if (domain == null || domain.isEmpty()) { return false; } String url = generateMatchUrl(sampler); CollectionProperty includePatterns = getIncludePatterns(); - if (includePatterns.size() > 0 && !matchesPatterns(url, includePatterns)) { + if (!includePatterns.isEmpty() && !matchesPatterns(url, includePatterns)) { return false; } CollectionProperty excludePatterns = getExcludePatterns(); - if (excludePatterns.size() > 0 && matchesPatterns(url, excludePatterns)) { + if (!excludePatterns.isEmpty() && matchesPatterns(url, excludePatterns)) { return false; } @@ -826,16 +826,14 @@ boolean filterContentType(SampleResult result) { String excludeExp = getContentTypeExclude(); // If no expressions are specified, we let the sample pass - if((includeExp == null || includeExp.length() == 0) && - (excludeExp == null || excludeExp.length() == 0) - ) - { + if ((includeExp == null || includeExp.isEmpty()) && + (excludeExp == null || excludeExp.isEmpty())) { return true; } // Check that we have a content type String sampleContentType = result.getContentType(); - if (sampleContentType == null || sampleContentType.length() == 0) { + if (sampleContentType == null || sampleContentType.isEmpty()) { if (log.isDebugEnabled()) { log.debug("No Content-type found for : {}", result.getUrlAsString()); } @@ -870,7 +868,7 @@ boolean filterContentType(SampleResult result) { * @return boolean true if Matching expression */ private boolean testPattern(String expression, String sampleContentType, boolean expectedToMatch) { - if(expression != null && expression.length() > 0) { + if(expression != null && !expression.isEmpty()) { if(log.isDebugEnabled()) { log.debug( "Testing Expression : {} on sampleContentType: {}, expected to match: {}", @@ -1324,7 +1322,7 @@ private void removeValuesFromSampler(HTTPSamplerBase sampler, Collection 0) { + if (configValue != null && !configValue.isEmpty()) { if (configValue.equals(value)) { sampler.setProperty(name, ""); // $NON-NLS-1$ } @@ -1342,7 +1340,7 @@ private String generateMatchUrl(HTTPSamplerBase sampler) { buf.append(':'); // $NON-NLS-1$ buf.append(sampler.getPort()); buf.append(sampler.getPath()); - if (sampler.getQueryString().length() > 0) { + if (!sampler.getQueryString().isEmpty()) { buf.append('?'); // $NON-NLS-1$ buf.append(sampler.getQueryString()); } @@ -1577,7 +1575,7 @@ private void initDynamicKeyStore() throws IOException, GeneralSecurityException keyStore = getKeyStore(storePassword.toCharArray()); // This should now work } final String sslDomains = getSslDomains().trim(); - if (sslDomains.length() > 0) { + if (!sslDomains.isEmpty()) { final String[] domains = sslDomains.split(","); // The subject may be either a host or a domain for (String subject : domains) { From 283e3b32209c3124937feb6533f5f1bf2d930314 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Wed, 23 Feb 2022 21:08:10 +0100 Subject: [PATCH 100/736] Add a switch to decide which regex engine should be used --- .../protocol/http/proxy/ProxyControl.java | 69 +++++++++++++++---- 1 file changed, 55 insertions(+), 14 deletions(-) diff --git a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/proxy/ProxyControl.java b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/proxy/ProxyControl.java index 6819c185215..80a856141ab 100644 --- a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/proxy/ProxyControl.java +++ b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/proxy/ProxyControl.java @@ -44,6 +44,7 @@ import java.util.Map; import java.util.Set; import java.util.prefs.Preferences; +import java.util.regex.PatternSyntaxException; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.digest.DigestUtils; @@ -245,6 +246,8 @@ public enum KeystoreMode { // Although this field is mutable, it is only accessed within the synchronized method deliverSampler() private static String LAST_REDIRECT = null; + private boolean useJavaRegex = JMeterUtils.getPropDefault("jmeter.use_java_regex", false); + private transient Daemon server; private long lastTime = 0;// When was the last sample seen? @@ -868,26 +871,42 @@ boolean filterContentType(SampleResult result) { * @return boolean true if Matching expression */ private boolean testPattern(String expression, String sampleContentType, boolean expectedToMatch) { - if(expression != null && !expression.isEmpty()) { - if(log.isDebugEnabled()) { - log.debug( - "Testing Expression : {} on sampleContentType: {}, expected to match: {}", - expression, sampleContentType, expectedToMatch); - } + if (expression == null || expression.isEmpty()) { + return true; + } + if(log.isDebugEnabled()) { + log.debug( + "Testing Expression : {} on sampleContentType: {}, expected to match: {}", + expression, sampleContentType, expectedToMatch); + } - Pattern pattern = null; - try { - pattern = JMeterUtils.getPatternCache().getPattern(expression, Perl5Compiler.READ_ONLY_MASK | Perl5Compiler.SINGLELINE_MASK); - if(JMeterUtils.getMatcher().contains(sampleContentType, pattern) != expectedToMatch) { - return false; - } - } catch (MalformedCachePatternException e) { - log.warn("Skipped invalid content pattern: {}", expression, e); + try { + boolean contains; + if (useJavaRegex) { + contains = isContainedWithJavaRegex(expression, sampleContentType); + } else { + contains = isContainedWithOroRegex(expression, sampleContentType); + } + if (contains != expectedToMatch) { + return false; } + } catch (PatternSyntaxException | MalformedCachePatternException e) { + log.warn("Skipped invalid content pattern: {}", expression, e); } return true; } + private boolean isContainedWithJavaRegex(String expression, String sampleContentType) { + java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(expression); + return pattern.matcher(sampleContentType).find(); + } + + private boolean isContainedWithOroRegex(String expression, String sampleContentType) { + Pattern pattern = JMeterUtils.getPatternCache().getPattern(expression, + Perl5Compiler.READ_ONLY_MASK | Perl5Compiler.SINGLELINE_MASK); + return JMeterUtils.getMatcher().contains(sampleContentType, pattern); + } + /** * Find if there is any AuthManager in JMeterTreeModel * If there is no one, create and add it to tree @@ -1348,6 +1367,28 @@ private String generateMatchUrl(HTTPSamplerBase sampler) { } private boolean matchesPatterns(String url, CollectionProperty patterns) { + if (useJavaRegex) { + return matchesPatternsWithJavaRegex(url, patterns); + } + return matchesPatternsWithOroRegex(url, patterns); + } + + private boolean matchesPatternsWithJavaRegex(String url, CollectionProperty patterns) { + for (JMeterProperty jMeterProperty : patterns) { + String item = jMeterProperty.getStringValue(); + try { + java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(item); + if (pattern.matcher(url).matches()) { + return true; + } + } catch (PatternSyntaxException e) { + log.warn("Skipped invalid pattern: {}", item, e); + } + } + return false; + } + + private boolean matchesPatternsWithOroRegex(String url, CollectionProperty patterns) { for (JMeterProperty jMeterProperty : patterns) { String item = jMeterProperty.getStringValue(); try { From e74cb153d2d45d5007365a6eb9c59b5f1fc44967 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Wed, 23 Feb 2022 21:59:41 +0100 Subject: [PATCH 101/736] Add a switch to decide which regex engine should be used --- .../http/config/MultipartUrlConfig.java | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/config/MultipartUrlConfig.java b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/config/MultipartUrlConfig.java index f4eeae90d16..4060e4902e3 100644 --- a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/config/MultipartUrlConfig.java +++ b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/config/MultipartUrlConfig.java @@ -18,6 +18,7 @@ package org.apache.jmeter.protocol.http.config; import java.io.Serializable; +import java.util.regex.Matcher; import org.apache.commons.lang3.StringUtils; import org.apache.http.HeaderElement; @@ -54,6 +55,8 @@ public class MultipartUrlConfig implements Serializable { private static final Logger log = LoggerFactory.getLogger(MultipartUrlConfig.class); + private static boolean useJavaRegex = JMeterUtils.getPropDefault("jmeter.use_java_regex", false); + /** * HTTPFileArgs list to be uploaded with http request. */ @@ -183,6 +186,24 @@ private static String getParameterValue(HeaderElement element, String name, Stri private static String getHeaderValue(String headerName, String multiPart) { String regularExpression = headerName + "\\s*:\\s*(.*)$"; //$NON-NLS-1$ + if (useJavaRegex) { + return getHeaderValueWithJavaRegex(headerName, multiPart, regularExpression); + } + return getHeaderValueWithOroRegex(headerName, multiPart, regularExpression); + } + + private static String getHeaderValueWithJavaRegex(String headerName, String multiPart, String regularExpression) { + java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(regularExpression, + java.util.regex.Pattern.CASE_INSENSITIVE + | java.util.regex.Pattern.MULTILINE); + Matcher matcher = pattern.matcher(multiPart); + if (matcher.find()) { + return matcher.group(1).trim(); + } + return null; + } + + private static String getHeaderValueWithOroRegex(String headerName, String multiPart, String regularExpression) { Perl5Matcher localMatcher = JMeterUtils.getMatcher(); Pattern pattern = JMeterUtils.getPattern(regularExpression, Perl5Compiler.READ_ONLY_MASK @@ -191,8 +212,6 @@ private static String getHeaderValue(String headerName, String multiPart) { if(localMatcher.contains(multiPart, pattern)) { return localMatcher.getMatch().group(1).trim(); } - else { - return null; - } + return null; } } From fe0d0f83170af500371eca58aa39df191be7ec70 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Wed, 23 Feb 2022 22:03:59 +0100 Subject: [PATCH 102/736] Use isEmpty instead of comparing length to zero --- .../apache/jmeter/protocol/http/control/HttpMirrorThread.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/control/HttpMirrorThread.java b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/control/HttpMirrorThread.java index 3fdb5c3fe6c..5411c6acf80 100644 --- a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/control/HttpMirrorThread.java +++ b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/control/HttpMirrorThread.java @@ -109,7 +109,7 @@ public void run() { baos.close(); final String headerString = headers.toString(); - if(headerString.length() == 0 || headerString.indexOf('\r') < 0) { + if(headerString.isEmpty() || headerString.indexOf('\r') < 0) { log.error("Invalid request received:'{}'", headerString); return; } From 3aa7cbf9418abe0fdb0ce4021302b7a1365dbe2e Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Thu, 24 Feb 2022 11:53:19 +0100 Subject: [PATCH 103/736] Remove unused parameter in private method --- .../jmeter/protocol/http/config/MultipartUrlConfig.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/config/MultipartUrlConfig.java b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/config/MultipartUrlConfig.java index 4060e4902e3..ead373c57e7 100644 --- a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/config/MultipartUrlConfig.java +++ b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/config/MultipartUrlConfig.java @@ -187,12 +187,12 @@ private static String getParameterValue(HeaderElement element, String name, Stri private static String getHeaderValue(String headerName, String multiPart) { String regularExpression = headerName + "\\s*:\\s*(.*)$"; //$NON-NLS-1$ if (useJavaRegex) { - return getHeaderValueWithJavaRegex(headerName, multiPart, regularExpression); + return getHeaderValueWithJavaRegex(multiPart, regularExpression); } - return getHeaderValueWithOroRegex(headerName, multiPart, regularExpression); + return getHeaderValueWithOroRegex(multiPart, regularExpression); } - private static String getHeaderValueWithJavaRegex(String headerName, String multiPart, String regularExpression) { + private static String getHeaderValueWithJavaRegex(String multiPart, String regularExpression) { java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(regularExpression, java.util.regex.Pattern.CASE_INSENSITIVE | java.util.regex.Pattern.MULTILINE); @@ -203,7 +203,7 @@ private static String getHeaderValueWithJavaRegex(String headerName, String mult return null; } - private static String getHeaderValueWithOroRegex(String headerName, String multiPart, String regularExpression) { + private static String getHeaderValueWithOroRegex(String multiPart, String regularExpression) { Perl5Matcher localMatcher = JMeterUtils.getMatcher(); Pattern pattern = JMeterUtils.getPattern(regularExpression, Perl5Compiler.READ_ONLY_MASK From c3e9f612ce5b8f283f6c295c822c76648f074eca Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Thu, 24 Feb 2022 12:04:52 +0100 Subject: [PATCH 104/736] Add a switch to decide which regex engine should be used --- .../http/control/HttpMirrorThread.java | 51 +++++++++++++++++-- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/control/HttpMirrorThread.java b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/control/HttpMirrorThread.java index 5411c6acf80..5dbb8c6aa08 100644 --- a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/control/HttpMirrorThread.java +++ b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/control/HttpMirrorThread.java @@ -28,6 +28,7 @@ import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; import org.apache.jmeter.protocol.http.util.HTTPConstants; import org.apache.jmeter.util.JMeterUtils; @@ -68,6 +69,8 @@ public class HttpMirrorThread implements Runnable { private static final String VERBOSE = "v"; // $NON-NLS-1$ + private static boolean useJavaRegex = JMeterUtils.getPropDefault("jmeter.use_java_regex", false); + /** Socket to client. */ private final Socket clientSocket; @@ -290,6 +293,13 @@ else if (isChunked) { } private static String getRequestHeaderValue(String requestHeaders, String headerName) { + if (useJavaRegex) { + return getRequestHeaderValueWithJavaRegex(requestHeaders, headerName); + } + return getRequestHeaderValueWithOroRegex(requestHeaders, headerName); + } + + private static String getRequestHeaderValueWithOroRegex(String requestHeaders, String headerName) { Perl5Matcher localMatcher = JMeterUtils.getMatcher(); // We use multi-line mask so can prefix the line with ^ String expression = "^" + headerName + ":\\s+([^\\r\\n]+)"; // $NON-NLS-1$ $NON-NLS-2$ @@ -297,16 +307,49 @@ private static String getRequestHeaderValue(String requestHeaders, String header Perl5Compiler.READ_ONLY_MASK | Perl5Compiler.CASE_INSENSITIVE_MASK | Perl5Compiler.MULTILINE_MASK); - if(localMatcher.contains(requestHeaders, pattern)) { + if (localMatcher.contains(requestHeaders, pattern)) { // The value is in the first group, group 0 is the whole match return localMatcher.getMatch().group(1); } - else { - return null; + return null; + } + + private static String getRequestHeaderValueWithJavaRegex(String requestHeaders, String headerName) { + // We use multi-line mask so can prefix the line with ^ + String expression = "^" + headerName + ":\\s+([^\\r\\n]+)"; // $NON-NLS-1$ $NON-NLS-2$ + java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(expression, + java.util.regex.Pattern.CASE_INSENSITIVE + | java.util.regex.Pattern.MULTILINE); + Matcher matcher = pattern.matcher(requestHeaders); + if (matcher.find()) { + // The value is in the first group, group 0 is the whole match + return matcher.group(1); } + return null; } private static int getPositionOfBody(String stringToCheck) { + if (useJavaRegex) { + return getPositionOfBodyWithJavaRegex(stringToCheck); + } + return getPositionOfBodyWithOroRegex(stringToCheck); + } + + private static int getPositionOfBodyWithJavaRegex(String stringToCheck) { + // The headers and body are divided by a blank line (the \r is to allow for the CR before LF) + String regularExpression = "^\\r$"; // $NON-NLS-1$ + java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(regularExpression, + java.util.regex.Pattern.CASE_INSENSITIVE | java.util.regex.Pattern.MULTILINE); + + Matcher matcher = pattern.matcher(stringToCheck); + if (matcher.find()) { + return matcher.start(0); + } + // No divider was found + return -1; + } + + private static int getPositionOfBodyWithOroRegex(String stringToCheck) { Perl5Matcher localMatcher = JMeterUtils.getMatcher(); // The headers and body are divided by a blank line (the \r is to allow for the CR before LF) String regularExpression = "^\\r$"; // $NON-NLS-1$ @@ -316,7 +359,7 @@ private static int getPositionOfBody(String stringToCheck) { | Perl5Compiler.MULTILINE_MASK); PatternMatcherInput input = new PatternMatcherInput(stringToCheck); - if(localMatcher.contains(input, pattern)) { + if (localMatcher.contains(input, pattern)) { MatchResult match = localMatcher.getMatch(); return match.beginOffset(0); } From 1efe1ee2818c4ef141e42ac4d0a8a7ca5cc20968 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Thu, 24 Feb 2022 16:32:26 +0100 Subject: [PATCH 105/736] Use isEmpty instead of comparing length to zero --- .../protocol/http/sampler/HTTPSamplerBase.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java index ad8cecc5b05..ddf8895133e 100644 --- a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java +++ b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java @@ -381,9 +381,9 @@ public boolean getSendFileAsPostBody() { // If there is one file with no parameter name, the file will // be sent as post body. HTTPFileArg[] files = getHTTPFiles(); - return (files.length == 1) - && (files[0].getPath().length() > 0) - && (files[0].getParamName().length() == 0); + return files.length == 1 + && !files[0].getPath().isEmpty() + && files[0].getParamName().isEmpty(); } /** @@ -402,7 +402,7 @@ public boolean getSendParameterValuesAsPostBody() { for (JMeterProperty jMeterProperty : getArguments()) { hasArguments = true; HTTPArgument arg = (HTTPArgument) jMeterProperty.getObjectValue(); - if (arg.getName() != null && arg.getName().length() > 0) { + if (arg.getName() != null && !arg.getName().isEmpty()) { return false; } } @@ -458,7 +458,7 @@ public void setProtocol(String value) { */ public String getProtocol() { String protocol = getPropertyAsString(PROTOCOL); - if (protocol == null || protocol.length() == 0) { + if (protocol == null || protocol.isEmpty()) { return DEFAULT_PROTOCOL; } return protocol; @@ -1104,7 +1104,7 @@ public URL getUrl() throws MalformedURLException { // If no encoding is specified by user, we will get it // encoded in UTF-8, which is what the HTTP spec says String queryString = getQueryString(getContentEncoding()); - if (queryString.length() > 0) { + if (!queryString.isEmpty()) { if (path.contains(QRY_PFX)) {// Already contains a prefix pathAndQuery.append(QRY_SEP); } else { @@ -1236,7 +1236,7 @@ public void parseArguments(String queryString, String contentEncoding) { name = arg; value = ""; } - if (name.length() > 0) { + if (!name.isEmpty()) { log.debug("Name: {} Value: {} Metadata: {}", name, value, metaData); // If we know the encoding, we can decode the argument value, // to make it easier to read for the user @@ -1367,7 +1367,7 @@ protected HTTPSampleResult downloadPageResources(final HTTPSampleResult pRes, fi String allowRegex = getEmbeddedUrlRE(); Perl5Matcher localMatcher = null; Pattern allowPattern = null; - if (allowRegex.length() > 0) { + if (!allowRegex.isEmpty()) { try { allowPattern = JMeterUtils.getPattern(allowRegex); localMatcher = JMeterUtils.getMatcher();// don't fetch unless pattern compiles @@ -1377,7 +1377,7 @@ protected HTTPSampleResult downloadPageResources(final HTTPSampleResult pRes, fi } Pattern excludePattern = null; String excludeRegex = getEmbededUrlExcludeRE(); - if (excludeRegex.length() > 0) { + if (!excludeRegex.isEmpty()) { try { excludePattern = JMeterUtils.getPattern(excludeRegex); if (localMatcher == null) { From 1654b75ec82d7dd1e352f7c7a68c59c92b71b3e4 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Thu, 24 Feb 2022 17:00:43 +0100 Subject: [PATCH 106/736] Add a switch to decide which regex engine should be used --- .../http/sampler/HTTPSamplerBase.java | 57 +++++++++++-------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java index ddf8895133e..57985dc7ef7 100644 --- a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java +++ b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java @@ -41,6 +41,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; +import java.util.function.Predicate; +import java.util.regex.PatternSyntaxException; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; @@ -320,6 +322,8 @@ public abstract class HTTPSamplerBase extends AbstractSampler private static final boolean SEPARATE_CONTAINER = JMeterUtils.getPropDefault("httpsampler.separate.container", true); // $NON-NLS-1$ + private boolean useJavaRegex = JMeterUtils.getPropDefault("jmeter.use_java_regex", false); + static { String[] parsers = JOrphanUtils.split(RESPONSE_PARSERS, " " , true);// returns empty array for null for (final String parser : parsers) { @@ -1365,28 +1369,9 @@ protected HTTPSampleResult downloadPageResources(final HTTPSampleResult pRes, fi // Get the URL matcher String allowRegex = getEmbeddedUrlRE(); - Perl5Matcher localMatcher = null; - Pattern allowPattern = null; - if (!allowRegex.isEmpty()) { - try { - allowPattern = JMeterUtils.getPattern(allowRegex); - localMatcher = JMeterUtils.getMatcher();// don't fetch unless pattern compiles - } catch (MalformedCachePatternException e) { // NOSONAR - log.warn("Ignoring embedded URL match string: {}", e.getMessage()); - } - } - Pattern excludePattern = null; + Predicate allowPredicate = generateMatcherPredicate(allowRegex, "allow", true); String excludeRegex = getEmbededUrlExcludeRE(); - if (!excludeRegex.isEmpty()) { - try { - excludePattern = JMeterUtils.getPattern(excludeRegex); - if (localMatcher == null) { - localMatcher = JMeterUtils.getMatcher();// don't fetch unless pattern compiles - } - } catch (MalformedCachePatternException e) { // NOSONAR - log.warn("Ignoring embedded URL exclude string: {}", e.getMessage()); - } - } + Predicate excludePredicate = generateMatcherPredicate(excludeRegex, "exclude", false); // For concurrent get resources final List> list = new ArrayList<>(); @@ -1423,12 +1408,11 @@ protected HTTPSampleResult downloadPageResources(final HTTPSampleResult pRes, fi setParentSampleSuccess(res, false); continue; } - log.debug("allowPattern: {}, excludePattern: {}, localMatcher: {}, url: {}", allowPattern, excludePattern, localMatcher, url); - // I don't think localMatcher can be null here, but check just in case - if (allowPattern != null && localMatcher != null && !localMatcher.matches(url.toString(), allowPattern)) { + log.debug("allowPattern: {}, excludePattern: {}, url: {}", allowRegex, excludeRegex, url); + if (!allowPredicate.test(url)) { continue; // we have a pattern and the URL does not match, so skip it } - if (excludePattern != null && localMatcher != null && localMatcher.matches(url.toString(), excludePattern)) { + if (excludePredicate.test(url)) { continue; // we have a pattern and the URL does not match, so skip it } try { @@ -1491,6 +1475,29 @@ protected HTTPSampleResult downloadPageResources(final HTTPSampleResult pRes, fi return res; } + private Predicate generateMatcherPredicate(String regex, String explanation, boolean defaultAnswer) { + if (StringUtils.isEmpty(regex)) { + return s -> defaultAnswer; + } + if (useJavaRegex) { + try { + java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(regex); + return s -> pattern.matcher(s.toString()).matches(); + } catch (PatternSyntaxException e) { + log.warn("Ignoring embedded URL {} string: {}", explanation, e.getMessage()); + return s -> defaultAnswer; + } + } + try { + Pattern pattern = JMeterUtils.getPattern(regex); + Perl5Matcher matcher = JMeterUtils.getMatcher(); + return s -> matcher.matches(s.toString(), pattern); + } catch (MalformedCachePatternException e) { // NOSONAR + log.warn("Ignoring embedded URL {} string: {}", explanation, e.getMessage()); + return s -> defaultAnswer; + } + } + static void registerParser(String contentType, String className) { log.info("Parser for {} is {}", contentType, className); PARSERS_FOR_CONTENT_TYPE.put(contentType, className); From 5de17638ba2b1bc5b0c09fd4e37c20b83863251d Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Thu, 24 Feb 2022 17:41:49 +0100 Subject: [PATCH 107/736] Add a cache to store compiled Patterns into JMeterUtils --- .../org/apache/jmeter/util/JMeterUtils.java | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/core/src/main/java/org/apache/jmeter/util/JMeterUtils.java b/src/core/src/main/java/org/apache/jmeter/util/JMeterUtils.java index a6b40c64a9c..a19d5a04331 100644 --- a/src/core/src/main/java/org/apache/jmeter/util/JMeterUtils.java +++ b/src/core/src/main/java/org/apache/jmeter/util/JMeterUtils.java @@ -53,6 +53,7 @@ import javax.swing.SwingUtilities; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; import org.apache.jmeter.gui.GuiPackage; import org.apache.jmeter.threads.JMeterContextService; import org.apache.jorphan.gui.JFactory; @@ -70,6 +71,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.github.benmanes.caffeine.cache.Caffeine; +import com.github.benmanes.caffeine.cache.LoadingCache; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.security.AnyTypePermission; import com.thoughtworks.xstream.security.NoTypePermission; @@ -95,6 +98,20 @@ private LazyPatternCacheHolder() { new Perl5Compiler()); } + private static final class LazyJavaPatternCacheHolder { + private LazyJavaPatternCacheHolder() { + super(); + }; + public static final LoadingCache, java.util.regex.Pattern> INSTANCE = + Caffeine + .newBuilder() + .maximumSize(getPropDefault("java_regex.patterncache.size", 1000)) + .build(key -> { + //noinspection MagicConstant + return java.util.regex.Pattern.compile(key.getLeft(), key.getRight().intValue()); + }); + } + public static final String RES_KEY_PFX = "[res_key="; // $NON-NLS-1$ private static final String EXPERT_MODE_PROPERTY = "jmeter.expertMode"; // $NON-NLS-1$ @@ -253,6 +270,14 @@ public static Properties loadProperties(String file, Properties defaultProps) { return p; } + public static java.util.regex.Pattern compilePattern(String expression) { + return compilePattern(expression, 0); + } + + public static java.util.regex.Pattern compilePattern(String expression, int flags) { + return LazyJavaPatternCacheHolder.INSTANCE.get(Pair.of(expression, Integer.valueOf(flags))); + } + public static PatternCacheLRU getPatternCache() { return LazyPatternCacheHolder.INSTANCE; } @@ -270,7 +295,6 @@ public static PatternCacheLRU getPatternCache() { public static Pattern getPattern(String expression) throws MalformedCachePatternException { return getPattern(expression, Perl5Compiler.READ_ONLY_MASK); } - /** * Get a compiled expression from the pattern cache. * From 6b01e55ecf23405d36f2e09b92445546df365a77 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Thu, 24 Feb 2022 17:53:51 +0100 Subject: [PATCH 108/736] Remove useless semicolon --- src/core/src/main/java/org/apache/jmeter/util/JMeterUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/src/main/java/org/apache/jmeter/util/JMeterUtils.java b/src/core/src/main/java/org/apache/jmeter/util/JMeterUtils.java index a19d5a04331..5ccf37daab4 100644 --- a/src/core/src/main/java/org/apache/jmeter/util/JMeterUtils.java +++ b/src/core/src/main/java/org/apache/jmeter/util/JMeterUtils.java @@ -101,7 +101,7 @@ private LazyPatternCacheHolder() { private static final class LazyJavaPatternCacheHolder { private LazyJavaPatternCacheHolder() { super(); - }; + } public static final LoadingCache, java.util.regex.Pattern> INSTANCE = Caffeine .newBuilder() From fe66021be8e009c0f685a1b2332c6191927428b2 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Thu, 24 Feb 2022 19:00:46 +0100 Subject: [PATCH 109/736] Rename property for regex cache size That way -- as Vladimir pointed out -- it would be more consistent to a potentially renamed property jmeter.regex.engine, which would replace the boolean property jmeter.use_java_regex. --- src/core/src/main/java/org/apache/jmeter/util/JMeterUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/src/main/java/org/apache/jmeter/util/JMeterUtils.java b/src/core/src/main/java/org/apache/jmeter/util/JMeterUtils.java index 5ccf37daab4..3a8408bb2a7 100644 --- a/src/core/src/main/java/org/apache/jmeter/util/JMeterUtils.java +++ b/src/core/src/main/java/org/apache/jmeter/util/JMeterUtils.java @@ -105,7 +105,7 @@ private LazyJavaPatternCacheHolder() { public static final LoadingCache, java.util.regex.Pattern> INSTANCE = Caffeine .newBuilder() - .maximumSize(getPropDefault("java_regex.patterncache.size", 1000)) + .maximumSize(getPropDefault("jmeter.regex.patterncache.size", 1000)) .build(key -> { //noinspection MagicConstant return java.util.regex.Pattern.compile(key.getLeft(), key.getRight().intValue()); From 4e21125aef15040ef3b992492b69a5eef3698089 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Thu, 24 Feb 2022 19:04:48 +0100 Subject: [PATCH 110/736] use 'modern' Java features as isEmpty and contains --- .../jmeter/protocol/http/modifier/URLRewritingModifier.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/modifier/URLRewritingModifier.java b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/modifier/URLRewritingModifier.java index 1cb6c1e1ed0..ac1250372bc 100644 --- a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/modifier/URLRewritingModifier.java +++ b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/modifier/URLRewritingModifier.java @@ -119,7 +119,7 @@ public void process() { // Bug 15025 - save session value across samplers if (shouldCache()){ - if (value == null || value.length() == 0) { + if (value == null || value.isEmpty()) { value = savedValue; } else { savedValue = value; @@ -132,7 +132,7 @@ private void modify(HTTPSamplerBase sampler, String value) { if (isPathExtension()) { String oldPath = sampler.getPath(); int indexOfSessionId = oldPath.indexOf(SEMI_COLON + getArgumentName()); - if(oldPath.indexOf(SEMI_COLON + getArgumentName())>=0) { + if(oldPath.contains(SEMI_COLON + getArgumentName())) { int indexOfQuestionMark = oldPath.indexOf('?'); if(indexOfQuestionMark < 0) { oldPath = oldPath.substring(0, indexOfSessionId); From d61b9d3550dcf8757d9bdfe70fb64e20f63f9211 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Thu, 24 Feb 2022 19:40:14 +0100 Subject: [PATCH 111/736] Add a switch to decide which regex engine should be used --- .../http/modifier/URLRewritingModifier.java | 196 +++++++++++------- 1 file changed, 121 insertions(+), 75 deletions(-) diff --git a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/modifier/URLRewritingModifier.java b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/modifier/URLRewritingModifier.java index ac1250372bc..d5986742d6c 100644 --- a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/modifier/URLRewritingModifier.java +++ b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/modifier/URLRewritingModifier.java @@ -18,6 +18,8 @@ package org.apache.jmeter.protocol.http.modifier; import java.io.Serializable; +import java.util.function.Function; +import java.util.regex.Matcher; import org.apache.jmeter.processor.PreProcessor; import org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase; @@ -41,15 +43,11 @@ public class URLRewritingModifier extends AbstractTestElement implements Seriali private static final String SEMI_COLON = ";"; // $NON-NLS-1$ - private transient Pattern pathExtensionEqualsQuestionmarkRegexp; - - private transient Pattern pathExtensionEqualsNoQuestionmarkRegexp; - - private transient Pattern parameterRegexp; - - private transient Pattern pathExtensionNoEqualsQuestionmarkRegexp; - - private transient Pattern pathExtensionNoEqualsNoQuestionmarkRegexp; + private transient Function pathExtensionEqualsQuestionmarkExtractor; + private transient Function pathExtensionEqualsNoQuestionmarkExtractor; + private transient Function pathExtensionNoEqualsQuestionmarkExtractor; + private transient Function pathExtensionNoEqualsNoQuestionmarkExtractor; + private transient Function parameterExtractor; private static final String ARGUMENT_NAME = "argument_name"; // $NON-NLS-1$ @@ -63,6 +61,8 @@ public class URLRewritingModifier extends AbstractTestElement implements Seriali private static final String ENCODE = "encode"; // $NON-NLS-1$ + private boolean useJavaRegex = JMeterUtils.getPropDefault("jmeter.use_java_regex", false); + // PreProcessors are cloned per-thread, so this will be saved per-thread private transient String savedValue = ""; // $NON-NLS-1$ @@ -79,46 +79,21 @@ public void process() { } initRegex(getArgumentName()); String text = responseText.getResponseDataAsString(); - Perl5Matcher matcher = JMeterUtils.getMatcher(); - String value = ""; + String value; if (isPathExtension() && isPathExtensionNoEquals() && isPathExtensionNoQuestionmark()) { - if (matcher.contains(text, pathExtensionNoEqualsNoQuestionmarkRegexp)) { - MatchResult result = matcher.getMatch(); - value = result.group(1); - } - } else if (isPathExtension() && isPathExtensionNoEquals()) // && !isPathExtensionNoQuestionmark() - { - if (matcher.contains(text, pathExtensionNoEqualsQuestionmarkRegexp)) { - MatchResult result = matcher.getMatch(); - value = result.group(1); - } - } else if (isPathExtension() && isPathExtensionNoQuestionmark()) // && !isPathExtensionNoEquals() - { - if (matcher.contains(text, pathExtensionEqualsNoQuestionmarkRegexp)) { - MatchResult result = matcher.getMatch(); - value = result.group(1); - } - } else if (isPathExtension()) // && !isPathExtensionNoEquals() && !isPathExtensionNoQuestionmark() - { - if (matcher.contains(text, pathExtensionEqualsQuestionmarkRegexp)) { - MatchResult result = matcher.getMatch(); - value = result.group(1); - } - } else // if ! isPathExtension() - { - if (matcher.contains(text, parameterRegexp)) { - MatchResult result = matcher.getMatch(); - for (int i = 1; i < result.groups(); i++) { - value = result.group(i); - if (value != null) { - break; - } - } - } + value = pathExtensionEqualsQuestionmarkExtractor.apply(text); + } else if (isPathExtension() && isPathExtensionNoEquals()) { // && !isPathExtensionNoQuestionmark() + value = pathExtensionEqualsNoQuestionmarkExtractor.apply(text); + } else if (isPathExtension() && isPathExtensionNoQuestionmark()) { // && !isPathExtensionNoEquals() + value = pathExtensionNoEqualsQuestionmarkExtractor.apply(text); + } else if (isPathExtension()) { // && !isPathExtensionNoEquals() && !isPathExtensionNoQuestionmark() + value = pathExtensionNoEqualsNoQuestionmarkExtractor.apply(text); + } else { // if ! isPathExtension() + value = parameterExtractor.apply(text); } // Bug 15025 - save session value across samplers - if (shouldCache()){ + if (shouldCache()) { if (value == null || value.isEmpty()) { value = savedValue; } else { @@ -158,42 +133,113 @@ public void setArgumentName(String argName) { private void initRegex(String argName) { String quotedArg = Perl5Compiler.quotemeta(argName);// Don't get tripped up by RE chars in the arg name - pathExtensionEqualsQuestionmarkRegexp = JMeterUtils.getPatternCache().getPattern( - SEMI_COLON + quotedArg + "=([^\"'<>&\\s;]*)", // $NON-NLS-1$ - Perl5Compiler.MULTILINE_MASK | Perl5Compiler.READ_ONLY_MASK); + pathExtensionEqualsQuestionmarkExtractor = generateExtractor( + SEMI_COLON + quotedArg + "=([^\"'<>&\\s;]*)" // $NON-NLS-1$ + ); + pathExtensionEqualsNoQuestionmarkExtractor = generateExtractor( + SEMI_COLON + quotedArg + "=([^\"'<>&\\s;?]*)" // $NON-NLS-1$ + ); + pathExtensionNoEqualsQuestionmarkExtractor = generateExtractor( + SEMI_COLON + quotedArg + "([^\"'<>&\\s;]*)"// $NON-NLS-1$ + ); + pathExtensionNoEqualsNoQuestionmarkExtractor = generateExtractor( + SEMI_COLON + quotedArg + "([^\"'<>&\\s;?]*)" // $NON-NLS-1$ + ); + + parameterExtractor = generateFirstMatchExtractor( + // ;sessionid=value + "[;\\?&]" + quotedArg + "=([^\"'<>&\\s;\\\\]*)" // $NON-NLS-1$ + + // name="sessionid" value="value" + + "|\\s[Nn][Aa][Mm][Ee]\\s*=\\s*[\"']" + quotedArg + + "[\"']" + "[^>]*" // $NON-NLS-1$ + + "\\s[vV][Aa][Ll][Uu][Ee]\\s*=\\s*[\"']" // $NON-NLS-1$ + + "([^\"']*)" + "[\"']" // $NON-NLS-1$ + + // value="value" name="sessionid" + + "|\\s[vV][Aa][Ll][Uu][Ee]\\s*=\\s*[\"']" // $NON-NLS-1$ + + "([^\"']*)" + "[\"']" + "[^>]*" // $NON-NLS-1$ // $NON-NLS-2$ // $NON-NLS-3$ + + "\\s[Nn][Aa][Mm][Ee]\\s*=\\s*[\"']" // $NON-NLS-1$ + + quotedArg + "[\"']" // $NON-NLS-1$ + ); + // NOTE: the handling of simple- vs. double-quotes could be formally + // more accurate, but I can't imagine a session id containing + // either, so we should be OK. The whole set of expressions is a + // quick hack anyway, so who cares. + } - pathExtensionEqualsNoQuestionmarkRegexp = JMeterUtils.getPatternCache().getPattern( - SEMI_COLON + quotedArg + "=([^\"'<>&\\s;?]*)", // $NON-NLS-1$ - Perl5Compiler.MULTILINE_MASK | Perl5Compiler.READ_ONLY_MASK); + private Function generateExtractor(String regex) { + if (useJavaRegex) { + return generateExtractorWithJavaRegex(regex); + } + return generateExtractorWithOroRegex(regex); + } - pathExtensionNoEqualsQuestionmarkRegexp = JMeterUtils.getPatternCache().getPattern( - SEMI_COLON + quotedArg + "([^\"'<>&\\s;]*)", // $NON-NLS-1$ - Perl5Compiler.MULTILINE_MASK | Perl5Compiler.READ_ONLY_MASK); + private Function generateExtractorWithJavaRegex(String regex) { + java.util.regex.Pattern pattern = java.util.regex.Pattern.compile( + regex, + java.util.regex.Pattern.MULTILINE); + return text -> { + Matcher matcher = pattern.matcher(text); + if (matcher.find()) { + return matcher.group(1); + } + return ""; + }; + } - pathExtensionNoEqualsNoQuestionmarkRegexp = JMeterUtils.getPatternCache().getPattern( - SEMI_COLON + quotedArg + "([^\"'<>&\\s;?]*)", // $NON-NLS-1$ + private Function generateExtractorWithOroRegex(String regex) { + Pattern pattern = JMeterUtils.getPatternCache().getPattern( + regex, Perl5Compiler.MULTILINE_MASK | Perl5Compiler.READ_ONLY_MASK); + Perl5Matcher matcher = JMeterUtils.getMatcher(); + return text -> { + if (matcher.contains(text, pattern)) { + MatchResult result = matcher.getMatch(); + return result.group(1); + } + return ""; + }; + } - parameterRegexp = JMeterUtils.getPatternCache().getPattern( - // ;sessionid=value - "[;\\?&]" + quotedArg + "=([^\"'<>&\\s;\\\\]*)" + // $NON-NLS-1$ - - // name="sessionid" value="value" - "|\\s[Nn][Aa][Mm][Ee]\\s*=\\s*[\"']" + quotedArg - + "[\"']" + "[^>]*" // $NON-NLS-1$ - + "\\s[vV][Aa][Ll][Uu][Ee]\\s*=\\s*[\"']" // $NON-NLS-1$ - + "([^\"']*)" + "[\"']" // $NON-NLS-1$ - - // value="value" name="sessionid" - + "|\\s[vV][Aa][Ll][Uu][Ee]\\s*=\\s*[\"']" // $NON-NLS-1$ - + "([^\"']*)" + "[\"']" + "[^>]*" // $NON-NLS-1$ // $NON-NLS-2$ // $NON-NLS-3$ - + "\\s[Nn][Aa][Mm][Ee]\\s*=\\s*[\"']" // $NON-NLS-1$ - + quotedArg + "[\"']", // $NON-NLS-1$ + private Function generateFirstMatchExtractor(String regex) { + if (useJavaRegex) { + return generateFirstMatchExtractorWithJavaRegex(regex); + } + return generateFirstMatchExtractorWithOroRegex(regex); + } + + private Function generateFirstMatchExtractorWithJavaRegex(String regex) { + java.util.regex.Pattern pattern = java.util.regex.Pattern.compile( + regex, + java.util.regex.Pattern.MULTILINE); + return text -> { + Matcher matcher = pattern.matcher(text); + for (int i = 1; i < matcher.groupCount(); i++) { + String value = matcher.group(i); + if (value != null) { + return value; + } + } + return ""; + }; + } + + private Function generateFirstMatchExtractorWithOroRegex(String regex) { + Pattern pattern = JMeterUtils.getPatternCache().getPattern( + regex, Perl5Compiler.MULTILINE_MASK | Perl5Compiler.READ_ONLY_MASK); - // NOTE: the handling of simple- vs. double-quotes could be formally - // more accurate, but I can't imagine a session id containing - // either, so we should be OK. The whole set of expressions is a - // quick hack anyway, so who cares. + Perl5Matcher matcher = JMeterUtils.getMatcher(); + return text -> { + MatchResult result = matcher.getMatch(); + for (int i = 1; i < result.groups(); i++) { + String value = result.group(i); + if (value != null) { + return value; + } + } + return ""; + }; } public String getArgumentName() { From 949a028802ad5d1f53186753632a2242d93fa463 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Thu, 24 Feb 2022 19:49:02 +0100 Subject: [PATCH 112/736] Fix missing 'contains'/'find' for pattern --- .../http/modifier/URLRewritingModifier.java | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/modifier/URLRewritingModifier.java b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/modifier/URLRewritingModifier.java index d5986742d6c..7565727ad2e 100644 --- a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/modifier/URLRewritingModifier.java +++ b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/modifier/URLRewritingModifier.java @@ -215,10 +215,12 @@ private Function generateFirstMatchExtractorWithJavaRegex(String java.util.regex.Pattern.MULTILINE); return text -> { Matcher matcher = pattern.matcher(text); - for (int i = 1; i < matcher.groupCount(); i++) { - String value = matcher.group(i); - if (value != null) { - return value; + if (matcher.find()) { + for (int i = 1; i < matcher.groupCount(); i++) { + String value = matcher.group(i); + if (value != null) { + return value; + } } } return ""; @@ -231,11 +233,13 @@ private Function generateFirstMatchExtractorWithOroRegex(String Perl5Compiler.MULTILINE_MASK | Perl5Compiler.READ_ONLY_MASK); Perl5Matcher matcher = JMeterUtils.getMatcher(); return text -> { - MatchResult result = matcher.getMatch(); - for (int i = 1; i < result.groups(); i++) { - String value = result.group(i); - if (value != null) { - return value; + if (matcher.contains(text, pattern)) { + MatchResult result = matcher.getMatch(); + for (int i = 1; i < result.groups(); i++) { + String value = result.group(i); + if (value != null) { + return value; + } } } return ""; From f9cb8fca34e93382ad3f7cb04970b1c6c001d413 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Thu, 24 Feb 2022 20:01:18 +0100 Subject: [PATCH 113/736] Use correct order of extractors too many No's there :) --- .../protocol/http/modifier/URLRewritingModifier.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/modifier/URLRewritingModifier.java b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/modifier/URLRewritingModifier.java index 7565727ad2e..67155eaab5c 100644 --- a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/modifier/URLRewritingModifier.java +++ b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/modifier/URLRewritingModifier.java @@ -81,13 +81,13 @@ public void process() { String text = responseText.getResponseDataAsString(); String value; if (isPathExtension() && isPathExtensionNoEquals() && isPathExtensionNoQuestionmark()) { - value = pathExtensionEqualsQuestionmarkExtractor.apply(text); + value = pathExtensionNoEqualsNoQuestionmarkExtractor.apply(text); } else if (isPathExtension() && isPathExtensionNoEquals()) { // && !isPathExtensionNoQuestionmark() - value = pathExtensionEqualsNoQuestionmarkExtractor.apply(text); - } else if (isPathExtension() && isPathExtensionNoQuestionmark()) { // && !isPathExtensionNoEquals() value = pathExtensionNoEqualsQuestionmarkExtractor.apply(text); + } else if (isPathExtension() && isPathExtensionNoQuestionmark()) { // && !isPathExtensionNoEquals() + value = pathExtensionEqualsNoQuestionmarkExtractor.apply(text); } else if (isPathExtension()) { // && !isPathExtensionNoEquals() && !isPathExtensionNoQuestionmark() - value = pathExtensionNoEqualsNoQuestionmarkExtractor.apply(text); + value = pathExtensionEqualsQuestionmarkExtractor.apply(text); } else { // if ! isPathExtension() value = parameterExtractor.apply(text); } From affa4994d435318d2e7cc603b30341977258f5a1 Mon Sep 17 00:00:00 2001 From: Felix Schumacher Date: Thu, 24 Feb 2022 20:10:44 +0100 Subject: [PATCH 114/736] Add missing closing parenthesis in javadoc --- .../apache/jmeter/protocol/http/parser/RegexpHTMLParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/parser/RegexpHTMLParser.java b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/parser/RegexpHTMLParser.java index 47ff39d2e46..0e421cd1bdc 100644 --- a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/parser/RegexpHTMLParser.java +++ b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/parser/RegexpHTMLParser.java @@ -37,7 +37,7 @@ * HtmlParser implementation using regular expressions. *

    * This class will find URLs specified in the following ways (where url - * represents the URL being found: + * represents the URL being found): *