This is an automated email from the ASF dual-hosted git repository.

vladimirsitnikov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/jmeter.git


The following commit(s) were added to refs/heads/master by this push:
     new 8cf1e4a186 feat: allow to enable/disable individual arguments in HTTP 
Sampler
8cf1e4a186 is described below

commit 8cf1e4a1868199dcd1d1261866f22fa43be31767
Author: pochopsp <[email protected]>
AuthorDate: Tue Jun 11 23:55:33 2024 +0200

    feat: allow to enable/disable individual arguments in HTTP Sampler
    
    This property is set by the user for each HTTP parameter by
    clicking on the "Enable" column put on the very left of each
    parameter row.
    
    Fixes https://github.com/apache/jmeter/issues/5466
    
    Co-authored-by: Vladimir Sitnikov <[email protected]>
---
 .../java/org/apache/jmeter/config/Arguments.java   |  16 +-
 .../jmeter/treebuilder/TreeBuilderExtensions.kt    |  34 ++++
 .../jmeter/timers/ConstantThroughputTimerKtTest.kt |  17 +-
 .../protocol/http/config/gui/UrlConfigGui.java     |   2 +-
 .../protocol/http/gui/HTTPArgumentsPanel.java      |  12 +-
 .../jmeter/protocol/http/sampler/AjpSampler.java   |   2 +-
 .../jmeter/protocol/http/sampler/HTTPHC4Impl.java  |  10 +-
 .../protocol/http/sampler/HTTPSamplerBase.java     |  11 +-
 .../jmeter/protocol/http/sampler/PostWriter.java   |   4 +-
 .../jmeter/protocol/http/sampler/PutWriter.java    |   2 +-
 .../sampler/HttpSamplerDisableArgumentsTest.kt     | 174 +++++++++++++++++++++
 .../protocol/http/sampler/HttpSamplerTest.kt       |  38 +----
 .../http/sampler/HttpSamplerTestingUtils.kt        |  40 +++++
 .../http/control/HttpRequestDefaultsExtensions.kt  |  53 +++++++
 14 files changed, 342 insertions(+), 73 deletions(-)

diff --git a/src/core/src/main/java/org/apache/jmeter/config/Arguments.java 
b/src/core/src/main/java/org/apache/jmeter/config/Arguments.java
index e6a060dd7f..0301eb5862 100644
--- a/src/core/src/main/java/org/apache/jmeter/config/Arguments.java
+++ b/src/core/src/main/java/org/apache/jmeter/config/Arguments.java
@@ -23,11 +23,13 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.commons.collections4.iterators.FilterIterator;
 import org.apache.jmeter.testelement.property.CollectionProperty;
 import org.apache.jmeter.testelement.property.JMeterProperty;
 import org.apache.jmeter.testelement.property.PropertyIterator;
 import org.apache.jmeter.testelement.property.TestElementProperty;
 import org.apache.jmeter.testelement.schema.PropertiesAccessor;
