Merge branch 'master' into bug_64553

This commit is contained in:
pmouawad 2020-08-30 14:22:19 +02:00
commit 459efe1bee
57 changed files with 681 additions and 409 deletions

View File

@ -22,10 +22,12 @@ jobs:
uses: actions/setup-java@v1
with:
java-version: 14
- name: 'Test'
shell: bash
run: |
./gradlew --no-parallel build -x distTar -x distTarSource
- uses: burrunan/gradle-cache-action@v1
name: Test
with:
job-id: jdk14
multi-cache-enabled: false
arguments: --scan --no-parallel build -x distTar -x distTarSource
mac:
name: 'macOS (JDK 14)'
@ -38,6 +40,9 @@ jobs:
uses: actions/setup-java@v1
with:
java-version: 14
- name: 'Test'
run: |
./gradlew --no-parallel build -x distTar -x distTarSource -Dskip.test_TestDNSCacheManager.testWithCustomResolverAnd1Server=true
- uses: burrunan/gradle-cache-action@v1
name: Test
with:
job-id: jdk14
multi-cache-enabled: false
arguments: --scan --no-parallel build -x distTar -x distTarSource -Dskip.test_TestDNSCacheManager.testWithCustomResolverAnd1Server=true

View File

@ -107,7 +107,7 @@ The following requirements exist for running Apache JMeter:
- Java Compiler (*OPTIONAL*):
A Java compiler is not needed since the distribution cludes a
A Java compiler is not needed since the distribution includes a
precompiled Java binary archive.
> **Note** that a compiler is required to build plugins for Apache JMeter.
@ -126,7 +126,7 @@ The following requirements exist for running Apache JMeter:
### Windows
For Windows there are also some other scripts which you can drag-and-drop
For Windows, there are also some other scripts which you can drag-and-drop
a JMX file onto:
- `jmeter-n.cmd` - runs the file as a non-GUI test
@ -160,7 +160,7 @@ _This is useful for testing what happens if the optional jars are not
downloaded by other JMeter users._
If you are behind a proxy, you can set a few build properties in
`~/.gradle/gradle.properties` for gradle to use the proxy:
`~/.gradle/gradle.properties` for Gradle to use the proxy:
```properties
systemProp.http.proxyHost=proxy.example.invalid
@ -193,14 +193,16 @@ The output artifacts (jars, reports) are placed in the `build` folder.
For instance, binary artifacts can be found under `src/dist/build/distributions`.
The following command would compile the application and enable you to run `jmeter`
from the `bin` directory. Note: it completely refreshes `lib/` contents,
so it would remove clustom plugins should you have them installed.
from the `bin` directory.
> **Note** that it completely refreshes `lib/` contents,
so it would remove custom plugins should you have them installed.
```sh
./gradlew createDist
```
Alternatively you could get Gradle to start the GUI:
Alternatively, you could get Gradle to start the GUI:
```sh
./gradlew runGui

View File

@ -140,6 +140,14 @@
# See https://bz.apache.org/bugzilla/show_bug.cgi?id=52026 for details
# N.B. the LAF can be defined in user.properties.
# Enable custom window chrome for Darklaf Look and Feels.
# defaults to false
# darklaf.decorations=false
# Enables the unified menubar for Darklaf Look and Feels.
# defaults to true
# darklaf.unifiedMenuBar=true
# LoggerPanel display
# default to false
#jmeter.loggerpanel.display=false

View File