+import org.apiguardian.api.API;
 
 /**
  * A set of Argument objects.
@@ -100,7 +102,7 @@ public class Arguments extends ConfigTestElement implements 
Serializable, Iterab
             // that this element's values prevail over defaults provided by
             // configuration
             // elements:
-            if (!argMap.containsKey(arg.getName())) {
+            if (!argMap.containsKey(arg.getName()) && arg.isEnabled()) {
                 argMap.put(arg.getName(), arg.getValue());
             }
         }
@@ -173,6 +175,18 @@ public class Arguments extends ConfigTestElement 
implements Serializable, Iterab
         return getArguments().iterator();
     }
 
+    /**
+     * Returns the list of enabled arguments.
+     * @return the list of enabled arguments
+     */
+    @API(since = "5.6", status = API.Status.EXPERIMENTAL)
+    public Iterable<JMeterProperty> getEnabledArguments() {
+        return () -> new FilterIterator<>(iterator(), property -> {
+            Object value = property.getObjectValue();
+            return value instanceof Argument argument && argument.isEnabled();
+        });
+    }
+
     /**
      * Create a string representation of the arguments.
      *
diff --git 
a/src/core/src/testFixtures/kotlin/org/apache/jmeter/treebuilder/TreeBuilderExtensions.kt
 
b/src/core/src/testFixtures/kotlin/org/apache/jmeter/treebuilder/TreeBuilderExtensions.kt
new file mode 100644
index 0000000000..650456f4f1
--- /dev/null
+++ 
b/src/core/src/testFixtures/kotlin/org/apache/jmeter/treebuilder/TreeBuilderExtensions.kt
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jmeter.treebuilder
+
+import org.apache.jmeter.control.LoopController
+import org.apache.jmeter.threads.ThreadGroup
+
+fun TreeBuilder.oneRequest(body: ThreadGroup.() -> Unit) {
+    ThreadGroup::class {
+        numThreads = 1
+        rampUp = 0
+        setSamplerController(
+            LoopController().apply {
+                loops = 1
+            }
+        )
+        body()
+    }
+}
diff --git 
a/src/functions/src/test/kotlin/org/apache/jmeter/timers/ConstantThroughputTimerKtTest.kt
 
b/src/functions/src/test/kotlin/org/apache/jmeter/timers/ConstantThroughputTimerKtTest.kt
index 1a1dc805ae..bcbc6cf045 100644
--- 
a/src/functions/src/test/kotlin/org/apache/jmeter/timers/ConstantThroughputTimerKtTest.kt
+++ 
b/src/functions/src/test/kotlin/org/apache/jmeter/timers/ConstantThroughputTimerKtTest.kt
@@ -17,30 +17,15 @@
 
 package org.apache.jmeter.timers
 
-import org.apache.jmeter.control.LoopController
 import org.apache.jmeter.junit.JMeterTestCase
 import org.apache.jmeter.sampler.DebugSampler
 import org.apache.jmeter.test.assertions.executePlanAndCollectEvents
-import org.apache.jmeter.threads.ThreadGroup
-import org.apache.jmeter.treebuilder.TreeBuilder
+import org.apache.jmeter.treebuilder.oneRequest
 import org.junit.jupiter.api.Assertions.assertEquals
 import org.junit.jupiter.api.Test
 import kotlin.time.Duration.Companion.seconds
 
 class ConstantThroughputTimerKtTest : JMeterTestCase() {
-    fun TreeBuilder.oneRequest(body: ThreadGroup.() -> Unit) {
-        ThreadGroup::class {
-            numThreads = 1
-            rampUp = 0
-            setSamplerController(
-                LoopController().apply {
-                    loops = 1
-                }
-            )
-            body()
-        }
-    }
-
     @Test
     fun `throughput as variable`() {
         val events = executePlanAndCollectEvents(5.seconds) {
diff --git 
a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/config/gui/UrlConfigGui.java
 
b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/config/gui/UrlConfigGui.java
index 593d54a782..2cb82f654c 100644
--- 
a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/config/gui/UrlConfigGui.java
+++ 
b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/config/gui/UrlConfigGui.java
@@ -261,7 +261,7 @@ public class UrlConfigGui extends JPanel implements 
ChangeListener {
      */
     private static String computePostBody(Arguments arguments, boolean 
crlfToLF) {
         StringBuilder postBody = new StringBuilder();
-        for (JMeterProperty argument : arguments) {
+        for (JMeterProperty argument : arguments.getEnabledArguments()) {
             HTTPArgument arg = (HTTPArgument) argument.getObjectValue();
             String value = arg.getValue();
             if (crlfToLF) {
diff --git 
a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/gui/HTTPArgumentsPanel.java
 
b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/gui/HTTPArgumentsPanel.java
index d350dc2666..7e58144621 100644
--- 
a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/gui/HTTPArgumentsPanel.java
+++ 
b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/gui/HTTPArgumentsPanel.java
@@ -39,12 +39,15 @@ import org.apache.jorphan.util.StringUtilities;
 /**
  * A GUI panel allowing the user to enter HTTP Parameters.
  * These have names and values, as well as check-boxes to determine whether or 
not to
- * include the "=" sign in the output and whether or not to encode the output.
+ * include the "=" sign in the output and whether or not to encode the output 
and
+ * whether or not to enable them.
  */
 public class HTTPArgumentsPanel extends ArgumentsPanel {
 
     private static final long serialVersionUID = 240L;
 
+    private static final String ENABLE = "enable"; //$NON-NLS-1$
+
     private static final String ENCODE_OR_NOT = "encode?"; //$NON-NLS-1$
 
     private static final String INCLUDE_EQUALS = "include_equals"; 
//$NON-NLS-1$
@@ -60,21 +63,23 @@ public class HTTPArgumentsPanel extends ArgumentsPanel {
     @Override
     protected void initializeTableModel() {
         tableModel = new ObjectTableModel(new String[] {
-                ArgumentsPanel.COLUMN_RESOURCE_NAMES_0, 
ArgumentsPanel.COLUMN_RESOURCE_NAMES_1, ENCODE_OR_NOT, CONTENT_TYPE, 
INCLUDE_EQUALS },
+                ENABLE, ArgumentsPanel.COLUMN_RESOURCE_NAMES_0, 
ArgumentsPanel.COLUMN_RESOURCE_NAMES_1, ENCODE_OR_NOT, CONTENT_TYPE, 
INCLUDE_EQUALS },
                 HTTPArgument.class,
                 new Functor[] {
+                new Functor("isEnabled"), //$NON-NLS-1$
                 new Functor("getName"), //$NON-NLS-1$
                 new Functor("getValue"), //$NON-NLS-1$
                 new Functor("isAlwaysEncoded"), //$NON-NLS-1$
                 new Functor("getContentType"), //$NON-NLS-1$
                 new Functor("isUseEquals") }, //$NON-NLS-1$
                 new Functor[] {
+                new Functor("setEnabled"), //$NON-NLS-1$
                 new Functor("setName"), //$NON-NLS-1$
                 new Functor("setValue"), //$NON-NLS-1$
                 new Functor("setAlwaysEncoded"), //$NON-NLS-1$
                 new Functor("setContentType"),
                 new Functor("setUseEquals")}, //$NON-NLS-1$
-                new Class[] {String.class, String.class, Boolean.class, 
String.class, Boolean.class });
+                new Class[] {Boolean.class, String.class, String.class, 
Boolean.class, String.class, Boolean.class });
     }
 
     public static boolean testFunctors(){
@@ -85,6 +90,7 @@ public class HTTPArgumentsPanel extends ArgumentsPanel {
 
     @Override
     protected void sizeColumns(JTable table) {
+        GuiUtils.fixSize(table.getColumn(ENABLE), table);
         GuiUtils.fixSize(table.getColumn(INCLUDE_EQUALS), table);
         GuiUtils.fixSize(table.getColumn(ENCODE_OR_NOT), table);
     }
diff --git 
a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/AjpSampler.java
 
b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/AjpSampler.java
index d705ae726c..2a5fe624bc 100644
--- 
a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/AjpSampler.java
+++ 
b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/AjpSampler.java
@@ -279,7 +279,7 @@ public class AjpSampler extends HTTPSamplerBase implements 
Interruptible {
                 setString(HTTPConstants.APPLICATION_X_WWW_FORM_URLENCODED);
                 StringBuilder sb = new StringBuilder();
                 boolean first = true;
-                for (JMeterProperty arg : getArguments()) {
+                for (JMeterProperty arg : 
getArguments().getEnabledArguments()) {
                     if (first) {
                         first = false;
                     } else {
diff --git 
a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl.java
 
b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl.java
index 2e68cb2226..569bb164b6 100644
--- 
a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl.java
+++ 
b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/HTTPHC4Impl.java
@@ -158,7 +158,6 @@ import org.apache.jmeter.samplers.SampleResult;
 import org.apache.jmeter.services.FileServer;
 import org.apache.jmeter.testelement.property.CollectionProperty;
 import org.apache.jmeter.testelement.property.JMeterProperty;
-import org.apache.jmeter.testelement.property.PropertyIterator;
 import org.apache.jmeter.threads.JMeterContextService;
 import org.apache.jmeter.threads.JMeterVariables;
 import org.apache.jmeter.util.JMeterUtils;
@@ -1562,7 +1561,7 @@ public class HTTPHC4Impl extends HTTPHCAbstractImpl {
             }
             // Create the parts
             // Add any parameters
-            for (JMeterProperty jMeterProperty : getArguments()) {
+            for (JMeterProperty jMeterProperty : 
getArguments().getEnabledArguments()) {
                 HTTPArgument arg = (HTTPArgument) 
jMeterProperty.getObjectValue();
                 String parameterName = arg.getName();
                 if (arg.isSkippable(parameterName)) {
@@ -1644,7 +1643,7 @@ public class HTTPHC4Impl extends HTTPHCAbstractImpl {
 
                     // Just append all the parameter values, and use that as 
the post body
                     StringBuilder postBody = new StringBuilder();
-                    for (JMeterProperty jMeterProperty : getArguments()) {
+                    for (JMeterProperty jMeterProperty : 
getArguments().getEnabledArguments()) {
                         HTTPArgument arg = (HTTPArgument) 
jMeterProperty.getObjectValue();
                         postBody.append(arg.getEncodedValue(contentEncoding));
                     }
@@ -1787,10 +1786,9 @@ public class HTTPHC4Impl extends HTTPHCAbstractImpl {
     private UrlEncodedFormEntity createUrlEncodedFormEntity(final String 
urlContentEncoding) throws UnsupportedEncodingException {
         // It is a normal request, with parameter names and values
         // Add the parameters
-        PropertyIterator args = getArguments().iterator();
         List<NameValuePair> nvps = new ArrayList<>();
-        while (args.hasNext()) {
-            HTTPArgument arg = (HTTPArgument) args.next().getObjectValue();
+        for (JMeterProperty jMeterProperty: 
getArguments().getEnabledArguments()) {
+            HTTPArgument arg = (HTTPArgument) jMeterProperty.getObjectValue();
             // The HTTPClient always urlencodes both name and value,
             // so if the argument is already encoded, we have to decode
             // it before adding it to the post request
diff --git 
a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java
 
b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java
index ccaf33d1e6..45628aeed2 100644
--- 
a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java
+++ 
b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/HTTPSamplerBase.java
@@ -79,7 +79,6 @@ import org.apache.jmeter.testelement.TestStateListener;
 import org.apache.jmeter.testelement.ThreadListener;
 import org.apache.jmeter.testelement.property.CollectionProperty;
 import org.apache.jmeter.testelement.property.JMeterProperty;
-import org.apache.jmeter.testelement.property.PropertyIterator;
 import org.apache.jmeter.testelement.schema.PropertiesAccessor;
 import org.apache.jmeter.testelement.schema.PropertyDescriptor;
 import org.apache.jmeter.threads.JMeterContext;
@@ -410,7 +409,7 @@ public abstract class HTTPSamplerBase extends 
AbstractSampler
             return true;
         } else {
             boolean hasArguments = false;
-            for (JMeterProperty jMeterProperty : getArguments()) {
+            for (JMeterProperty jMeterProperty : 
getArguments().getEnabledArguments()) {
                 hasArguments = true;
                 HTTPArgument arg = (HTTPArgument) 
jMeterProperty.getObjectValue();
                 if (arg.getName() != null && !arg.getName().isEmpty()) {
@@ -1156,9 +1155,10 @@ public abstract class HTTPSamplerBase extends 
AbstractSampler
      */
     public String getQueryString(final String contentEncoding) {
 
-        CollectionProperty arguments = getArguments().getArguments();
+        Arguments args = getArguments();
+        Iterator<JMeterProperty> iter = args.getEnabledArguments().iterator();
         // Optimisation : avoid building useless objects if empty arguments
-        if(arguments.isEmpty()) {
+        if (!iter.hasNext()) {
             return "";
         }
         String lContentEncoding = contentEncoding;
@@ -1168,8 +1168,7 @@ public abstract class HTTPSamplerBase extends 
AbstractSampler
             lContentEncoding = EncoderCache.URL_ARGUMENT_ENCODING;
         }
 
-        StringBuilder buf = new StringBuilder(arguments.size() * 15);
-        PropertyIterator iter = arguments.iterator();
+        StringBuilder buf = new StringBuilder(args.getArgumentCount() * 15);
         boolean first = true;
         while (iter.hasNext()) {
             HTTPArgument item = null;
diff --git 
a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/PostWriter.java
 
b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/PostWriter.java
index c34d430829..8cc29d8cdd 100644
--- 
a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/PostWriter.java
+++ 
b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/PostWriter.java
@@ -191,7 +191,7 @@ public class PostWriter {
             ByteArrayOutputStream bos = new ByteArrayOutputStream();
             OutputStreamWriter osw = new OutputStreamWriter(bos, 
contentEncoding);
             // Add any parameters
-            for (JMeterProperty jMeterProperty : sampler.getArguments()) {
+            for (JMeterProperty jMeterProperty : 
sampler.getArguments().getEnabledArguments()) {
                 HTTPArgument arg = (HTTPArgument) 
jMeterProperty.getObjectValue();
                 String parameterName = arg.getName();
                 if (arg.isSkippable(parameterName)) {
@@ -300,7 +300,7 @@ public class PostWriter {
 
                     // Just append all the parameter values, and use that as 
the post body
                     StringBuilder postBodyBuffer = new StringBuilder();
-                    for (JMeterProperty jMeterProperty : 
sampler.getArguments()) {
+                    for (JMeterProperty jMeterProperty : 
sampler.getArguments().getEnabledArguments()) {
                         HTTPArgument arg = (HTTPArgument) 
jMeterProperty.getObjectValue();
                         
postBodyBuffer.append(arg.getEncodedValue(contentEncoding));
                     }
diff --git 
a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/PutWriter.java
 
b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/PutWriter.java
index 5a020662f7..488495d44c 100644
--- 
a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/PutWriter.java
+++ 
b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/sampler/PutWriter.java
@@ -85,7 +85,7 @@ public class PutWriter extends PostWriter {
 
             // Just append all the parameter values, and use that as the put 
body
             StringBuilder putBodyBuffer = new StringBuilder();
-             for (JMeterProperty jMeterProperty : sampler.getArguments()) {
+             for (JMeterProperty jMeterProperty : 
sampler.getArguments().getEnabledArguments()) {
                  HTTPArgument arg = (HTTPArgument) 
jMeterProperty.getObjectValue();
                  putBodyBuffer.append(arg.getEncodedValue(contentEncoding));
              }
diff --git 
a/src/protocol/http/src/test/kotlin/org/apache/jmeter/protocol/http/sampler/HttpSamplerDisableArgumentsTest.kt
 
b/src/protocol/http/src/test/kotlin/org/apache/jmeter/protocol/http/sampler/HttpSamplerDisableArgumentsTest.kt
new file mode 100644
index 0000000000..80c54d0f2a
--- /dev/null
+++ 
b/src/protocol/http/src/test/kotlin/org/apache/jmeter/protocol/http/sampler/HttpSamplerDisableArgumentsTest.kt
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jmeter.protocol.http.sampler
+
+import com.github.tomakehurst.wiremock.client.WireMock.aMultipart
+import com.github.tomakehurst.wiremock.client.WireMock.aResponse
+import com.github.tomakehurst.wiremock.client.WireMock.equalTo
+import com.github.tomakehurst.wiremock.client.WireMock.get
+import com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor
+import com.github.tomakehurst.wiremock.client.WireMock.post
+import com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor
+import com.github.tomakehurst.wiremock.client.WireMock.put
+import com.github.tomakehurst.wiremock.client.WireMock.putRequestedFor
+import com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo
+import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo
+import com.github.tomakehurst.wiremock.junit5.WireMockTest
+import org.apache.jmeter.junit.JMeterTestCase
+import org.apache.jmeter.protocol.http.control.arguments
+import org.apache.jmeter.protocol.http.control.httpRequestDefaults
+import org.apache.jmeter.protocol.http.util.HTTPArgument
+import org.apache.jmeter.test.assertions.executePlanAndCollectEvents
+import org.apache.jmeter.treebuilder.TreeBuilder
+import org.apache.jmeter.treebuilder.oneRequest
+import org.junit.jupiter.params.ParameterizedTest
+import org.junit.jupiter.params.provider.ValueSource
+import kotlin.time.Duration.Companion.seconds
+
+@WireMockTest
+class HttpSamplerDisableArgumentsTest : JMeterTestCase() {
+
+    fun TreeBuilder.httpRequest(body: HTTPSamplerProxy.() -> Unit) {
+        HTTPSamplerProxy::class {
+            name = "Test disabled params"
+            method = "GET"
+            domain = "localhost"
+            path = "/test"
+            body()
+        }
+    }
+
+    @ParameterizedTest
+    @ValueSource(strings = ["Java", "HttpClient4"])
+    fun `GET disable param1 should send enabled param2`(httpImplementation: 
String, server: WireMockRuntimeInfo) {
+        server.wireMock.register(
+            get("/test").willReturn(aResponse().withStatus(200))
+        )
+
+        executePlanAndCollectEvents(10.seconds) {
+            oneRequest {
+                httpRequest {
+                    method = "GET"
+                    implementation = httpImplementation
+                    port = server.httpPort
+                    addArgument("param1", "value1")
+                    arguments.getArgument(0).isEnabled = false
+                    addArgument("param2", "value2")
+                }
+            }
+        }
+
+        server.wireMock.verifyThat(
+            1,
+            getRequestedFor(urlEqualTo("/test?param2=value2"))
+        )
+    }
+
+    @ParameterizedTest
+    @ValueSource(strings = ["Java", "HttpClient4"])
+    fun `PUT disable param2 should send enabled param1 and 
param3`(httpImplementation: String, server: WireMockRuntimeInfo) {
+        server.wireMock.register(
+            put("/test").willReturn(aResponse().withStatus(200))
+        )
+
+        executePlanAndCollectEvents(1000.seconds) {
+            oneRequest {
+                httpRequest {
+                    method = "PUT"
+                    implementation = httpImplementation
+                    port = server.httpPort
+                    postBodyRaw = true
+                    addArgument("param1", "value1")
+                    addArgument("param2", "value2")
+                    arguments.getArgument(1).isEnabled = false
+                    addArgument("param3", "value3")
+                }
+            }
+        }
+
+        server.wireMock.verifyThat(
+            1,
+            putRequestedFor(urlEqualTo("/test"))
+                .withRequestBody(equalTo("value1value3"))
+        )
+    }
+
+    @ParameterizedTest
+    @ValueSource(strings = ["Java", "HttpClient4"])
+    fun `POST disable default and non-default param should send the only 
enabled non-default param`(httpImplementation: String, server: 
WireMockRuntimeInfo) {
+        server.wireMock.register(
+            post("/test").willReturn(aResponse().withStatus(200))
+        )
+
+        executePlanAndCollectEvents(10.seconds) {
+            oneRequest {
+                httpRequestDefaults {
+                    arguments {
+                        addArgument(
+                            HTTPArgument("param0", "value0").apply {
+                                isEnabled = false
+                            }
+                        )
+                        addArgument(
+                            HTTPArgument("param4", "value4")
+                        )
+                    }
+                }
+                httpRequest {
+                    method = "POST"
+                    doMultipart = true
+                    implementation = httpImplementation
+                    port = server.httpPort
+                    addArgument("param1", "value1")
+                    arguments.getArgument(0).isEnabled = false
+                    addArgument("param2", "value2")
+                }
+            }
+        }
+
+        server.wireMock.verifyThat(
+            1,
+            postRequestedFor(urlEqualTo("/test"))
+                .withRequestBodyPart(
+                    aMultipart("param2").withBody(equalTo("value2")).build()
+                )
+                .withRequestBodyPart(
+                    aMultipart("param4").withBody(equalTo("value4")).build()
+                )
+                .withRequestBody(
+                    httpImplementation,
+                    """
+                    -----------------------------7d159c1302d0y0
+                    Content-Disposition: form-data; name="param2"
+                    Content-Type: text/plain; charset=UTF-8
+                    Content-Transfer-Encoding: 8bit
+
+                    value2
+                    -----------------------------7d159c1302d0y0
+                    Content-Disposition: form-data; name="param4"
+                    Content-Type: text/plain; charset=UTF-8
+                    Content-Transfer-Encoding: 8bit
+
+                    value4
+                    -----------------------------7d159c1302d0y0--
+
+                    """.trimIndent()
+                )
+        )
+    }
+}
diff --git 
a/src/protocol/http/src/test/kotlin/org/apache/jmeter/protocol/http/sampler/HttpSamplerTest.kt
 
b/src/protocol/http/src/test/kotlin/org/apache/jmeter/protocol/http/sampler/HttpSamplerTest.kt
index fb82fe4adf..180bbb42b6 100644
--- 
a/src/protocol/http/src/test/kotlin/org/apache/jmeter/protocol/http/sampler/HttpSamplerTest.kt
+++ 
b/src/protocol/http/src/test/kotlin/org/apache/jmeter/protocol/http/sampler/HttpSamplerTest.kt
@@ -21,20 +21,17 @@ import 
com.github.tomakehurst.wiremock.client.WireMock.aMultipart
 import com.github.tomakehurst.wiremock.client.WireMock.aResponse
 import com.github.tomakehurst.wiremock.client.WireMock.containing
 import com.github.tomakehurst.wiremock.client.WireMock.equalTo
-import com.github.tomakehurst.wiremock.client.WireMock.matching
 import com.github.tomakehurst.wiremock.client.WireMock.post
 import com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor
 import com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo
 import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo
 import com.github.tomakehurst.wiremock.junit5.WireMockTest
-import com.github.tomakehurst.wiremock.matching.RequestPatternBuilder
-import org.apache.jmeter.control.LoopController
 import org.apache.jmeter.junit.JMeterTestCase
 import org.apache.jmeter.protocol.http.control.Header
 import org.apache.jmeter.protocol.http.util.HTTPFileArg
 import org.apache.jmeter.test.assertions.executePlanAndCollectEvents
-import org.apache.jmeter.threads.ThreadGroup
 import org.apache.jmeter.treebuilder.TreeBuilder
+import org.apache.jmeter.treebuilder.oneRequest
 import org.junit.jupiter.api.Assumptions.assumeTrue
 import org.junit.jupiter.api.io.TempDir
 import org.junit.jupiter.params.ParameterizedTest
@@ -51,21 +48,8 @@ class HttpSamplerTest : JMeterTestCase() {
     @TempDir
     lateinit var dir: Path
 
-    fun TreeBuilder.oneRequest(body: ThreadGroup.() -> Unit) {
-        ThreadGroup::class {
-            numThreads = 1
-            rampUp = 0
-            setSamplerController(
-                LoopController().apply {
-                    loops = 1
-                }
-            )
-            body()
-        }
-    }
-
     fun TreeBuilder.httpPost(body: HTTPSamplerProxy.() -> Unit) {
-        org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy::class {
+        HTTPSamplerProxy::class {
             name = "Upload file"
             method = "POST"
             domain = "localhost"
@@ -137,24 +121,6 @@ class HttpSamplerTest : JMeterTestCase() {
         )
     }
 
-    fun RequestPatternBuilder.withRequestBody(
-        httpImplementation: String,
-        body: String
-    ) = apply {
-        // normalize line endings to CRLF
-        val normalizedBody = body.replace("\r\n", "\n").replace("\n", "\r\n")
-        withRequestBody(
-            if (httpImplementation == "Java") {
-                equalTo(normalizedBody)
-            } else {
-                matching(
-                    normalizedBody
-                        .replace(PostWriter.BOUNDARY, "[^ \\n\\r]{1,69}?")
-                )
-            }
-        )
-    }
-
     @ParameterizedTest
     @ValueSource(strings = ["Java", "HttpClient4"])
     fun `one parameter`(httpImplementation: String, server: 
WireMockRuntimeInfo) {
diff --git 
a/src/protocol/http/src/test/kotlin/org/apache/jmeter/protocol/http/sampler/HttpSamplerTestingUtils.kt
 
b/src/protocol/http/src/test/kotlin/org/apache/jmeter/protocol/http/sampler/HttpSamplerTestingUtils.kt
new file mode 100644
index 0000000000..bc9c8500d8
--- /dev/null
+++ 
b/src/protocol/http/src/test/kotlin/org/apache/jmeter/protocol/http/sampler/HttpSamplerTestingUtils.kt
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jmeter.protocol.http.sampler
+
+import com.github.tomakehurst.wiremock.client.WireMock.equalTo
+import com.github.tomakehurst.wiremock.client.WireMock.matching
+import com.github.tomakehurst.wiremock.matching.RequestPatternBuilder
+
+fun RequestPatternBuilder.withRequestBody(
+    httpImplementation: String,
+    body: String
+) = apply {
+    // normalize line endings to CRLF
+    val normalizedBody = body.replace("\r\n", "\n").replace("\n", "\r\n")
+    withRequestBody(
+        if (httpImplementation == "Java") {
+            equalTo(normalizedBody)
+        } else {
+            matching(
+                normalizedBody
+                    .replace(PostWriter.BOUNDARY, "[^ \\n\\r]{1,69}?")
+            )
+        }
+    )
+}
diff --git 
a/src/protocol/http/src/testFixtures/kotlin/org/apache/jmeter/protocol/http/control/HttpRequestDefaultsExtensions.kt
 
b/src/protocol/http/src/testFixtures/kotlin/org/apache/jmeter/protocol/http/control/HttpRequestDefaultsExtensions.kt
new file mode 100644
index 0000000000..b64fa9563e
--- /dev/null
+++ 
b/src/protocol/http/src/testFixtures/kotlin/org/apache/jmeter/protocol/http/control/HttpRequestDefaultsExtensions.kt
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.jmeter.protocol.http.control
+
+import org.apache.jmeter.config.Arguments
+import org.apache.jmeter.config.ConfigTestElement
+import org.apache.jmeter.protocol.http.sampler.HTTPSamplerBaseSchema
+import org.apache.jmeter.testelement.property.TestElementProperty
+import org.apache.jmeter.treebuilder.Action
+import org.apache.jmeter.treebuilder.TreeBuilder
+
+fun TreeBuilder.httpRequestDefaults(configure: Action<ConfigTestElement> = 
Action {}) {
+    ConfigTestElement::class {
+        props {
+            it[name] = "HTTP Request Defaults"
+            it[guiClass] = 
"org.apache.jmeter.protocol.http.config.gui.HttpDefaultsGui"
+        }
+        setProperty(
+            TestElementProperty(
+                HTTPSamplerBaseSchema.arguments.name,
+                Arguments().apply {
+                    props {
+                        it[guiClass] = 
"org.apache.jmeter.protocol.http.gui.HTTPArgumentsPanel"
+                        it[testClass] = "org.apache.jmeter.config.Arguments"
+                    }
+                }
+            )
+        )
+        configure(this)
+    }
+}
+
+val ConfigTestElement.arguments: Arguments
+    get() = getProperty(HTTPSamplerBaseSchema.arguments.name) as Arguments
+
+fun ConfigTestElement.arguments(configure: Action<Arguments> = Action {}) {
+    configure((getProperty(HTTPSamplerBaseSchema.arguments.name) as 
TestElementProperty).element as Arguments)
+}


Reply via email to