@ -15,8 +15,7 @@
* limitations under the License.
*/
import com.github.spotbugs.SpotBugsPlugin
import com.github.spotbugs.SpotBugsTask
import com.github.spotbugs.snom.SpotBugsTask
import com.github.vlsi.gradle.crlf.CrLfSpec
import com.github.vlsi.gradle.crlf.LineEndings
import com.github.vlsi.gradle.crlf.filter
@ -188,11 +187,15 @@ sonarqube {
}
}
fun SonarQubeProperties.add(name: String, value: String) {
properties.getOrPut(name) { mutableSetOf<String>() }
fun SonarQubeProperties.add(name: String, valueProvider: () -> String) {
properties.getOrPut(name) { mutableSetOf<Any>() }
.also {
@Suppress("UNCHECKED_CAST")
(it as MutableCollection<String>).add(value)
(it as MutableCollection<Any>).add(object {
// SonarQube calls toString when converting properties to values
// (see SonarQubeProperties), so we use that to emulate "lazy properties"
override fun toString() = valueProvider()
})
}
}
@ -239,7 +242,11 @@ if (enableSpotBugs) {
sonarqube {
properties {
spotBugTasks.configureEach {
add("sonar.java.spotbugs.reportPaths", reports.xml.destination.toString())
add("sonar.java.spotbugs.reportPaths") {
// Note: report is created with lower-case xml, and then
// the created entry MUST be retrieved as upper-case XML
reports.named("XML").get().destination.toString()
}
}
}
}
@ -321,8 +328,14 @@ allprojects {
}
val sourceSets: SourceSetContainer by project
if (sourceSets.isNotEmpty()) {
val checkstyleTasks = tasks.withType<Checkstyle>()
checkstyleTasks.configureEach {
// Checkstyle 8.26 does not need classpath, see https://github.com/gradle/gradle/issues/14227
classpath = files()
}
tasks.register("checkstyleAll") {
dependsOn(tasks.withType<Checkstyle>())
dependsOn(checkstyleTasks)
}
tasks.register("checkstyle") {
group = LifecycleBasePlugin.VERIFICATION_GROUP
@ -341,11 +354,11 @@ allprojects {
}
}
}
apply<SpotBugsPlugin>()
apply(plugin = "com.github.spotbugs")
spotbugs {
toolVersion = "spotbugs".v
isIgnoreFailures = ignoreSpotBugsFailures
toolVersion.set("spotbugs".v)
ignoreFailures.set(ignoreSpotBugsFailures)
}
if (!skipAutostyle) {
@ -457,21 +470,17 @@ allprojects {
options.encoding = "UTF-8"
}
withType<ProcessResources>().configureEach {
from(source) {
include("**/*.properties")
filteringCharset = "UTF-8"
// apply native2ascii conversion since Java 8 expects properties to have ascii symbols only
filter(org.apache.tools.ant.filters.EscapeUnicode::class)
filter(LineEndings.LF)
}
// Text-like resources are normalized to LF (just for consistency purposes)
// This makes to produce exactly the same jar files no matter which OS is used for the build
from(source) {
include("**/*.dtd")
include("**/*.svg")
include("**/*.txt")
filteringCharset = "UTF-8"
filter(LineEndings.LF)
filteringCharset = "UTF-8"
eachFile {
if (name.endsWith(".properties")) {
filteringCharset = "UTF-8"
// apply native2ascii conversion since Java 8 expects properties to have ascii symbols only
filter(org.apache.tools.ant.filters.EscapeUnicode::class)
filter(LineEndings.LF)
} else if (name.endsWith(".dtd") || name.endsWith(".svg") ||
name.endsWith(".txt")) {
filter(LineEndings.LF)
}
}
}
afterEvaluate {
@ -506,6 +515,11 @@ allprojects {
exceptionFormat = TestExceptionFormat.FULL
showStandardStreams = true
}
outputs.cacheIf("test outcomes sometimes depends on third-party systems, so we should not cache it for now") {
false
}
// Pass the property to tests
fun passProperty(name: String, default: String? = null) {
val value = System.getProperty(name) ?: default
@ -522,10 +536,11 @@ allprojects {
description = "$description (skipped by default, to enable it add -Dspotbugs)"
}
reports {
html.isEnabled = reportsForHumans()
xml.isEnabled = !reportsForHumans()
// This is for Sonar
xml.isWithMessages = true
// xml goes for SonarQube, so we always create it just in case
create("xml")
if (reportsForHumans()) {
create("html")
}
}
enabled = enableSpotBugs
}

View File

@ -54,6 +54,9 @@
<dependency group='org.gradle.kotlin' module='plugins' version='1.3.4'>
<sha512>B6F05B16B1826C3FD50D80AFD14965566B27313691A111EC8589867678D6B92AF827E5E098BECCE8F911D8B479AF5303322A6B2ECA971D1A2D985F42BD1AAA87</sha512>
</dependency>
<dependency group='org.gradle.kotlin' module='plugins' version='1.3.6'>
<sha512>FFC641492549525D06D6788A3D708C7108AFA06C35796EF0B3A71541672162A7BAFDE6DC8F90F63D524BA33D1447C172C589491C16CF3B91C2C3E150AAB71B46</sha512>
</dependency>
<dependency group='org.slf4j' module='jcl-over-slf4j' version='1.6.2'>
<sha512>3BA508C96EE0985865C9E86EBE803D1903835F7C198EB15723CDC86B028D6C82DBB7E96ECB01CEFAD7CC6EC7023155676D034B6B730A911D0FFE9F91FE532592</sha512>
</dependency>

View File

@ -17,7 +17,7 @@
*/
dependencies {
compile("org.ajoberstar.grgit:grgit-gradle:3.1.1")
implementation("org.ajoberstar.grgit:grgit-gradle:3.1.1")
}
gradlePlugin {

View File

@ -14,11 +14,13 @@
<trusted-key id='8ea48d105232855d' group='com.github.jknack' />
<trusted-key id='461a804f2609fd89' group='com.github.shyiko.klob' />
<trusted-key id='1756b920eecf0e90' group='com.github.spotbugs' />
<trusted-key id='a5def5a76f94a471' group='com.github.spotbugs' />
<trusted-key id='78fcd238c26ea995' group='com.github.tomakehurst' />
<trusted-key id='105cb91cac2aee0e' group='com.github.vlsi.gradle' />
<trusted-key id='254e9c64c264c176' group='com.github.weisj' />
<trusted-key id='59a252fb1199d873' group='com.google.code.findbugs' />
<trusted-key id='7a01b0f236e5430f' group='com.google.code.gson' />
<trusted-key id='1669c4bb543e0445' group='com.google.errorprone' />
<trusted-key id='912d2c0eccda55c0' group='com.google.errorprone' />
<trusted-key id='9a259c7ee636c5ed' group='com.google.errorprone' />
<trusted-key id='bf935c771a8474f8' group='com.google.errorprone' />
@ -39,6 +41,7 @@
<trusted-key id='6425559c47cc79c4' group='com.sun.activation' />
<trusted-key id='602ec18d20c4661c' group='com.thoughtworks.xstream' />
<trusted-key id='1861c322c56014b2' group='commons-beanutils' />
<trusted-key id='3faad2cd5ecbb314' group='commons-beanutils' />
<trusted-key id='411063a3a0ffd119' group='commons-beanutils' />
<trusted-key id='9daadc1c9fcc82d0' group='commons-cli' />
<trusted-key id='86fdc7e2a11262cb' group='commons-codec' />
@ -77,8 +80,8 @@
<trusted-key id='411063a3a0ffd119' group='org.apache-extras.beanshell' />
<trusted-key id='87a7f75a6a8ba5fc' group='org.apache.activemq' />
<trusted-key id='bff2ee42c8282e76' group='org.apache.activemq' />
<trusted-key id='ddbcc1270a29d081' group='org.apache.ant' />
<trusted-key id='a2115ae15f6b8b72' group='org.apache.ant' />
<trusted-key id='ddbcc1270a29d081' group='org.apache.ant' />
<trusted-key id='86fdc7e2a11262cb' group='org.apache.bcel' />
<trusted-key id='3faad2cd5ecbb314' group='org.apache.commons' />
<trusted-key id='64a16faaec16a4be' group='org.apache.commons' />
@ -130,6 +133,7 @@
<trusted-key id='98fe03a974ce0a0b' group='org.jetbrains.kotlin' />
<trusted-key id='379ce192d401ab61' group='org.jetbrains.kotlinx' />
<trusted-key id='91ae1504568ec4dd' group='org.jodd' />
<trusted-key id='145d819475314d97' group='org.json' />
<trusted-key id='f42e87f9665015c9' group='org.jsoup' />
<trusted-key id='85911f425ec61b51' group='org.junit.jupiter' />
<trusted-key id='85911f425ec61b51' group='org.junit.platform' />
@ -169,6 +173,9 @@
<dependency group='de.marcphilipp.gradle' module='nexus-publish-plugin' version='0.4.0'>
<sha512>37EC6DFBDDD0458A2A341E371D038B3B0A25AB2F9006B295EBCF3BDE873A8D02C8CDAA6C69D875500F67593C618E8EF62C0269FB2F7F527A1367A7D6B8EA3CBE</sha512>
</dependency>
<dependency group='gradle.plugin.com.github.spotbugs.snom' module='spotbugs-gradle-plugin' version='4.5.0'>
<sha512>36557C04B8FC7DC446B5FBDD6383A1B7281708B424C3039E7EC11807F3BB9A5E2764BE4BEC1D717C38595B12D8B291CB2A002D85B5E79DC9A9A4CBD27C58C7BB</sha512>
</dependency>
<dependency group='gradle.plugin.com.github.spotbugs' module='spotbugs-gradle-plugin' version='1.6.10'>
<sha512>E7486B32EF6C9C14FE879814DA5F06CA6ECABF47195063A93E6FC8CD10119244C5A7BC3C71A4760CCE3AFFA9E9736336D345D8ED84EB65153C15683FA6529D92</sha512>
</dependency>
@ -238,6 +245,9 @@
<dependency group='org.slf4j' module='slf4j-nop' version='1.6.2'>
<sha512>89F8559C281F6BCEA4EB193C49AA8C960A5FE6762DCA0198A7BB04B9D8A846AC52231F77EC16B2E9C0B48D0F6011517B641B5B93279B24EEF65EE22E2C1167F3</sha512>
</dependency>
<dependency group='org.sonarsource.scanner.gradle' module='sonarqube-gradle-plugin' version='3.0'>
<sha512>AFC41AFD611214C500CACA4D826652E38D5DDD1BCF182D935AFFD2B5B8DF26650DFEB76E4C06C2D46593E1FB86BB4D093438E8E862666E64AB32FB4B6EFEA30D</sha512>
</dependency>
<dependency group='oro' module='oro' version='2.0.8'>
<sha512>9A98E493C4D771322B1331EC05AB0E363A83D8AC2AF8018D96A44DF2BF5BFC97D33EBE6F6F93E46AB10BF1536F0C29E9D9569318ED49BC18B4E96B1A8B476D37</sha512>
</dependency>

View File

@ -68,6 +68,12 @@
<property name="fileExtensions" value="java, kt, kts, groovy"/>
</module>
<module name="LineLength">
<!-- TODO: reduce this to 120 -->
<property name="max" value="160"/>
<property name="fileExtensions" value="java, kt, kts, groovy"/>
</module>
<module name="TreeWalker">
<!-- Annotations -->
@ -178,10 +184,6 @@
<module name="AnonInnerLength">
<property name="max" value="45"/>
</module>
<module name="LineLength">
<!-- TODO: reduce this to 120 -->
<property name="max" value="160"/>
</module>
<!-- whitespace -->
<module name="EmptyForInitializerPad"/>

View File

@ -16,6 +16,10 @@
#
org.gradle.parallel=true
# Build cache can be disabled with --no-build-cache option
org.gradle.caching=true
#org.gradle.caching.debug=true
# See https://github.com/gradle/gradle/pull/11358 , https://issues.apache.org/jira/browse/INFRA-14923
# repository.apache.org does not yet support .sha256 and .sha512 checksums
systemProp.org.gradle.internal.publish.checksums.insecure=true
@ -28,28 +32,28 @@ kotlin.parallel.tasks.in.project=true
jmeter.version=5.3.1
# Tools
checkstyle.version=8.22
checkstyle.version=8.35
jacoco.version=0.8.5
spotbugs.version=3.1.12
spotbugs.version=4.1.2
velocity.version=1.7
# Plugins
com.github.autostyle.version=3.0
com.github.spotbugs.version=2.0.0
com.github.spotbugs.version=4.5.0
com.github.vlsi.checksum-dependency.sha512=4D1A76F38F327CEA0C723D9BDD9ABFE16933769052F47BCECD555DDD1A6CD0A9C21E3CC8F9E1B92780F9B443070D4844889EE9ECB0690D30E50AAB085096D8E1
com.github.vlsi.checksum-dependency.version=1.70
com.github.vlsi.vlsi-release-plugins.version=1.70
org.jetbrains.gradle.plugin.idea-ext.version=0.5
org.nosphere.apache.rat.version=0.5.3
org.sonarqube.version=2.7.1
org.sonarqube.version=3.0
# Dependencies
accessors-smart.version=1.2
activemq.version=5.15.11
activemq.version=5.16.0
apache-rat.version=0.13
apiguardian-api.version=1.1.0
asm.version=7.3.1
bouncycastle.version=1.64
bouncycastle.version=1.66
bsf.version=2.4.0
bsh.version=2.0b6
caffeine.version=2.8.0
@ -58,20 +62,19 @@ commons-codec.version=1.14
commons-collections.version=3.2.2
commons-collections4.version=4.4
commons-dbcp2.version=2.7.0
commons-io.version=2.6
commons-io.version=2.7
commons-jexl.version=2.1.1
commons-jexl3.version=3.1
commons-lang.version=2.6
commons-lang3.version=3.10
commons-lang3.version=3.11
commons-math3.version=3.6.1
commons-net.version=3.6
commons-pool2.version=2.8.0
commons-text.version=1.8
darklaf.version=2.4.2
#darklaf.version=latest.integration
commons-net.version=3.7
commons-pool2.version=2.8.1
commons-text.version=1.9
darklaf.version=2.4.5
dec.version=0.1.2
dnsjava.version=2.1.9
equalsverifier.version=3.1.13
equalsverifier.version=3.4.2
freemarker.version=2.3.30
ftplet-api.version=1.1.1
ftpserver-core.version=1.1.1
@ -98,8 +101,8 @@ json-smart.version=2.3
jsoup.version=1.13.1
jtidy.version=r938
junit4.version=4.13
junit5.version=5.6.0
log4j.version=2.13.1
junit5.version=5.6.2
log4j.version=2.13.3
mail.version=1.5.0-b01
miglayout.version=5.2
mina-core.version=2.0.19
@ -110,7 +113,7 @@ oro.version=2.0.8
ph-commons.version=9.4.1
ph-css.version=6.2.2
rhino.version=1.7.12
rsyntaxtextarea.version=3.1.0
rsyntaxtextarea.version=3.1.1
Saxon-HE.version=9.9.1-7
slf4j.version=1.7.30
spock-core.version=2.0-M2-groovy-3.0

Binary file not shown.

View File

@ -17,7 +17,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=0f316a67b971b7b571dac7215dcf2591a30994b3450e0629925ffcfe2c68cc5c
distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip
distributionSha256Sum=e6f83508f0970452f56197f610d13c5f593baaf43c0e3c6a571e5967be754025
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

2
gradlew vendored
View File

@ -82,6 +82,7 @@ esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
@ -129,6 +130,7 @@ fi
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath

22
gradlew.bat vendored
View File

@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@ -54,7 +54,7 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@ -64,28 +64,14 @@ echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell

View File

@ -32,6 +32,10 @@ pluginManagement {
}
}
plugins {
`gradle-enterprise`
}
// This is the name of a current project
// Note: it cannot be inferred from the directory name as developer might clone JMeter to jmeter_tmp folder
rootProject.name = "jmeter"
@ -92,6 +96,18 @@ if (property("localReleasePlugins").toBool(nullAs = false, blankAs = true, defau
includeBuild("../vlsi-release-plugins")
}
val isCiServer = System.getenv().containsKey("CI")
if (isCiServer) {
gradleEnterprise {
buildScan {
termsOfServiceUrl = "https://gradle.com/terms-of-service"
termsOfServiceAgree = "yes"
tag("CI")
}
}
}
// Checksum plugin sources can be validated at https://github.com/vlsi/vlsi-release-plugins
buildscript {
dependencies {
@ -107,6 +123,8 @@ buildscript {
// Note: we need to verify the checksum for checksum-dependency-plugin itself
val expectedSha512 = mapOf(
"F7040C571C2A2727F2EED4EA772F5A7C5D9CB393828B7A2331F7167E467429486F5F3E9423883FE9A6D652FFB0484EAE722CDFB46D97180209BCBEEBF9C25DE3"
to "gradle-enterprise-gradle-plugin-3.4.jar",
"43BC9061DFDECA0C421EDF4A76E380413920E788EF01751C81BDC004BD28761FBD4A3F23EA9146ECEDF10C0F85B7BE9A857E9D489A95476525565152E0314B5B"
to "bcpg-jdk15on-1.62.jar",
"2BA6A5DEC9C8DAC2EB427A65815EB3A9ADAF4D42D476B136F37CD57E6D013BF4E9140394ABEEA81E42FBDB8FC59228C7B85C549ED294123BF898A7D048B3BD95"
@ -137,7 +155,7 @@ val violations =
.joinToString("\n ") { (file, sha512) -> "SHA-512(${file.name}) = $sha512 ($file)" }
if (violations.isNotBlank()) {
throw GradleException("Buildscript classpath has permitted files that were not explicitly permitted:\n $violations")
throw GradleException("Buildscript classpath has files that were not explicitly permitted:\n $violations")
}
apply(plugin = "com.github.vlsi.checksum-dependency")

View File

@ -17,7 +17,7 @@
dependencies {
api(project(":src:core"))
testCompile(project(":src:core", "testClasses"))
testImplementation(project(":src:core", "testClasses"))
api("org.apache-extras.beanshell:bsh") {
because("""

View File

@ -121,9 +121,9 @@ public class HTMLAssertion extends AbstractTestElement implements Serializable,
|| (!isErrorsOnly() && warningsAboveThreshold)) {
log.debug("Errors/warnings detected while parsing with tidy: {}", errbuf);
result.setFailure(true);
result.setFailureMessage(MessageFormat.format("Tidy Parser errors: " + tidy.getParseErrors()
+ " (allowed " + getErrorThreshold() + ") " + "Tidy Parser warnings: "
+ tidy.getParseWarnings() + " (allowed " + getWarningThreshold() + ")", new Object[0]));
result.setFailureMessage(MessageFormat.format(
"Tidy Parser errors: {} (allowed {}) Tidy Parser warnings: {} (allowed {})",
tidy.getParseErrors(), getErrorThreshold(), tidy.getParseWarnings(), getWarningThreshold()));
// return with an error
} else if (tidy.getParseErrors() > 0 || tidy.getParseWarnings() > 0) {

View File

@ -203,19 +203,36 @@ public class BoundaryExtractor extends AbstractScopedTestElement implements Post
}
private String getInputString(SampleResult result) {
String inputString = useUrl() ? result.getUrlAsString() // Bug 39707
: useHeaders() ? result.getResponseHeaders()
: useRequestHeaders() ? result.getRequestHeaders()
: useCode() ? result.getResponseCode() // Bug 43451
: useMessage() ? result.getResponseMessage() // Bug 43451
: useUnescapedBody() ? StringEscapeUtils.unescapeHtml4(result.getResponseDataAsString())
: useBodyAsDocument() ? Document.getTextFromDocument(result.getResponseData())
: result.getResponseDataAsString() // Bug 36898
;
String inputString = chosenInput(result);
log.debug("Input = '{}'", inputString);
return inputString;
}
private String chosenInput(SampleResult result) {
if (useUrl()) {
return result.getUrlAsString(); // Bug 39707;
}
if (useHeaders()) {
return result.getResponseHeaders();
}
if (useRequestHeaders()) {
return result.getRequestHeaders();
}
if (useCode()) {
return result.getResponseCode(); // Bug 43451
}
if (useMessage()) {
return result.getResponseMessage(); // Bug 43451
}
if (useUnescapedBody()) {
return StringEscapeUtils.unescapeHtml4(result.getResponseDataAsString());
}
if (useBodyAsDocument()) {
return Document.getTextFromDocument(result.getResponseData());
}
return result.getResponseDataAsString(); // Bug 36898
}
private List<String> extract(
String leftBoundary, String rightBoundary, int matchNumber, Stream<String> previousResults) {
boolean allItems = matchNumber <= 0;

View File

@ -53,13 +53,7 @@ public class JSONManager {
private final Map<String, JsonPath> expressionToJsonPath = new HashMap<>(2);
private JsonPath getJsonPath(String jsonPathExpression) {
JsonPath jsonPath = expressionToJsonPath.get(jsonPathExpression);
if (jsonPath == null) {
jsonPath = JsonPath.compile(jsonPathExpression);
expressionToJsonPath.put(jsonPathExpression, jsonPath);
}
return jsonPath;
return expressionToJsonPath.computeIfAbsent(jsonPathExpression, JsonPath::compile);
}
public void reset() {

View File

@ -22,7 +22,7 @@ plugins {
dependencies {
api(project(":src:launcher"))
api(project(":src:jorphan"))
testCompile(project(":src:jorphan", "testClasses"))
testImplementation(project(":src:jorphan", "testClasses"))
api("bsf:bsf") {
because("protected BSFManager BSFTestElement#getManager()")

View File

@ -385,18 +385,26 @@ public class JMeter implements JMeterPlugin {
SplashScreen splash = new SplashScreen();
splash.showScreen();
splash.setProgress(10);
log.debug("Apply HiDPI on fonts");
JMeterUtils.applyHiDPIOnFonts();
splash.setProgress(20);
log.debug("Configure PluginManager");
PluginManager.install(this, true);
JMeterTreeModel treeModel = new JMeterTreeModel();
splash.setProgress(30);
log.debug("Setup tree");
JMeterTreeModel treeModel = new JMeterTreeModel();
JMeterTreeListener treeLis = new JMeterTreeListener(treeModel);
final ActionRouter instance = ActionRouter.getInstance();
splash.setProgress(40);
log.debug("populate command map");
instance.populateCommandMap();
splash.setProgress(60);
treeLis.setActionHandler(instance);
log.debug("init instance");
splash.setProgress(70);
GuiPackage.initInstance(treeLis, treeModel);
splash.setProgress(80);
log.debug("constructing main frame");
MainFrame main = new MainFrame(treeModel, treeLis);
splash.setProgress(100);
ComponentUtil.centerComponentInWindow(main, 80);

View File

@ -24,9 +24,9 @@ import java.net.URL;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.JWindow;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
@ -40,7 +40,7 @@ import com.github.weisj.darklaf.icons.ThemedSVGIcon;
* Splash Screen
* @since 3.2
*/
public class SplashScreen extends JWindow {
public class SplashScreen extends JDialog {
private static final Logger log = LoggerFactory.getLogger(SplashScreen.class);
private static final long serialVersionUID = 1L;
@ -53,6 +53,9 @@ public class SplashScreen extends JWindow {
setLayout(new BorderLayout());
add(loadLogo(), BorderLayout.CENTER);
add(progressBar, BorderLayout.SOUTH);
setModalityType(ModalityType.APPLICATION_MODAL);
setAutoRequestFocus(true);
setUndecorated(true);
pack();
setLocationRelativeTo(null);
}
@ -89,10 +92,7 @@ public class SplashScreen extends JWindow {
* Show screen
*/
public void showScreen() {
SwingUtilities.invokeLater(() -> {
setVisible(true);
setAlwaysOnTop(true);
});
SwingUtilities.invokeLater(() -> setVisible(true));
}
/**

View File

@ -89,13 +89,13 @@ public class HtmlReportGenerator {
}
} catch (TimeoutException e) {
errorMessageList.add(MessageFormat.format(JMeterUtils.getResString("generate_report_ui.html_report_timeout_error"),
COMMAND_TIMEOUT, e.getMessage(), commandExecutionOutput.toString()));
LOGGER.error("Report generation took more time than configured timeout(Property {}={})",
"generate_report_ui.generation_timeout", COMMAND_TIMEOUT, commandExecutionOutput.toString(), e);
COMMAND_TIMEOUT, e.getMessage(), commandExecutionOutput));
LOGGER.error("Report generation took more time than configured timeout (Property {}={}, command output=[{}])",
"generate_report_ui.generation_timeout", COMMAND_TIMEOUT, commandExecutionOutput, e);
} catch (InterruptedException | IOException e) {
errorMessageList.add(MessageFormat.format(JMeterUtils.getResString("generate_report_ui.html_report_unknown_error"),
e.getMessage(), commandExecutionOutput.toString()));
LOGGER.error("Error during HTML report generation, executing {}", commandExecutionOutput.toString(), e);
e.getMessage(), commandExecutionOutput));
LOGGER.error("Error during HTML report generation, executing {}", commandExecutionOutput, e);
if (e instanceof InterruptedException) {
Thread.currentThread().interrupt();
}

View File

@ -18,7 +18,6 @@
package org.apache.jmeter.gui.action;
import java.awt.event.ActionEvent;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@ -41,12 +40,6 @@ import org.slf4j.LoggerFactory;
import com.github.weisj.darklaf.LafManager;
import com.github.weisj.darklaf.theme.DarculaTheme;
import com.github.weisj.darklaf.theme.HighContrastDarkTheme;
import com.github.weisj.darklaf.theme.HighContrastLightTheme;
import com.github.weisj.darklaf.theme.IntelliJTheme;
import com.github.weisj.darklaf.theme.OneDarkTheme;
import com.github.weisj.darklaf.theme.SolarizedDarkTheme;
import com.github.weisj.darklaf.theme.SolarizedLightTheme;
import com.github.weisj.darklaf.theme.Theme;
/**
@ -70,9 +63,9 @@ public class LookAndFeelCommand extends AbstractAction {
final String title;
final String command;
final String lafClassName;
final Class<? extends Theme> lafTheme;
final Theme lafTheme;
private MenuItem(String title, String command, String lafClassName, Class<? extends Theme> lafTheme) {
private MenuItem(String title, String command, String lafClassName, Theme lafTheme) {
this.title = title;
this.command = command;
this.lafClassName = lafClassName;
@ -88,39 +81,41 @@ public class LookAndFeelCommand extends AbstractAction {
}
private static MenuItem of(String title, String lafClass) {
return new MenuItem(title,ActionNames.LAF_PREFIX + lafClass, lafClass, null);
return new MenuItem(title, ActionNames.LAF_PREFIX + lafClass, lafClass, null);
}
private static MenuItem ofDarklafTheme(Class<? extends Theme> lafTheme) {
return new MenuItem("Darklaf - " + lafTheme.getSimpleName().replace("Theme", ""),
JMeterMenuBar.DARKLAF_LAF_CLASS + ":" + lafTheme.getName(),
private static MenuItem ofDarklafTheme(Theme theme) {
return new MenuItem("Darklaf - " + theme.getName(),
JMeterMenuBar.DARKLAF_LAF_CLASS + ":" + theme.getThemeClass().getName(),
JMeterMenuBar.DARKLAF_LAF_CLASS,
lafTheme);
theme);
}
}
static {
if (System.getProperty("darklaf.decorations") == null) {
System.setProperty("darklaf.decorations", "false");
} else if (Boolean.getBoolean("darklaf.allowNativeCode")) {
// darklaf.allowNativeCode=true is required for darklaf.decorations=true to work.
System.setProperty("darklaf.decorations", "true");
}
if (System.getProperty("darklaf.allowNativeCode") == null) {
System.setProperty("darklaf.allowNativeCode", "false");
}
UIManager.installLookAndFeel(JMeterMenuBar.DARKLAF_LAF, JMeterMenuBar.DARKLAF_LAF_CLASS);
if (System.getProperty("darklaf.unifiedMenuBar") == null) {
System.setProperty("darklaf.unifiedMenuBar", "true");
}
UIManager.installLookAndFeel(JMeterMenuBar.DARCULA_LAF, JMeterMenuBar.DARCULA_LAF_CLASS);
List<MenuItem> items = new ArrayList<>();
for (UIManager.LookAndFeelInfo laf : JMeterMenuBar.getAllLAFs()) {
if (!laf.getClassName().equals(JMeterMenuBar.DARKLAF_LAF_CLASS)) {
if (!laf.getClassName().equals(JMeterMenuBar.DARCULA_LAF_CLASS)) {
items.add(MenuItem.of(laf.getName(), laf.getClassName()));
continue;
} else {
for (Theme theme : LafManager.getRegisteredThemes()) {
items.add(MenuItem.ofDarklafTheme(theme));
}
}
items.add(MenuItem.ofDarklafTheme(DarculaTheme.class));
items.add(MenuItem.ofDarklafTheme(IntelliJTheme.class));
items.add(MenuItem.ofDarklafTheme(OneDarkTheme.class));
items.add(MenuItem.ofDarklafTheme(SolarizedDarkTheme.class));
items.add(MenuItem.ofDarklafTheme(SolarizedLightTheme.class));
items.add(MenuItem.ofDarklafTheme(HighContrastDarkTheme.class));
items.add(MenuItem.ofDarklafTheme(HighContrastLightTheme.class));
}
items.sort(Comparator.comparing(MenuItem::getTitle));
for (MenuItem item : items) {
@ -184,7 +179,7 @@ public class LookAndFeelCommand extends AbstractAction {
String jMeterLaf = getJMeterLaf();
if (jMeterLaf.equals(JMeterMenuBar.DARCULA_LAF_CLASS)) {
// Convert old Darcula to new Darklaf-Darcula LaF
return MenuItem.ofDarklafTheme(DarculaTheme.class).command;
return MenuItem.ofDarklafTheme(new DarculaTheme()).command;
}
return MenuItem.of("default", jMeterLaf).command; // $NON-NLS-1$
@ -208,12 +203,7 @@ public class LookAndFeelCommand extends AbstractAction {
public static boolean isDark() {
String lookAndFeelID = UIManager.getLookAndFeel().getID();
if (lookAndFeelID.equals("Darklaf")) { // $NON-NLS-1$
Theme lafTheme = LafManager.getTheme();
if (lafTheme == null) {
return false;
}
String name = lafTheme.getName();
return name.equals("darcula") || name.equals("solarized_dark"); // $NON-NLS-1$
return Theme.isDark(LafManager.getTheme());
}
return false;
}
@ -221,24 +211,15 @@ public class LookAndFeelCommand extends AbstractAction {
public static void activateLookAndFeel(String command) {
MenuItem item = items.get(command);
String className = item.lafClassName;
try {
if (item.lafTheme != null) {
LafManager.setTheme(item.lafTheme.getConstructor().newInstance());
}
GuiPackage instance = GuiPackage.getInstance();
if (instance != null) {
instance.updateUIForHiddenComponents();
}
JFactory.refreshUI(className);
PREFS.put(USER_PREFS_KEY, item.command);
} catch ( InstantiationException
| NoSuchMethodException
| IllegalAccessException e) {
throw new IllegalArgumentException("Look and Feel unavailable:" + e.toString(), e);
} catch (InvocationTargetException e) {
Throwable c = e.getCause();
throw new IllegalArgumentException("Look and Feel unavailable:" + c.toString(), c);
if (item.lafTheme != null) {
LafManager.setTheme(item.lafTheme);
}
GuiPackage instance = GuiPackage.getInstance();
if (instance != null) {
instance.updateUIForHiddenComponents();
}
JFactory.refreshUI(className);
PREFS.put(USER_PREFS_KEY, item.command);
}
@Override

View File

@ -41,6 +41,7 @@ import org.apache.jmeter.processor.gui.AbstractPreProcessorGui;
import org.apache.jmeter.samplers.Sampler;
import org.apache.jmeter.samplers.gui.AbstractSamplerGui;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.threads.ThreadGroup;
import org.apache.jmeter.threads.gui.AbstractThreadGroupGui;
import org.apache.jmeter.timers.Timer;
import org.apache.jmeter.timers.gui.AbstractTimerGui;
@ -100,7 +101,7 @@ public class StaticJMeterGUIComponent implements JMeterGUIComponent {
group = MenuFactory.SAMPLERS;
} else if (Timer.class.isAssignableFrom(c) || AbstractTimerGui.class.isAssignableFrom(c)) {
group = MenuFactory.TIMERS;
} else if (AbstractThreadGroupGui.class.isAssignableFrom(c) || AbstractThreadGroupGui.class.isAssignableFrom(c)) {
} else if (ThreadGroup.class.isAssignableFrom(c) || AbstractThreadGroupGui.class.isAssignableFrom(c)) {
group = MenuFactory.THREADS;
} else {
throw new IllegalArgumentException("Unknown group for class " + c);

View File

@ -20,13 +20,14 @@ package org.apache.jmeter.report.dashboard;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.text.StringEscapeUtils;
import org.apache.jmeter.report.core.JsonUtil;
import org.apache.jmeter.report.processor.ListResultData;
import org.apache.jmeter.report.processor.MapResultData;
import org.apache.jmeter.report.processor.ResultData;
import org.apache.jmeter.report.processor.ResultDataVisitor;
import org.apache.jmeter.report.processor.ValueResultData;
import com.fasterxml.jackson.core.io.JsonStringEncoder;
/**
* The class JsonizerVisitor provides a visitor that can get json-like string
* from ResultData.
@ -96,7 +97,7 @@ public class JsonizerVisitor implements ResultDataVisitor<String> {
Object value = valueResult.getValue();
result = String.valueOf(value);
if (value instanceof String) {
result = '"' + StringEscapeUtils.escapeEcmaScript(result.replace('\"', '\'')) + '"';
result = '"' + new String(JsonStringEncoder.getInstance().quoteAsString(result)) + '"';
}
}
return result;

View File

@ -24,6 +24,8 @@ import org.apache.jmeter.report.utils.MetricUtils;
import org.apache.jmeter.samplers.SampleSaveConfiguration;
import org.apache.jmeter.util.JMeterUtils;
import com.fasterxml.jackson.core.io.JsonStringEncoder;
/**
* <p>
* The class ErrorSummaryConsumer provides a consumer that calculates error
@ -89,7 +91,7 @@ public class ErrorsSummaryConsumer extends AbstractSummaryConsumer<Long> {
String responseCode = sample.getResponseCode();
String responseMessage = sample.getResponseMessage();
String key = responseCode + (!StringUtils.isEmpty(responseMessage) ?
"/" + StringEscapeUtils.escapeJson(StringEscapeUtils.escapeHtml4(responseMessage)) : "");
"/" + escapeJson(responseMessage) : "");
if (MetricUtils.isSuccessCode(responseCode) ||
(StringUtils.isEmpty(responseCode) &&
!StringUtils.isEmpty(sample.getFailureMessage()))) {
@ -97,12 +99,17 @@ public class ErrorsSummaryConsumer extends AbstractSummaryConsumer<Long> {
if (ASSERTION_RESULTS_FAILURE_MESSAGE) {
String msg = sample.getFailureMessage();
if (!StringUtils.isEmpty(msg)) {
key = StringEscapeUtils.escapeJson(StringEscapeUtils.escapeHtml4(msg));
key = escapeJson(msg);
}
}
}
return key;
}
private static String escapeJson(String responseMessage) {
return new String(JsonStringEncoder.getInstance().quoteAsString(StringEscapeUtils.escapeHtml4(responseMessage)));
}
/*
* (non-Javadoc)
*

View File

@ -188,7 +188,7 @@ public class JsseSSLManager extends SSLManager {
public void resetContext() {
if (!SHARED_SESSION_CONTEXT) {
log.debug("Clearing session context for current thread");
this.threadlocal.set(null);
this.threadlocal.remove();
}
}

View File

@ -1016,8 +1016,14 @@ run_threadgroup_no_timers=Start no pauses
running_test=Running test
runtime_controller_title=Runtime Controller
runtime_seconds=Runtime (seconds)
sample_creator_counter_value=Counter start value
sample_creator_set_counter=Set counter
sample_name_formatter=Use format string
sample_name_prefix=Prefix
sample_name_suffix=Suffix
sample_naming_scheme=Naming scheme
sample_name_transaction=Transaction name
sample_naming_format_help=<html>Format for the names of the samplers.<br> The counter, path and transaction names can be given with the placeholders <tt>#{counter}</tt>, <tt>#{path}</tt> and <tt>#{name}</tt>.</html>
salt_string=Salt to be used for hashing (optional)
sample_result_save_configuration=Sample Result Save Configuration
sample_scope=Apply to:
@ -1459,6 +1465,7 @@ web_testing_basic=Basic
web_testing_advanced=Advanced
web_testing_concurrent_download=Parallel downloads. Number:
web_testing_embedded_url_pattern=URLs must match\:
web_testing_embedded_url_exclude_pattern=URLs must not match\:
web_testing_retrieve_images=Retrieve All Embedded Resources
web_testing_retrieve_title=Embedded Resources from HTML Files
web_testing_source_ip=Source address

View File

@ -1006,8 +1006,14 @@ running_test=Lancer test
runtime_controller_title=Contrôleur Durée d'exécution
runtime_seconds=Temps d'exécution (secondes) \:
salt_string=Sel à utiliser pour le hash
sample_creator_counter_value=Valeur de départ du compteur
sample_creator_set_counter=Définir le compteur
sample_name_formatter=Utiliser le format
sample_name_prefix=Préfixe
sample_name_suffix=Suffixe
sample_naming_scheme=Schéma de dénomination
sample_name_transaction=Nom de la transaction
sample_naming_format_help=<html>Format des noms des échantillonneurs.<br>Les noms de compteur, chemin et transaction peuvent être donnés avec <tt>#{counter}</tt>, <tt>#{path}</tt> et <tt>#{name}</tt>.</html>
sample_result_save_configuration=Sauvegarder la configuration de la sauvegarde des échantillons
sample_scope=Appliquer sur
sample_scope_all=L'échantillon et ses ressources liées
@ -1448,6 +1454,7 @@ web_testing_advanced=Avancée
web_testing_basic=Basique
web_testing_concurrent_download=Téléchargements en parallèle. Nombre \:
web_testing_embedded_url_pattern=Les URL à inclure doivent correspondre à \:
web_testing_embedded_url_exclude_pattern=Les URL à exclure doivent correspondre à \:
web_testing_retrieve_images=Récupérer les ressources incluses
web_testing_retrieve_title=Ressources incluses dans les pages HTML
web_testing_source_ip=Adresse source

View File

@ -40,12 +40,12 @@ public class ErrorsSummaryConsumerTest {
sample = new Sample(0, metadata, new String[] { "false", "200", "",
"Test failed: text expected to contain /<title>Some html text</title>/" });
assertEquals("Test failed: text expected to contain \\/&lt;title&gt;Some html text&lt;\\/title&gt;\\/",
assertEquals("Test failed: text expected to contain /&lt;title&gt;Some html text&lt;/title&gt;/",
ErrorsSummaryConsumer.getErrorKey(sample));
sample = new Sample(0, metadata, new String[] { "false", "200", "",
"Test failed: text expected to contain /{\"glossary\": { \"title\": \"example glossary\"}}/" });
assertEquals("Test failed: text expected to contain \\/{&quot;glossary&quot;: { &quot;title&quot;: &quot;example glossary&quot;}}\\/",
assertEquals("Test failed: text expected to contain /{&quot;glossary&quot;: { &quot;title&quot;: &quot;example glossary&quot;}}/",
ErrorsSummaryConsumer.getErrorKey(sample));
sample = new Sample(0, metadata, new String[] { "true", "200", "", "" });

View File

@ -30,7 +30,7 @@ val loggingClasspath by configurations.creating
dependencies {
api(project(":src:dist"))
testCompile(project(":src:dist", "testClasses"))
testImplementation(project(":src:dist", "allTestClasses"))
testImplementation("org.apache.commons:commons-lang3") {
because("StringUtils")
}

View File

@ -64,12 +64,17 @@ val srcLicense by configurations.creating {
isCanBeConsumed = false
}
val allTestClasses by configurations.creating {
isCanBeConsumed = true
isCanBeResolved = false
}
// Note: you can inspect final classpath (list of jars in the binary distribution) via
// gw dependencies --configuration runtimeClasspath
dependencies {
for (p in jars) {
api(project(p))
testCompile(project(p, "testClasses"))
allTestClasses(project(p, "testClasses"))
}
binLicense(project(":src:licenses", "binLicense"))

View File

@ -17,7 +17,7 @@
dependencies {
api(project(":src:components"))
testCompile(project(":src:components", "testClasses"))
testImplementation(project(":src:core", "testClasses"))
implementation("org.mozilla:rhino")
implementation("commons-codec:commons-codec")

View File

@ -79,12 +79,15 @@ public final class NewDriver {
tmpDir = null;
}
} else {// e.g. started from IDE with full classpath
tmpDir = System.getProperty("jmeter.home","");// Allow override $NON-NLS-1$ $NON-NLS-2$
if (tmpDir.length() == 0) {
tmpDir = System.getProperty("jmeter.home", System.getenv("JMETER_HOME"));// Allow override $NON-NLS-1$ $NON-NLS-2$
if (tmpDir == null || tmpDir.length() == 0) {
File userDir = new File(System.getProperty("user.dir"));// $NON-NLS-1$
tmpDir = userDir.getAbsoluteFile().getParent();
}
}
if (tmpDir == null) {
tmpDir = System.getenv("JMETER_HOME");
}
JMETER_INSTALLATION_DIRECTORY=tmpDir;
/*

View File

@ -18,7 +18,7 @@
subprojects {
dependencies {
api(project(":src:core"))
testCompile(project(":src:core", "testClasses"))
testImplementation(project(":src:core", "testClasses"))
}
}
@ -47,7 +47,7 @@ project("http") {
dependencies {
// for SearchTextExtension
api(project(":src:components"))
testCompile(project(":src:components", "testClasses"))
testImplementation(project(":src:components", "testClasses"))
api("com.thoughtworks.xstream:xstream") {
because("HTTPResultConverter uses XStream in public API")
@ -84,6 +84,7 @@ project("http") {
implementation("org.apache.httpcomponents:httpmime")
implementation("org.apache.httpcomponents:httpcore")
implementation("org.brotli:dec")
implementation("com.miglayout:miglayout-swing")
testImplementation(testFixtures(project(":src:testkit-wiremock")))
testImplementation("com.github.tomakehurst:wiremock-jre8")
}
@ -114,7 +115,7 @@ project("jdbc") {
project("jms") {
dependencies {
testCompile(project(":src:core", "testClasses"))
testImplementation(project(":src:core", "testClasses"))
api("com.github.ben-manes.caffeine:caffeine") {
because("MessageRenderer#getValueFromFile(..., caffeine.cache.Cache)")
}

View File

@ -46,7 +46,8 @@ import org.apache.jmeter.testelement.property.IntegerProperty;
import org.apache.jmeter.testelement.property.StringProperty;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.gui.JFactory;
import org.apache.jorphan.gui.JLabeledTextField;
import net.miginfocom.swing.MigLayout;
/**
* GUI for Http Request defaults
@ -55,14 +56,15 @@ import org.apache.jorphan.gui.JLabeledTextField;
@TestElementMetadata(labelResource = "url_config_title")
public class HttpDefaultsGui extends AbstractConfigGui {
private static final long serialVersionUID = 241L;
private static final long serialVersionUID = 242L;
private UrlConfigGui urlConfigGui;
private JCheckBox retrieveEmbeddedResources;
private JCheckBox concurrentDwn;
private JTextField concurrentPool;
private JCheckBox useMD5;
private JLabeledTextField embeddedRE; // regular expression used to match against embedded resource URLs
private JTextField embeddedAllowRE; // regular expression used to match against embedded resource URLs to allow
private JTextField embeddedExcludeRE; // regular expression used to match against embedded resource URLs to discard
private JTextField sourceIpAddr; // does not apply to Java implementation
private JComboBox<String> sourceIpType = new JComboBox<>(HTTPSamplerBase.getSourceTypeList());
private JTextField proxyScheme;
@ -131,12 +133,18 @@ public class HttpDefaultsGui extends AbstractConfigGui {
} else {
config.removeProperty(HTTPSamplerBase.MD5);
}
if (!StringUtils.isEmpty(embeddedRE.getText())) {
if (!StringUtils.isEmpty(embeddedAllowRE.getText())) {
config.setProperty(new StringProperty(HTTPSamplerBase.EMBEDDED_URL_RE,
embeddedRE.getText()));
embeddedAllowRE.getText()));
} else {
config.removeProperty(HTTPSamplerBase.EMBEDDED_URL_RE);
}
if (!StringUtils.isEmpty(embeddedExcludeRE.getText())) {
config.setProperty(new StringProperty(HTTPSamplerBase.EMBEDDED_URL_EXCLUDE_RE,
embeddedExcludeRE.getText()));
} else {
config.removeProperty(HTTPSamplerBase.EMBEDDED_URL_EXCLUDE_RE);
}
if(!StringUtils.isEmpty(sourceIpAddr.getText())) {
config.setProperty(new StringProperty(HTTPSamplerBase.IP_SOURCE,
@ -170,7 +178,8 @@ public class HttpDefaultsGui extends AbstractConfigGui {
enableConcurrentDwn(false);
useMD5.setSelected(false);
urlConfigGui.clear();
embeddedRE.setText(""); // $NON-NLS-1$
embeddedAllowRE.setText(""); // $NON-NLS-1$
embeddedExcludeRE.setText(""); // $NON-NLS-1$
sourceIpAddr.setText(""); // $NON-NLS-1$
sourceIpType.setSelectedIndex(HTTPSamplerBase.SourceType.HOSTNAME.ordinal()); //default: IP/Hostname
proxyScheme.setText(""); // $NON-NLS-1$
@ -192,7 +201,8 @@ public class HttpDefaultsGui extends AbstractConfigGui {
concurrentDwn.setSelected(samplerBase.getPropertyAsBoolean(HTTPSamplerBase.CONCURRENT_DWN));
concurrentPool.setText(samplerBase.getPropertyAsString(HTTPSamplerBase.CONCURRENT_POOL));
useMD5.setSelected(samplerBase.getPropertyAsBoolean(HTTPSamplerBase.MD5, false));
embeddedRE.setText(samplerBase.getPropertyAsString(HTTPSamplerBase.EMBEDDED_URL_RE, ""));//$NON-NLS-1$
embeddedAllowRE.setText(samplerBase.getPropertyAsString(HTTPSamplerBase.EMBEDDED_URL_RE, ""));//$NON-NLS-1$
embeddedExcludeRE.setText(samplerBase.getPropertyAsString(HTTPSamplerBase.EMBEDDED_URL_EXCLUDE_RE, ""));//$NON-NLS-1$
sourceIpAddr.setText(samplerBase.getPropertyAsString(HTTPSamplerBase.IP_SOURCE)); //$NON-NLS-1$
sourceIpType.setSelectedIndex(
samplerBase.getPropertyAsInt(HTTPSamplerBase.IP_SOURCE_TYPE,
@ -294,22 +304,33 @@ public class HttpDefaultsGui extends AbstractConfigGui {
});
concurrentPool = new JTextField(2); // 2 columns size
concurrentPool.setMinimumSize(new Dimension(10, (int) concurrentPool.getPreferredSize().getHeight()));
concurrentPool.setMaximumSize(new Dimension(30, (int) concurrentPool.getPreferredSize().getHeight()));
concurrentPool.setMaximumSize(new Dimension(60, (int) concurrentPool.getPreferredSize().getHeight()));
final JPanel embeddedRsrcPanel = new HorizontalPanel();
final JPanel embeddedRsrcPanel = new JPanel(new MigLayout());
embeddedRsrcPanel.setBorder(BorderFactory.createTitledBorder(
JMeterUtils.getResString("web_testing_retrieve_title"))); // $NON-NLS-1$
embeddedRsrcPanel.add(retrieveEmbeddedResources);
embeddedRsrcPanel.add(concurrentDwn);
embeddedRsrcPanel.add(concurrentPool);
embeddedRsrcPanel.add(concurrentPool, "wrap");
// Embedded URL match regex
embeddedRE = new JLabeledTextField(JMeterUtils.getResString("web_testing_embedded_url_pattern"),20); // $NON-NLS-1$
embeddedRsrcPanel.add(embeddedRE);
// Embedded URL match regex to allow
embeddedAllowRE = addTextFieldWithLabel(embeddedRsrcPanel, JMeterUtils.getResString("web_testing_embedded_url_pattern")); // $NON-NLS-1$
// Embedded URL match regex to exclude
embeddedExcludeRE = addTextFieldWithLabel(embeddedRsrcPanel, JMeterUtils.getResString("web_testing_embedded_url_exclude_pattern")); // $NON-NLS-1$
return embeddedRsrcPanel;
}
private JTextField addTextFieldWithLabel(JPanel panel, String labelText) {
JLabel label = new JLabel(labelText); // $NON-NLS-1$
JTextField field = new JTextField(100);
label.setLabelFor(field);
panel.add(label);
panel.add(field, "span");
return field;
}
protected JPanel createSourceAddrPanel() {
final JPanel sourceAddrPanel = new HorizontalPanel();
sourceAddrPanel.setBorder(BorderFactory.createTitledBorder(
@ -343,17 +364,10 @@ public class HttpDefaultsGui extends AbstractConfigGui {
}
private void enableConcurrentDwn(final boolean enable) {
if (enable) {
concurrentDwn.setEnabled(true);
embeddedRE.setEnabled(true);
if (concurrentDwn.isSelected()) {
concurrentPool.setEnabled(true);
}
} else {
concurrentDwn.setEnabled(false);
concurrentPool.setEnabled(false);
embeddedRE.setEnabled(false);
}
concurrentDwn.setEnabled(enable);
embeddedAllowRE.setEnabled(enable);
embeddedExcludeRE.setEnabled(enable);
concurrentPool.setEnabled(concurrentDwn.isSelected() && enable);
}
/**

View File

@ -43,7 +43,8 @@ import org.apache.jmeter.samplers.gui.AbstractSamplerGui;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.gui.JFactory;
import org.apache.jorphan.gui.JLabeledTextField;
import net.miginfocom.swing.MigLayout;
/**
* HTTP Sampler GUI
@ -52,14 +53,15 @@ import org.apache.jorphan.gui.JLabeledTextField;
@TestElementMetadata(labelResource = "web_testing_title")
public class HttpTestSampleGui extends AbstractSamplerGui {
private static final long serialVersionUID = 241L;
private static final long serialVersionUID = 242L;
private UrlConfigGui urlConfigGui;
private JCheckBox retrieveEmbeddedResources;
private JCheckBox concurrentDwn;
private JTextField concurrentPool;
private JCheckBox useMD5;
private JLabeledTextField embeddedRE; // regular expression used to match against embedded resource URLs
private JTextField embeddedAllowRE; // regular expression used to match against embedded resource URLs to allow
private JTextField embeddedExcludeRE; // regular expression used to match against embedded resource URLs to exclude
private JTextField sourceIpAddr; // does not apply to Java implementation
private JComboBox<String> sourceIpType = new JComboBox<>(HTTPSamplerBase.getSourceTypeList());
private JTextField proxyScheme;
@ -96,7 +98,8 @@ public class HttpTestSampleGui extends AbstractSamplerGui {
concurrentDwn.setSelected(samplerBase.isConcurrentDwn());
concurrentPool.setText(samplerBase.getConcurrentPool());
useMD5.setSelected(samplerBase.useMD5());
embeddedRE.setText(samplerBase.getEmbeddedUrlRE());
embeddedAllowRE.setText(samplerBase.getEmbeddedUrlRE());
embeddedExcludeRE.setText(samplerBase.getEmbededUrlExcludeRE());
if (!isAJP) {
sourceIpAddr.setText(samplerBase.getIpSource());
sourceIpType.setSelectedIndex(samplerBase.getIpSourceType());
@ -136,7 +139,8 @@ public class HttpTestSampleGui extends AbstractSamplerGui {
samplerBase.setConcurrentDwn(concurrentDwn.isSelected());
samplerBase.setConcurrentPool(concurrentPool.getText());
samplerBase.setMD5(useMD5.isSelected());
samplerBase.setEmbeddedUrlRE(embeddedRE.getText());
samplerBase.setEmbeddedUrlRE(embeddedAllowRE.getText());
samplerBase.setEmbeddedUrlExcludeRE(embeddedExcludeRE.getText());
if (!isAJP) {
samplerBase.setIpSource(sourceIpAddr.getText());
samplerBase.setIpSourceType(sourceIpType.getSelectedIndex());
@ -256,22 +260,33 @@ public class HttpTestSampleGui extends AbstractSamplerGui {
});
concurrentPool = new JTextField(2); // 2 column size
concurrentPool.setMinimumSize(new Dimension(10, (int) concurrentPool.getPreferredSize().getHeight()));
concurrentPool.setMaximumSize(new Dimension(30, (int) concurrentPool.getPreferredSize().getHeight()));
concurrentPool.setMaximumSize(new Dimension(60, (int) concurrentPool.getPreferredSize().getHeight()));
final JPanel embeddedRsrcPanel = new HorizontalPanel();
final JPanel embeddedRsrcPanel = new JPanel(new MigLayout());
embeddedRsrcPanel.setBorder(BorderFactory.createTitledBorder(
JMeterUtils.getResString("web_testing_retrieve_title"))); // $NON-NLS-1$
embeddedRsrcPanel.add(retrieveEmbeddedResources);
embeddedRsrcPanel.add(concurrentDwn);
embeddedRsrcPanel.add(concurrentPool);
embeddedRsrcPanel.add(concurrentPool, "wrap");
// Embedded URL match regex
embeddedRE = new JLabeledTextField(JMeterUtils.getResString("web_testing_embedded_url_pattern"),20); // $NON-NLS-1$
embeddedRsrcPanel.add(embeddedRE);
embeddedAllowRE = addTextFieldWithLabel(embeddedRsrcPanel, JMeterUtils.getResString("web_testing_embedded_url_pattern")); // $NON-NLS-1$
// Embedded URL to not match regex
embeddedExcludeRE = addTextFieldWithLabel(embeddedRsrcPanel, JMeterUtils.getResString("web_testing_embedded_url_exclude_pattern")); // $NON-NLS-1$
return embeddedRsrcPanel;
}
private JTextField addTextFieldWithLabel(JPanel panel, String labelText) {
JLabel label = new JLabel(labelText); // $NON-NLS-1$
JTextField field = new JTextField(100);
label.setLabelFor(field);
panel.add(label);
panel.add(field, "span");
return field;
}
/**
* Create a panel containing the implementation details
*
@ -334,7 +349,7 @@ public class HttpTestSampleGui extends AbstractSamplerGui {
enableConcurrentDwn(false);
useMD5.setSelected(false);
urlConfigGui.clear();
embeddedRE.setText(""); // $NON-NLS-1$
embeddedAllowRE.setText(""); // $NON-NLS-1$
if (!isAJP) {
sourceIpAddr.setText(""); // $NON-NLS-1$
sourceIpType.setSelectedIndex(HTTPSamplerBase.SourceType.HOSTNAME.ordinal()); //default: IP/Hostname
@ -350,17 +365,10 @@ public class HttpTestSampleGui extends AbstractSamplerGui {
}
private void enableConcurrentDwn(boolean enable) {
if (enable) {
concurrentDwn.setEnabled(true);
embeddedRE.setEnabled(true);
if (concurrentDwn.isSelected()) {
concurrentPool.setEnabled(true);
}
} else {
concurrentDwn.setEnabled(false);
concurrentPool.setEnabled(false);
embeddedRE.setEnabled(false);
}
concurrentDwn.setEnabled(enable);
embeddedAllowRE.setEnabled(enable);
embeddedExcludeRE.setEnabled(enable);
concurrentPool.setEnabled(concurrentDwn.isSelected() && enable);
}

View File

@ -73,12 +73,6 @@ public abstract class AbstractSamplerCreator implements SamplerCreator {
}
/**
*
*/
/**
*
*/
public AbstractSamplerCreator() {
super();
}
@ -97,6 +91,11 @@ public abstract class AbstractSamplerCreator implements SamplerCreator {
incrementRequestNumberAndGet();
}
@Override
public void setCounter(int value) {
REQUEST_NUMBER.set(value);
}
/**
* Increment request number
* @return int number for created sampler

View File

@ -22,6 +22,7 @@ import java.io.IOException;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.MessageFormat;
import java.util.Map;
import javax.xml.XMLConstants;
@ -60,6 +61,8 @@ public class DefaultSamplerCreator extends AbstractSamplerCreator {
*/
private static final int SAMPLER_NAME_NAMING_MODE_PREFIX = 0; // $NON-NLS-1$
private static final int SAMPLER_NAME_NAMING_MODE_COMPLETE = 1; // $NON-NLS-1$
private static final int SAMPLER_NAME_NAMING_MODE_SUFFIX = 2; // $NON-NLS-1$
private static final int SAMPLER_NAME_NAMING_MODE_FORMATTER = 3; // $NON_NLS-1$
/**
*
@ -285,35 +288,50 @@ public class DefaultSamplerCreator extends AbstractSamplerCreator {
*/
protected void computeSamplerName(HTTPSamplerBase sampler,
HttpRequestHdr request) {
String prefix = request.getPrefix();
String prefix = StringUtils.defaultString(request.getPrefix(), "");
int httpSampleNameMode = request.getHttpSampleNameMode();
String format = getFormat(httpSampleNameMode, request.getHttpSampleNameFormat());
if (!HTTPConstants.CONNECT.equals(request.getMethod()) && isNumberRequests()) {
if(StringUtils.isNotEmpty(prefix)) {
if (httpSampleNameMode == SAMPLER_NAME_NAMING_MODE_PREFIX) {
sampler.setName(prefix + sampler.getPath()+ "-" + incrementRequestNumberAndGet());
} else if (httpSampleNameMode == SAMPLER_NAME_NAMING_MODE_COMPLETE) {
sampler.setName(prefix + "-" + incrementRequestNumberAndGet());
} else {
log.debug("Sampler name naming mode not recognized");
}
} else {
sampler.setName(sampler.getPath()+"-"+incrementRequestNumberAndGet());
}
sampler.setName(MessageFormat.format(format, prefix, sampler.getPath(), incrementRequestNumberAndGet()));
} else {
if(StringUtils.isNotEmpty(prefix)) {
if (httpSampleNameMode == SAMPLER_NAME_NAMING_MODE_PREFIX) {
sampler.setName(prefix + sampler.getPath());
} else if (httpSampleNameMode == SAMPLER_NAME_NAMING_MODE_COMPLETE) {
sampler.setName(prefix);
} else {
log.debug("Sampler name naming mode not recognized");
}
} else {
sampler.setName(sampler.getPath());
}
sampler.setName(MessageFormat.format(format, prefix, sampler.getPath()));
}
}
private String getFormat(int httpSampleNameMode, String format) {
if (httpSampleNameMode == SAMPLER_NAME_NAMING_MODE_FORMATTER) {
return format.replaceAll("#\\{name([,}])", "{0$1")
.replaceAll("#\\{path([,}])", "{1$1")
.replaceAll("#\\{counter([,}])", "{2$1");
}
if (isNumberRequests()) {
return getNumberedFormat(httpSampleNameMode, format);
}
if (httpSampleNameMode == SAMPLER_NAME_NAMING_MODE_PREFIX) {
return "{0}{1}";
}
if (httpSampleNameMode == SAMPLER_NAME_NAMING_MODE_COMPLETE) {
return "{0}";
}
if (httpSampleNameMode == SAMPLER_NAME_NAMING_MODE_SUFFIX) {
return "{0} {1}";
}
return "{1}";
}
private String getNumberedFormat(int httpSampleNameMode, String format) {
if (httpSampleNameMode == SAMPLER_NAME_NAMING_MODE_PREFIX) {
return "{0}{1}-{2}";
}
if (httpSampleNameMode == SAMPLER_NAME_NAMING_MODE_COMPLETE) {
return "{0}-{2}";
}
if (httpSampleNameMode == SAMPLER_NAME_NAMING_MODE_SUFFIX) {
return "{0}-{2} {1}";
}
return "{1}";
}
/**
* Set path on sampler
* @param sampler {@link HTTPSamplerBase}

View File

@ -84,6 +84,8 @@ public class HttpRequestHdr {
private int httpSampleNameMode;
private String httpSampleNameFormat;
public HttpRequestHdr() {
this("", "");
}
@ -100,19 +102,21 @@ public class HttpRequestHdr {
* @param httpSamplerName the http sampler name
*/
public HttpRequestHdr(String prefix, String httpSamplerName) {
this(prefix, httpSamplerName,0);
this(prefix, httpSamplerName, 0, "{0}{1}");
}
/**
* @param prefix Sampler prefix
* @param httpSamplerName the http sampler name
* @param httpSampleNameMode the naming mode of sampler name
* @param format format to use when mode is 3
*/
public HttpRequestHdr(String prefix, String httpSamplerName, int httpSampleNameMode) {
public HttpRequestHdr(String prefix, String httpSamplerName, int httpSampleNameMode, String format) {
this.prefix = prefix;
this.httpSamplerName = httpSamplerName;
this.firstLine = "" ; // $NON-NLS-1$
this.httpSampleNameMode = httpSampleNameMode;
this.httpSampleNameFormat = format;
}
/**
@ -463,4 +467,8 @@ public class HttpRequestHdr {
public int getHttpSampleNameMode() {
return httpSampleNameMode;
}
public String getHttpSampleNameFormat() {
return httpSampleNameFormat;
}
}

View File

@ -32,6 +32,7 @@ import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -63,6 +64,9 @@ import org.slf4j.LoggerFactory;
* JMeter test plan.
*/
public class Proxy extends Thread {
// Mime-types of resources, that are not HTML and not binary that should be skipped on form parsing in JSoup
private static final List<String> NOT_HTML_TEXT_TYPES = Arrays.asList("application/javascript", "application/json", "text/javascript");
private static final Logger log = LoggerFactory.getLogger(Proxy.class);
private static final byte[] CRLF_BYTES = { 0x0d, 0x0a };
@ -157,7 +161,8 @@ public class Proxy extends Thread {
// Check which HTTPSampler class we should use
String httpSamplerName = target.getSamplerTypeName();
HttpRequestHdr request = new HttpRequestHdr(target.getPrefixHTTPSampleName(), httpSamplerName,target.getHTTPSampleNamingMode());
HttpRequestHdr request = new HttpRequestHdr(target.getPrefixHTTPSampleName(), httpSamplerName,
target.getHTTPSampleNamingMode(), target.getHttpSampleNameFormat());
SampleResult result = null;
HeaderManager headers = null;
HTTPSamplerBase sampler = null;
@ -300,6 +305,15 @@ public class Proxy extends Thread {
}
}
/**
* Set the counter for all registered {@link SamplerCreatorFactory}s
*
* @param value to be initialized
*/
public static void setCounter(int value) {
SAMPLERFACTORY.setCounter(value);
}
/**
* Get SSL connection from hashmap, creating it if necessary.
*
@ -595,10 +609,16 @@ public class Proxy extends Thread {
FormCharSetFinder finder = new FormCharSetFinder();
if (SampleResult.isBinaryType(result.getContentType())) {
if (log.isDebugEnabled()) {
log.debug("Will not guess encoding of url:{} as it's binary", result.getUrlAsString());
log.debug("Will not guess encoding of URL: {} as it's binary", result.getUrlAsString());
}
return; // no point parsing anything else, e.g. GIF ...
}
if (isNotHtmlType(result.getContentType())) {
if (log.isDebugEnabled()) {
log.debug("Will not guess encoding of URL: {} as it's not HTML", result.getUrlAsString());
}
return; // None HTML types have been crashing JSoup parser, so return here early
}
try {
finder.addFormActionsAndCharSet(result.getResponseDataAsString(), formEncodings, pageEncoding);
}
@ -609,6 +629,15 @@ public class Proxy extends Thread {
}
}
private boolean isNotHtmlType(String contentType) {
for (String mimeType: NOT_HTML_TEXT_TYPES) {
if (contentType.startsWith(mimeType)) {
return true;
}
}
return false;
}
private String getUrlWithoutQuery(URL url) {
String fullUrl = url.toString();
String urlWithoutQuery = fullUrl;

View File

@ -288,6 +288,8 @@ public class ProxyControl extends GenericController implements NonTestElement {
private transient javax.swing.Timer sampleWorkerTimer;
private String httpSampleNameFormat;
public ProxyControl() {
setPort(DEFAULT_PORT);
setExcludeList(new HashSet<>());
@ -1658,8 +1660,7 @@ public class ProxyControl extends GenericController implements NonTestElement {
private int groupingMode;
private long recordedAt;
public SamplerInfo(HTTPSamplerBase sampler, TestElement[] testElements, JMeterTreeNode target, String prefix,
int groupingMode) {
public SamplerInfo(HTTPSamplerBase sampler, TestElement[] testElements, JMeterTreeNode target, String prefix, int groupingMode) {
this.sampler = sampler;
this.testElements = testElements;
this.target = target;
@ -1668,4 +1669,12 @@ public class ProxyControl extends GenericController implements NonTestElement {
this.recordedAt = System.currentTimeMillis();
}
}
public void setHttpSampleNameFormat(String text) {
this.httpSampleNameFormat = text;
}
public String getHttpSampleNameFormat() {
return httpSampleNameFormat;
}
}

View File

@ -93,4 +93,12 @@ public interface SamplerCreator {
* @return List
*/
List<TestElement> createChildren(HTTPSamplerBase sampler, SampleResult result);
/**
* Set the counter for this implementation. The counter should be incremented
* before creating a new sampler by the implementation.
*
* @param value to be used
*/
default void setCounter(int value) {};
}

View File

@ -42,6 +42,19 @@ public class SamplerCreatorFactory {
init();
}
/**
* Set the counter for all available {@link SamplerCreator}s.
* <p>
* <em>The only implementation that is currently available, increments the counter before it is used!</em>
* @param value to initialize the creators
*/
public void setCounter(int value) {
DEFAULT_SAMPLER_CREATOR.setCounter(value);
for (SamplerCreator samplerCreator: samplerCreatorMap.values()) {
samplerCreator.setCounter(value);
}
}
/**
* Initialize factory from classpath
*/

View File

@ -79,6 +79,7 @@ import org.apache.jmeter.gui.util.MenuFactory;
import org.apache.jmeter.gui.util.PowerTableModel;
import org.apache.jmeter.gui.util.VerticalPanel;
import org.apache.jmeter.protocol.http.control.RecordingController;
import org.apache.jmeter.protocol.http.proxy.Proxy;
import org.apache.jmeter.protocol.http.proxy.ProxyControl;
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerFactory;
import org.apache.jmeter.testelement.TestElement;
@ -91,6 +92,8 @@ import org.apache.jorphan.gui.JLabeledTextField;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.miginfocom.swing.MigLayout;
/**
* GUI of HTTP(s) Test Script Recorder
*
@ -229,7 +232,7 @@ public class ProxyControlGui extends LogicControllerGui implements JMeterGUIComp
private transient RecorderDialog recorderDialog;
private Component labelDefaultEncoding;
private JTextField httpSampleNameFormat;
//+ action names
private static final String ACTION_STOP = "stop"; // $NON-NLS-1$
@ -270,6 +273,9 @@ public class ProxyControlGui extends LogicControllerGui implements JMeterGUIComp
// Used by itemListener
private static final String PORT_FIELD_NAME = "portField"; // $NON-NLS-1$
static final String HTTP_SAMPLER_NAME_FORMAT = "proxy_http_sampler_name_format";
public ProxyControlGui() {
super();
log.debug("Creating ProxyControlGui");
@ -416,12 +422,12 @@ public class ProxyControlGui extends LogicControllerGui implements JMeterGUIComp
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getSource() instanceof JComboBox) {
JComboBox combo = (JComboBox) e.getSource();
if(HTTP_SAMPLER_NAMING_MODE.equals(combo.getName())){
JComboBox<?> combo = (JComboBox<?>) e.getSource();
if (HTTP_SAMPLER_NAMING_MODE.equals(combo.getName())) {
model.setHTTPSampleNamingMode(httpSampleNamingMode.getSelectedIndex());
}
httpSampleNameFormat.setEnabled(httpSampleNamingMode.getSelectedIndex() == 3);
}
else {
} else {
enableRestart();
}
}
@ -710,6 +716,8 @@ public class ProxyControlGui extends LogicControllerGui implements JMeterGUIComp
enableRestart();
} else if(fieldName.equals(PREFIX_HTTP_SAMPLER_NAME)) {
model.setPrefixHTTPSampleName(prefixHTTPSampleName.getText());
} else if (fieldName.equals(HTTP_SAMPLER_NAME_FORMAT)) {
model.setHttpSampleNameFormat(httpSampleNameFormat.getText());
} else if(fieldName.equals(PROXY_PAUSE_HTTP_SAMPLER)) {
try {
Long.parseLong(proxyPauseHTTPSample.getText());
@ -868,22 +876,16 @@ public class ProxyControlGui extends LogicControllerGui implements JMeterGUIComp
regexMatch.addActionListener(this);
regexMatch.setActionCommand(ENABLE_RESTART);
VerticalPanel mainPanel = new VerticalPanel();
mainPanel.setBorder(BorderFactory.createTitledBorder(
JPanel contentPanel = new JPanel(new MigLayout("fillx, wrap 3"));
contentPanel.setBorder(BorderFactory.createTitledBorder(
JMeterUtils.getResString("proxy_test_plan_content"))); // $NON-NLS-1$
addTargetToPanel(contentPanel);
addGroupingToPanel(contentPanel);
contentPanel.add(httpHeaders);
contentPanel.add(addAssertions);
contentPanel.add(regexMatch);
HorizontalPanel nodeCreationPanel = new HorizontalPanel();
nodeCreationPanel.add(createGroupingPanel());
nodeCreationPanel.add(httpHeaders);
nodeCreationPanel.add(addAssertions);
nodeCreationPanel.add(regexMatch);
HorizontalPanel targetPanel = new HorizontalPanel();
targetPanel.add(createTargetPanel());
mainPanel.add(targetPanel);
mainPanel.add(nodeCreationPanel);
return mainPanel;
return contentPanel;
}
private JPanel createHTTPSamplerPanel() {
@ -922,6 +924,8 @@ public class ProxyControlGui extends LogicControllerGui implements JMeterGUIComp
DefaultComboBoxModel<String> choice = new DefaultComboBoxModel<>();
choice.addElement(JMeterUtils.getResString("sample_name_prefix")); // $NON-NLS-1$
choice.addElement(JMeterUtils.getResString("sample_name_transaction")); // $NON-NLS-1$
choice.addElement(JMeterUtils.getResString("sample_name_suffix")); // $NON-NLS-1$
choice.addElement(JMeterUtils.getResString("sample_name_formatter")); // $NON-NLS-1$
httpSampleNamingMode = new JComboBox<>(choice);
httpSampleNamingMode.setName(HTTP_SAMPLER_NAMING_MODE);
httpSampleNamingMode.addItemListener(this);
@ -932,6 +936,10 @@ public class ProxyControlGui extends LogicControllerGui implements JMeterGUIComp
prefixHTTPSampleName.addKeyListener(this);
prefixHTTPSampleName.setName(PREFIX_HTTP_SAMPLER_NAME);
httpSampleNameFormat = new JTextField(20);
httpSampleNameFormat.addKeyListener(this);
httpSampleNameFormat.setName(HTTP_SAMPLER_NAME_FORMAT);
proxyPauseHTTPSample = new JTextField(10);
proxyPauseHTTPSample.addKeyListener(this);
proxyPauseHTTPSample.setName(PROXY_PAUSE_HTTP_SAMPLER);
@ -942,71 +950,50 @@ public class ProxyControlGui extends LogicControllerGui implements JMeterGUIComp
JLabel labelDefaultEncoding = new JLabel(JMeterUtils.getResString("proxy_default_encoding")); // $NON-NLS-1$
labelDefaultEncoding.setLabelFor(defaultEncoding);
GridBagLayout gridBagLayout = new GridBagLayout();
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.FIRST_LINE_START;
gbc.fill = GridBagConstraints.NONE;
gbc.gridheight = 1;
gbc.gridwidth = 1;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1;
gbc.weighty = 1;
JPanel panel = new JPanel(gridBagLayout);
JPanel panel = new JPanel(new MigLayout("fillx, wrap 3"));
panel.setBorder(BorderFactory.createTitledBorder(
JMeterUtils.getResString("proxy_sampler_settings"))); // $NON-NLS-1$
panel.add(httpSampleNamingMode, gbc.clone());
gbc.gridx++;
gbc.weightx = 3;
gbc.fill=GridBagConstraints.HORIZONTAL;
panel.add(prefixHTTPSampleName, gbc.clone());
gbc.gridx = 0;
gbc.gridy++;
panel.add(labelProxyPause, gbc.clone());
gbc.gridx++;
gbc.weightx = 3;
gbc.fill = GridBagConstraints.HORIZONTAL;
panel.add(proxyPauseHTTPSample, gbc.clone());
gbc.weightx = 1;
JLabel labelSampleTransactionName = new JLabel(JMeterUtils.getResString("sample_name_transaction"));
labelSampleTransactionName.setLabelFor(prefixHTTPSampleName);
panel.add(labelSampleTransactionName);
panel.add(prefixHTTPSampleName, "growx, span");
gbc.gridx = 0;
gbc.gridy++;
panel.add(labelDefaultEncoding, gbc.clone());
gbc.gridx++;
gbc.weightx = 3;
gbc.fill = GridBagConstraints.HORIZONTAL;
panel.add(defaultEncoding, gbc.clone());
gbc.weightx = 1;
JLabel labelNamingScheme = new JLabel(JMeterUtils.getResString("sample_naming_scheme"));
labelNamingScheme.setLabelFor(httpSampleNamingMode);
panel.add(labelNamingScheme, "split 2");
panel.add(httpSampleNamingMode);
panel.add(httpSampleNameFormat, "growx, span");
httpSampleNameFormat.setToolTipText(JMeterUtils.getResString("sample_naming_format_help"));
gbc.gridx = 0;
gbc.gridy++;
gbc.fill=GridBagConstraints.VERTICAL;
panel.add(samplerDownloadImages, gbc.clone());
gbc.gridx = 0;
gbc.gridy++;
gbc.fill=GridBagConstraints.VERTICAL;
panel.add(samplerRedirectAutomatically, gbc.clone());
gbc.gridx++;
gbc.fill=GridBagConstraints.HORIZONTAL;
panel.add(samplerFollowRedirects, gbc.clone());
gbc.gridx = 0;
gbc.gridy++;
gbc.fill=GridBagConstraints.VERTICAL;
panel.add(useKeepAlive, gbc.clone());
gbc.gridx = 0;
gbc.gridy++;
gbc.fill=GridBagConstraints.VERTICAL;
panel.add(labelSamplerType, gbc.clone());
gbc.gridx++;
gbc.fill=GridBagConstraints.HORIZONTAL;
panel.add(samplerTypeName, gbc.clone());
JLabel labelSetCounter = new JLabel(JMeterUtils.getResString("sample_creator_counter_value"));
JTextField counterValue = new JTextField(10);
labelSetCounter.setLabelFor(counterValue);
JButton buttonSetCounter = new JButton(JMeterUtils.getResString("sample_creator_set_counter"));
buttonSetCounter.addActionListener(e -> Proxy.setCounter(Integer.valueOf(counterValue.getText())));
panel.add(labelSetCounter);
panel.add(counterValue);
panel.add(buttonSetCounter);
panel.add(labelProxyPause);
panel.add(proxyPauseHTTPSample, "growx, span");
panel.add(labelDefaultEncoding);
panel.add(defaultEncoding, "growx, span");
panel.add(samplerDownloadImages);
panel.add(samplerRedirectAutomatically);
panel.add(samplerFollowRedirects);
panel.add(useKeepAlive, "wrap");
panel.add(labelSamplerType);
panel.add(samplerTypeName, "growx, span");
return panel;
}
private JPanel createTargetPanel() {
private void addTargetToPanel(JPanel destPanel) {
targetNodesModel = new DefaultComboBoxModel<>();
targetNodes = new JComboBox<>(targetNodesModel);
targetNodes.setPrototypeDisplayValue(""); // $NON-NLS-1$ // Bug 56303 fixed the width of combo list
// Bug 56303 fixed the width of combo list
JPopupMenu popup = (JPopupMenu) targetNodes.getUI().getAccessibleChild(targetNodes, 0); // get popup element
JScrollPane scrollPane = findScrollPane(popup);
if(scrollPane != null) {
@ -1019,11 +1006,8 @@ public class ProxyControlGui extends LogicControllerGui implements JMeterGUIComp
JLabel label = new JLabel(JMeterUtils.getResString("proxy_target")); // $NON-NLS-1$
label.setLabelFor(targetNodes);
HorizontalPanel panel = new HorizontalPanel();
panel.add(label);
panel.add(targetNodes);
return panel;
destPanel.add(label);
destPanel.add(targetNodes, "growx, span");
}
private JScrollPane findScrollPane(JPopupMenu popup) {
@ -1036,7 +1020,7 @@ public class ProxyControlGui extends LogicControllerGui implements JMeterGUIComp
return null;
}
private JPanel createGroupingPanel() {
private void addGroupingToPanel(JPanel destPanel) {
DefaultComboBoxModel<String> m = new DefaultComboBoxModel<>();
// Note: position of these elements in the menu *must* match the
// corresponding ProxyControl.GROUPING_* values.
@ -1046,18 +1030,14 @@ public class ProxyControlGui extends LogicControllerGui implements JMeterGUIComp
m.addElement(JMeterUtils.getResString("grouping_store_first_only")); // $NON-NLS-1$
m.addElement(JMeterUtils.getResString("grouping_in_transaction_controllers")); // $NON-NLS-1$
groupingMode = new JComboBox<>(m);
groupingMode.setPreferredSize(new Dimension(150, 20));
groupingMode.setSelectedIndex(0);
groupingMode.addItemListener(this);
JLabel label2 = new JLabel(JMeterUtils.getResString("grouping_mode")); // $NON-NLS-1$
label2.setLabelFor(groupingMode);
HorizontalPanel panel = new HorizontalPanel();
panel.add(label2);
panel.add(groupingMode);
return panel;
destPanel.add(label2);
destPanel.add(groupingMode, "growx, span");
}
private JPanel createContentTypePanel() {
@ -1266,4 +1246,9 @@ public class ProxyControlGui extends LogicControllerGui implements JMeterGUIComp
prefixHTTPSampleName.setText(text);
model.setPrefixHTTPSampleName(text);
}
void setSampleNameFormat(String text) {
httpSampleNameFormat.setText(text);
model.setHttpSampleNameFormat(text);
}
}

View File

@ -18,8 +18,6 @@
package org.apache.jmeter.protocol.http.proxy.gui;
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
@ -47,8 +45,11 @@ import javax.swing.JTextField;
import org.apache.jmeter.gui.action.KeyStrokes;
import org.apache.jmeter.gui.util.JMeterToolBar;
import org.apache.jmeter.protocol.http.proxy.Proxy;
import org.apache.jmeter.util.JMeterUtils;
import net.miginfocom.swing.MigLayout;
/**
* Dialog for Recorder
* @since 5.0
@ -66,6 +67,8 @@ public class RecorderDialog extends JDialog implements ItemListener, KeyListener
*/
private JTextField prefixHTTPSampleName;
private JTextField sampleNameFormat;
private JTextField proxyPauseHTTPSample;
/**
@ -120,6 +123,8 @@ public class RecorderDialog extends JDialog implements ItemListener, KeyListener
DefaultComboBoxModel<String> choice = new DefaultComboBoxModel<>();
choice.addElement(JMeterUtils.getResString("sample_name_prefix")); // $NON-NLS-1$
choice.addElement(JMeterUtils.getResString("sample_name_transaction")); // $NON-NLS-1$
choice.addElement(JMeterUtils.getResString("sample_name_suffix")); // $NON-NLS-1$
choice.addElement(JMeterUtils.getResString("sample_name_formatter")); // $NON-NLS-1$
httpSampleNamingMode = new JComboBox<>(choice);
httpSampleNamingMode.setName(ProxyControlGui.HTTP_SAMPLER_NAMING_MODE);
httpSampleNamingMode.addItemListener(this);
@ -136,31 +141,35 @@ public class RecorderDialog extends JDialog implements ItemListener, KeyListener
JLabel labelProxyPause = new JLabel(JMeterUtils.getResString("proxy_pause_http_sampler")); // $NON-NLS-1$
labelProxyPause.setLabelFor(proxyPauseHTTPSample);
GridBagLayout gridBagLayout = new GridBagLayout();
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.FIRST_LINE_START;
gbc.fill = GridBagConstraints.NONE;
gbc.gridheight = 1;
gbc.gridwidth = 1;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1;
gbc.weighty = 1;
JPanel panel = new JPanel(gridBagLayout);
JPanel panel = new JPanel(new MigLayout("fillx, wrap 3"));
panel.setBorder(BorderFactory.createTitledBorder(
JMeterUtils.getResString("proxy_sampler_settings"))); // $NON-NLS-1$
panel.add(httpSampleNamingMode, gbc.clone());
gbc.gridx++;
gbc.weightx = 3;
gbc.fill=GridBagConstraints.HORIZONTAL;
panel.add(prefixHTTPSampleName, gbc.clone());
gbc.gridx = 0;
gbc.gridy++;
panel.add(labelProxyPause, gbc.clone());
gbc.gridx++;
gbc.weightx = 3;
gbc.fill = GridBagConstraints.HORIZONTAL;
panel.add(proxyPauseHTTPSample, gbc.clone());
JLabel labelTransactionName = new JLabel(JMeterUtils.getResString("sample_name_transaction"));
labelTransactionName.setLabelFor(prefixHTTPSampleName);
panel.add(labelTransactionName);
panel.add(prefixHTTPSampleName, "span");
JLabel labelNamingScheme = new JLabel(JMeterUtils.getResString("sample_naming_scheme"));
labelNamingScheme.setLabelFor(httpSampleNamingMode);
panel.add(labelNamingScheme, "split 2");
panel.add(httpSampleNamingMode);
sampleNameFormat = new JTextField(20);
sampleNameFormat.addKeyListener(this);
sampleNameFormat.setName(ProxyControlGui.HTTP_SAMPLER_NAME_FORMAT);
sampleNameFormat.setEnabled(httpSampleNamingMode.getSelectedIndex() == 3);
sampleNameFormat.setToolTipText(JMeterUtils.getResString("sample_naming_format_help"));
panel.add(sampleNameFormat, "span");
JLabel labelSetCounter = new JLabel(JMeterUtils.getResString("sample_creator_counter_value"));
JTextField counterValue = new JTextField(10);
labelSetCounter.setLabelFor(counterValue);
JButton buttonSetCounter = new JButton(JMeterUtils.getResString("sample_creator_set_counter"));
buttonSetCounter.addActionListener(e -> Proxy.setCounter(Integer.valueOf(counterValue.getText())));
panel.add(labelSetCounter);
panel.add(counterValue);
panel.add(buttonSetCounter);
panel.add(labelProxyPause);
panel.add(proxyPauseHTTPSample, "span");
this.getContentPane().add(panel, BorderLayout.CENTER);
@ -194,9 +203,10 @@ public class RecorderDialog extends JDialog implements ItemListener, KeyListener
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getSource() instanceof JComboBox) {
JComboBox combo = (JComboBox) e.getSource();
JComboBox<?> combo = (JComboBox<?>) e.getSource();
if(ProxyControlGui.HTTP_SAMPLER_NAMING_MODE.equals(combo.getName())){
recorderGui.setHTTPSampleNamingMode(httpSampleNamingMode.getSelectedIndex());
sampleNameFormat.setEnabled(httpSampleNamingMode.getSelectedIndex() == 3);
}
}
else {
@ -220,9 +230,11 @@ public class RecorderDialog extends JDialog implements ItemListener, KeyListener
@Override
public void keyReleased(KeyEvent e) {
String fieldName = e.getComponent().getName();
if(fieldName.equals(ProxyControlGui.PREFIX_HTTP_SAMPLER_NAME)) {
if (fieldName.equals(ProxyControlGui.PREFIX_HTTP_SAMPLER_NAME)) {
recorderGui.setPrefixHTTPSampleName(prefixHTTPSampleName.getText());
} else if(fieldName.equals(ProxyControlGui.PROXY_PAUSE_HTTP_SAMPLER)) {
} else if (fieldName.equals(ProxyControlGui.HTTP_SAMPLER_NAME_FORMAT)) {
recorderGui.setSampleNameFormat(sampleNameFormat.getText());
} else if (fieldName.equals(ProxyControlGui.PROXY_PAUSE_HTTP_SAMPLER)) {
try {
Long.parseLong(proxyPauseHTTPSample.getText());
} catch (NumberFormatException nfe) {

View File

@ -100,7 +100,7 @@ public abstract class HTTPSamplerBase extends AbstractSampler
implements TestStateListener, TestIterationListener, ThreadListener, HTTPConstantsInterface,
Replaceable {
private static final long serialVersionUID = 242L;
private static final long serialVersionUID = 243L;
private static final Logger log = LoggerFactory.getLogger(HTTPSamplerBase.class);
@ -266,6 +266,9 @@ public abstract class HTTPSamplerBase extends AbstractSampler
// Embedded URLs must match this RE (if provided)
public static final String EMBEDDED_URL_RE = "HTTPSampler.embedded_url_re"; // $NON-NLS-1$
// Embedded URLs must not match this RE (if provided)
public static final String EMBEDDED_URL_EXCLUDE_RE = "HTTPSampler.embedded_url_exclude_re"; // $NON-NLS-1$
public static final String MONITOR = "HTTPSampler.monitor"; // $NON-NLS-1$
// Store MD5 hash instead of storing response
@ -1026,6 +1029,17 @@ public abstract class HTTPSamplerBase extends AbstractSampler
setProperty(new StringProperty(EMBEDDED_URL_RE, regex));
}
/**
* @return the regular (as String) expression that embedded URLs must not match
*/
public String getEmbededUrlExcludeRE() {
return getPropertyAsString(EMBEDDED_URL_EXCLUDE_RE, "");
}
public void setEmbeddedUrlExcludeRE(String regex) {
setProperty(new StringProperty(EMBEDDED_URL_EXCLUDE_RE, regex));
}
/**
* Populates the provided HTTPSampleResult with details from the Exception.
* Does not create a new instance, so should not be used directly to add a subsample.
@ -1349,17 +1363,29 @@ public abstract class HTTPSamplerBase extends AbstractSampler
res = lContainer;
// Get the URL matcher
String re = getEmbeddedUrlRE();
String allowRegex = getEmbeddedUrlRE();
Perl5Matcher localMatcher = null;
Pattern pattern = null;
if (re.length() > 0) {
Pattern allowPattern = null;
if (allowRegex.length() > 0) {
try {
pattern = JMeterUtils.getPattern(re);
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;
String excludeRegex = getEmbededUrlExcludeRE();
if (excludeRegex.length() > 0) {
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());
}
}
// For concurrent get resources
final List<Callable<AsynSamplerResultHolder>> list = new ArrayList<>();
@ -1396,8 +1422,12 @@ public abstract class HTTPSamplerBase extends AbstractSampler
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 (pattern != null && localMatcher != null && !localMatcher.matches(url.toString(), pattern)) {
if (allowPattern != null && localMatcher != null && !localMatcher.matches(url.toString(), allowPattern)) {
continue; // we have a pattern and the URL does not match, so skip it
}
if (excludePattern != null && localMatcher != null && localMatcher.matches(url.toString(), excludePattern)) {
continue; // we have a pattern and the URL does not match, so skip it
}
try {

View File

@ -32,6 +32,7 @@ import java.util.Map;
import java.util.TimeZone;
import org.apache.jmeter.junit.JMeterTestCase;
import org.apache.jmeter.protocol.http.control.CacheManager.CacheEntry;
import org.apache.jmeter.protocol.http.sampler.HTTPSampleResult;
import org.apache.jmeter.protocol.http.util.HTTPConstants;
import org.junit.jupiter.api.Test;
@ -281,8 +282,9 @@ public abstract class TestCacheManagerBase extends JMeterTestCase {
assertNotNull(getThreadCacheEntry(LOCAL_HOST), "Should find entry");
assertTrue(this.cacheManager.inCache(url), "Should find valid entry");
sleepTill(start + age / 10 + 10);
assertNotNull(getThreadCacheEntry(LOCAL_HOST), "Should find entry");
assertFalse(this.cacheManager.inCache(url), "Should not find valid entry");
CacheEntry cachedEntry = getThreadCacheEntry(LOCAL_HOST);
assertNotNull(cachedEntry, "Should find entry");
assertFalse(this.cacheManager.inCache(url), "Should not find valid entry. Found " + cachedEntry);
}
@Test

View File

@ -631,7 +631,7 @@ public abstract class AbstractJDBCTestElement extends AbstractTestElement implem
s.close();
}
} catch (SQLException e) {
log.warn("Error closing Statement {}", s.toString(), e);
log.warn("Error closing Statement {}", s, e);
}
}

View File

@ -74,7 +74,7 @@ public class SynchronousTransportListener extends TransportAdapter {
* Synchronized-method
* <p>
* Waits until {@link #finish()} was called and thus the end of the mail
* sending was signalled.
* sending was signaled.
*
* @throws InterruptedException
* when interrupted while waiting with the lock
@ -93,7 +93,7 @@ public class SynchronousTransportListener extends TransportAdapter {
public void finish() {
finished = true;
synchronized(LOCK) {
LOCK.notify();
LOCK.notifyAll();
}
}

View File

@ -63,9 +63,13 @@ Summary
<ch_title>Core improvements</ch_title>
<ch_title>Test Plan</ch_title>
<ch_title>Scripting / Debugging enhancements</ch_title>
<ch_title>UX improvements</ch_title>
<ch_title>Functions</ch_title>
-->
<ch_title>UX improvements</ch_title>
<p>The splash screen is now application-modal rather than system-modal, so it does not block other
applications when JMeter is starting up.</p>
<!-- =================== Incompatible changes =================== -->
<ch_section>Incompatible changes</ch_section>
@ -77,6 +81,8 @@ Summary
<h3>HTTP Samplers and Test Script Recorder</h3>
<ul>
<li><bug>63527</bug>Implement a new setting to allow the exclusion of embedded URLs</li>
<li><bug>64696</bug><pr>571</pr><pr>595</pr>Freestyle format for names in (Default)SamplerCreater. Based on a patch by Vincent Daburon (vdaburon at gmail.com)</li>
</ul>
<h3>Other samplers</h3>
@ -113,6 +119,7 @@ Summary
<li><bug>64446</bug>Better parse curl commands with backslash at line endings and support <code>PUT</code> method with data arguments</li>
<li><pr>599</pr>Ensure all buttons added to the toolbar behave/look consistently. Contributed by Jannis Weis</li>
<li><bug>64581</bug>Allow SampleResult#setIgnore to influence behaviour on Sampler Error</li>
<li><bug>64680</bug>Fall back to <code>JMETER_HOME</code> on startup to detect JMeter's installation directory</li>
</ul>
<ch_section>Non-functional changes</ch_section>
@ -121,11 +128,27 @@ Summary
<li><bug>64454</bug>More precise error message, when no datasource value can be found in JDBC sampler</li>
<li><bug>64440</bug>Log exeptions reported via <code>JMeterUtils#reportToUser</code> even when in GUI mode</li>
<li><pr>591</pr>Remove deprecated sudo flag from travis file. Deng Liming (liming.d.pro at gmail.com)</li>
<li>Updated Darklaf to 2.4.2 (from 2.1.1)</li>
<li>Updated Darklaf to 2.4.5 (from 2.1.1)</li>
<li>Updated Groovy to 3.0.5 (from 3.0.3)</li>
<li><pr>596</pr>Use neutral words in documentation</li>
<li><bug>63809</bug><pr>557</pr>Updated commons-collections to 4.4 (from 3.2.2) while keeping the jars for the old commons-collections 3.x for compatibility</li>
<li><pr>598</pr>Add another option for creating diffs to the building page. Contributed by jmetertea (github.com/jmetertea)</li>
<li><pr>609</pr>Make use of newer API for darklaf installation. Jannis Weis</li>
<li><pr>612</pr>Correct typos in <code>README.me</code>. Based on patches by Pooja Chandak (poojachandak002 at gmail.com)</li>
<li><pr>613</pr>Add documentation for Darklaf properties. Jannis Weis</li>
<li>Update SpotBugs to 4.1.2 (from 4.1.1), upgrade spotbugs-gradle-plugin to 4.5.0 (from 2.0.0)</li>
<li>Update org.sonarqube Gradle plugin to 3.0 (from 2.7.1)</li>
<li>Update Apache ActiveMQ to 5.16.0 (from 5.15.11)</li>
<li>Update Bouncycastle to 1.66 (from 1.64)</li>
<li>Update Apache commons-io to 2.7 (from 2.6)</li>
<li>Update Apache commons-lang3 to 3.11 (from 3.10)</li>
<li>Update Apache commons-net to 3.7 (from 3.6)</li>
<li>Update Apache commons-pool2 to 2.8.1 (from 2.8.0)</li>
<li>Update Apache commons-text to 1.9 (from 1.8)</li>
<li>Update equalsverifier to 3.4.2 (from 3.1.13)</li>
<li>Update junit5 to 5.6.2 (from 5.6.0)</li>
<li>Update Apache log4j2 to 2.13.3 (from 2.13.1)</li>
<li>Update rsyntaxtextarea to 3.1.1 (from 3.1.0)</li>
</ul>
<!-- =================== Bug fixes =================== -->
@ -135,6 +158,7 @@ Summary
<h3>HTTP Samplers and Test Script Recorder</h3>
<ul>
<li><bug>64479</bug>Regression: HTTP(s) Script Recorder prevents proper shutdown in non-GUI mode</li>
<li><bug>64653</bug>Exclude Javascript and JSON from parsing for charsets from forms by proxy</li>
</ul>
<h3>Other Samplers</h3>
@ -172,6 +196,7 @@ Summary
<h3>Documentation</h3>
<ul>
<li><pr>571</pr>Correct documented name of generated CA when using proxy script recorder. Part of a bigger PR. Vincent Daburon (vdaburon at gmail.com)</li>
</ul>
<h3>General</h3>
@ -204,6 +229,8 @@ Summary
<li><a href="https://github.com/topicus-pw-dvdouden">Daniel van den Ouden</a></li>
<li><a href="https://ubikloadpack.com" >Ubik Load Pack</a></li>
<li>Till Neunast (https://github.com/tilln)</li>
<li>Pooja Chandak (poojachandak002 at gmail.com)</li>
<li>Vincent Daburon (vdaburon at gmail.com)</li>
</ul>
<p>We also thank bug reporters who helped us improve JMeter.</p>
<ul>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -36,7 +36,7 @@
<note><b>These builds should not be used in production.</b></note>
<h2>Last Build status on Jenkins</h2>
<a href='https://builds.apache.org/job/JMeter-trunk/'><img src='https://builds.apache.org/buildStatus/icon?job=JMeter-trunk' /></a>
<a href='https://ci-builds.apache.org/job/JMeter/job/JMeter-trunk/'><img src='https://ci-builds.apache.org/buildStatus/icon?job=JMeter%2FJMeter-trunk'/></a>
<h2>Last Quality Report on Sonar</h2>
<a href="https://sonarcloud.io/dashboard?id=JMeter">Apache JMeter quality report</a>
@ -45,7 +45,7 @@
<p>JMeter CI builds are currently run by Jenkins and Buildbot</p>
<p>These are located at:
<ul>
<li><a href="https://builds.apache.org/job/JMeter-trunk/lastSuccessfulBuild/artifact/src/dist/build/distributions/">Last Successful Jenkins build for JMeter-trunk</a></li>
<li><a href="https://ci-builds.apache.org/job/JMeter/job/JMeter-trunk/lastSuccessfulBuild/artifact/src/dist/build/distributions/">Last Successful Jenkins build for JMeter-trunk</a></li>
<li><a href="http://ci.apache.org/projects/jmeter/nightlies/">Buildbot nightly builds for JMeter-trunk</a></li>
<li><a href="https://repository.apache.org/content/repositories/snapshots/org/apache/jmeter/">Maven Snapshots (Buildbot nightly builds)</a></li>
</ul>
@ -55,10 +55,10 @@
JMeter is distributed as a set of zip (or tar-gz) archive files as are the released versions.
You can find the bundles:
<ul>
<li>apache-jmeter-{SVN revision}.zip - Bundle in ZIP format</li>
<li>apache-jmeter-{SVN revision}.tgz - Bundle in TAR GZIP format</li>
<li>apache-jmeter-{SVN revision}_src.zip - Sources in ZIP format</li>
<li>apache-jmeter-{SVN revision}_src.tgz - Sources in TAR GZIP format</li>
<li>{git revision}/apache-jmeter-{version}.zip - Bundle in ZIP format</li>
<li>{git revision}/apache-jmeter-{version}.tgz - Bundle in TAR GZIP format</li>
<li>{git revision}/apache-jmeter-{version}_src.zip - Sources in ZIP format</li>
<li>{git revision}/apache-jmeter-{version}_src.tgz - Sources in TAR GZIP format</li>
</ul>
For each file you will also find a hash (MD5, SHA) that allows you to test its integrity.
</p>

View File

@ -331,10 +331,15 @@ and send HTTP/HTTPS requests for all images, Java applets, JavaScript files, CSS
Instead, the 32 character MD5 hash of the data is calculated and stored instead.
This is intended for testing large amounts of data.
</property>
<property name="Embedded URLs must match:" required="No">
<property name="URLs must match:" required="No">
If present, this must be a regular expression that is used to match against any embedded URLs found.
So if you only want to download embedded resources from <code>http://example.com/</code>, use the expression:
<code>http://example\.com/.*</code>
So if you only want to download embedded resources from <code>http://example.invalid/</code>, use the expression:
<code>http://example\.invalid/.*</code>
</property>
<property name="URLs must not match:" required="No">
If present, this must be a regular expression that is used to filter out any embedded URLs found.
So if you don't want to download PNG or SVG files from any source, use the expression:
<code>.*\.(?i:svg|png)</code>
</property>
<property name="Use concurrent pool" required="No">Use a pool of concurrent connections to get embedded resources.</property>
<property name="Size" required="No">Pool size for concurrent connections used to get embedded resources.</property>
@ -3898,10 +3903,15 @@ and send HTTP/HTTPS requests for all images, Java applets, JavaScript files, CSS
</property>
<property name="Use concurrent pool" required="No">Use a pool of concurrent connections to get embedded resources.</property>
<property name="Size" required="No">Pool size for concurrent connections used to get embedded resources.</property>
<property name="Embedded URLs must match:" required="No">
<property name="URLs must match:" required="No">
If present, this must be a regular expression that is used to match against any embedded URLs found.
So if you only want to download embedded resources from <code>http://example.com/</code>, use the expression:
<code>http://example\.com/.*</code>
So if you only want to download embedded resources from <code>http://example.invalid/</code>, use the expression:
<code>http://example\.invalid/.*</code>
</property>
<property name="URLs must not match:" required="No">
If present, this must be a regular expression that is used to filter out any embedded URLs found.
So if you don't want to download PNG or SVG files from any source, use the expression:
<code>.*\.(?i:svg|png)</code>
</property>
</properties>
<note>
@ -6531,7 +6541,7 @@ Behaviour can be modified with some properties by setting in <code>user.properti
</p>
</component>
<component name="HTTP(S) Test Script Recorder" was="HTTP Proxy Server" index="&sect-num;.9.5" width="1052" height="694" screenshot="proxy_control.png">
<component name="HTTP(S) Test Script Recorder" was="HTTP Proxy Server" index="&sect-num;.9.5" width="983" height="702" screenshot="proxy_control.png">
<description><p>The HTTP(S) Test Script Recorder allows JMeter to intercept and record your actions while you browse your web application
with your normal browser. JMeter will create test sample objects and store them
directly into your test plan as you go (so you can view samples interactively while you make them).<br/>
@ -6607,9 +6617,9 @@ As a consequence:
<li>The browser should display a dialogue asking if you want to accept the certificate or not. For example:
<source>
1) The server's name "<code>www.example.com</code>" does not match the certificate's name
"<code>JMeter Proxy (DO NOT TRUST)</code>". Somebody may be trying to eavesdrop on you.
2) The certificate for "<code>JMeter Proxy (DO NOT TRUST)</code>" is signed by the unknown Certificate Authority
"<code>JMeter Proxy (DO NOT TRUST)</code>". It is not possible to verify that this is a valid certificate.
"<code>_ JMeter Root CA for recording (INSTALL ONLY IF IT S YOURS)</code>". Somebody may be trying to eavesdrop on you.
2) The certificate for "<code>_ JMeter Root CA for recording (INSTALL ONLY IF IT S YOURS)</code>" is signed by the unknown Certificate Authority
"<code>_ JMeter Root CA for recording (INSTALL ONLY IF IT S YOURS)</code>". It is not possible to verify that this is a valid certificate.
</source>
You will need to accept the certificate in order to allow the JMeter Proxy to intercept the SSL traffic in order to
record it.
@ -6735,6 +6745,9 @@ Both Chrome and Internet Explorer use the same trust store for certificates.
<property name="Add Assertions" required="Yes">Add a blank assertion to each sampler?</property>
<property name="Regex Matching" required="Yes">Use Regex Matching when replacing variables? If checked replacement will use word boundaries, i.e. it will only replace word matching values of variable, not part of a word. A word boundary follows Perl5 definition and is equivalent to <code>\b</code>. More information below in the paragraph about "<code>User Defined Variable replacement</code>".</property>
<property name="Prefix/Transaction name" required="No">Add a prefix to sampler name during recording (Prefix mode). Or replace sampler name by user chosen name (Transaction name)</property>
<property name="Naming scheme" required="No">Select the naming scheme for sampler names during recording. Default is <code>Transaction name</code></property>
<property name="Naming format" required="No">If <code>Use format string</code> is selected as naming scheme, a freestyle format can be given. Placeholders for the transaction name, path and counter can be given by <code>#{name}</code>, <code>#{path}</code> and <code>#{counter}</code>. A simple format could be "<code>#{name}-#{counter}</code>", which would be equivalent to the numbered default naming scheme. For more complex formatting Java formatting for MessageFormat can be used, as in "<code>#{counter,number,000}: #{name}-#{path}</code>", which would print the counter filled with up to three zeroes. Default is an empty string.</property>
<property name="Counter start value" required="No">Can be used to reset the counter to a given value. Note, that the next sample will first increment and then use the value. If the first sampler should start with <code>1</code>, reset the counter to <code>0</code>.</property>
<property name="Create new transaction after request (ms)">Inactivity time between two requests needed to consider them in two separate groups.</property>
<property name="Type" required="Yes">Which type of sampler to generate (the HTTPClient default or Java)</property>
<property name="Redirect Automatically" required="Yes">Set Redirect Automatically in the generated samplers?</property>

View File

@ -196,6 +196,17 @@ Defaults to: <code>true</code>
Defaults to: <code>500</code></property>
</properties>
</section>
<section name="&sect-num;.4.1 Darklaf configuration" anchor="darklaf_config">
<properties>
<property name="darklaf.decorations">
Enables custom window chrome when using a Darklaf Look And Feel.
Defaults to: <code>false</code></property>
<property name="darklaf.unifiedMenuBar">
Enables the unified menubar on Windows when using a Darklaf Look and Feel.<br/>
This property only has an effect if <code>darklaf.native</code> is <code>true</code>.
Defaults to: <code>true</code></property>
</properties>
</section>
<section name="&sect-num;.5 Toolbar display" anchor="toolbar_display">
<properties>
<property name="jmeter.toolbar.icons">