Skip to content

Commit

Permalink
Merge pull request #74 from Blazemeter/RELEASE_v2.6
Browse files Browse the repository at this point in the history
Release v2.6
  • Loading branch information
Baraujo25 authored Aug 22, 2024
2 parents 5bc7a86 + 298cac8 commit de76670
Show file tree
Hide file tree
Showing 30 changed files with 495 additions and 170 deletions.
4 changes: 4 additions & 0 deletions docs/src/guide/after-recording.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ If you select more than one, the plugin will use the union of the dynamic values
By default, the latest version of a Template is selected, but you can change that by clicking on the field in the Version column.

![Select Correlation Templates](./assets/select-correlation-template.png)
::: tip
Since version [v2.5.1](https://github.com/Blazemeter/CorrelationRecorder/releases/tag/v2.5.1) you can quickly test your pre-existing rules in the Correlation rules tab by selecting the *Draft* template.
As long as you have rules underdevelopment, the Draft template will be accessible.
:::

::: warning

Expand Down
Binary file modified docs/src/guide/assets/select-correlation-template.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/src/guide/installation-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Once JMeter restarts, the Auto Correlation Recorder plugin will be installed.

### Manually

1. Go to the [Auto Correlation Recorder plugin page](https://jmeter-plugins.org/?search=BlazeMeter%20-%20Correlation%20Recorder%20Plugin) and download the
1. Go to the [Auto Correlation Recorder plugin page](https://jmeter-plugins.org/?search=Blazemeter%20-%20Auto%20Correlation%20Recorder%20Plugin) and download the
latest version of the plugin, with the dependencies.
1. Place the Plugin jar in the ext folder of your JMeter installation. The ext folder is usually located in
`<JMeter_Home>/lib/ext`.
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<groupId>com.blazemeter</groupId>
<artifactId>jmeter-bzm-correlation-recorder</artifactId>
<packaging>jar</packaging>
<version>2.5.1</version>
<version>2.6</version>
<name>Auto Correlation Recorder</name>
<description>Auto Correlation Recorder as JMeter Plugin</description>
<url>https://github.com/Blazemeter/CorrelationRecorder</url>
Expand Down
14 changes: 14 additions & 0 deletions releases.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,19 @@
"json>=20190722",
"maven-artifact>=3.8.4"
]
},
{
"version": "2.6",
"what_is_new": "Encode and decode automatic correlation",
"dependencies": [
"jackson-dataformat-xml>=2.10.3",
"jackson-annotations>=2.13.3",
"jackson-databind>=2.10.3",
"jackson-core>=2.13.3",
"jackson-module-jaxb-annotations>=2.10.3",
"jmeter-bzm-commons>=0.2.1",
"json>=20190722",
"maven-artifact>=3.8.4"
]
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ public static HashTree getNormalizedTestPlan(JMeterTreeModel model) {
* @param testPlan the HashTree object to be converted.
* @return a fully functional JMeterTreeModel instance.
* @throws IllegalUserActionException when some elements of the JMeterTreeNode are not an
* AbstractConfigGui and no instance of TestPlan subTree.
* AbstractConfigGui and no instance of TestPlan subTree.
*/
public static JMeterTreeModel convertToTreeModel(HashTree testPlan)
throws IllegalUserActionException {
Expand Down Expand Up @@ -659,9 +659,9 @@ private static JMeterTreeModel getTreeModel() {
/**
* Adds a new PostProcessor to the JMeter's tree node.
*
* @param destNode the node to add the PostProcessor to.
* @param destNode the node to add the PostProcessor to.
* @param postProcessor the PostProcessor to add.
* @param model the JMeter's tree model.
* @param model the JMeter's tree model.
*/
public static void addPostProcessorToNode(JMeterTreeNode destNode,
AbstractTestElement postProcessor,
Expand Down Expand Up @@ -868,7 +868,7 @@ public ReplayReport getReplayErrors(String originalRecordingFilepath,
* Replay the test plan from the given filepath.
*
* @param filepath The filepath of the test plan to replay. The test plan must be a JMeter test
* plan.
* plan.
* @return The result collector that was used to collect the results of the replay.
*/
@VisibleForTesting
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.jmeter.samplers.SampleResult;

/**
Expand All @@ -35,14 +36,14 @@ public class ResponseAnalyzer {
* @return The location of the argument in the response
* @see ExtractionStrategy
*/
public LocationType identifyArgumentLocation(SampleResult response, String value) {
public Pair<LocationType, String> identifyArgumentLocation(SampleResult response, String value) {
for (ExtractionStrategy strategy : strategies) {
LocationType location = strategy.identifyLocationInResponse(response, value);
if (location != LocationType.UNKNOWN) {
Pair<LocationType, String> location = strategy.identifyLocationInResponse(response, value);
if (location.getLeft() != LocationType.UNKNOWN) {
return location;
}
}
return LocationType.UNKNOWN;
return Pair.of(LocationType.UNKNOWN, "");
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,19 +133,24 @@ private static HTTPSamplerProxy parseToHttpSampler(HTTPSampleResult httpResult)
parameters = getParameterListFromQuery(httpResult);
}

for (Pair<String, String> param : parameters) {
String value = param.getValue();
String decode = JMeterElementUtils.decode(value);
if (!value.equals(decode)) {
try {
sampler.addEncodedArgument(param.getKey(), value);
} catch (IllegalArgumentException e) {
LOG.warn("Error adding argument to the sampler, {}", httpResult.getSampleLabel(), e);
e.printStackTrace();
if (isRawBody(parameters)) {
sampler.addArgument(parameters.get(0).getKey(), parameters.get(0).getValue());
sampler.setPostBodyRaw(true);
} else {
for (Pair<String, String> param : parameters) {
String value = param.getValue();
String decode = JMeterElementUtils.decode(value);
if (!value.equals(decode)) {
try {
sampler.addEncodedArgument(param.getKey(), value);
} catch (IllegalArgumentException e) {
LOG.warn("Error adding argument to the sampler, {}", httpResult.getSampleLabel(), e);
e.printStackTrace();
}
continue;
}
continue;
sampler.addArgument(param.getKey(), value);
}
sampler.addArgument(param.getKey(), value);
}

if (isJson) {
Expand All @@ -160,6 +165,10 @@ private static HTTPSamplerProxy parseToHttpSampler(HTTPSampleResult httpResult)
return sampler;
}

private static boolean isRawBody(List<Pair<String, String>> parameters) {
return parameters.size() == 1 && parameters.get(0).getKey().isEmpty();
}

private static List<Pair<String, String>> getParametersFromJsonBody(HTTPSampleResult httpResult,
ContentType contentType) {
String body = httpResult.getQueryString();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
package com.blazemeter.jmeter.correlation.core.automatic.extraction.location;

import com.blazemeter.jmeter.correlation.core.automatic.ExtractorGenerator;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.jmeter.samplers.SampleResult;

public class BodyExtractionStrategy implements ExtractionStrategy {

@Override
public LocationType identifyLocationInResponse(SampleResult response, String value) {
public Pair<LocationType, String> identifyLocationInResponse(SampleResult response,
String value) {
String bodyResponse =
response.getDataType().equals("bin") ? "" : response.getResponseDataAsString();
boolean isInBody = bodyResponse.contains(value);
String encodedValue = ExtractorGenerator.encodeValue(value);
boolean isInBodyEncoded = !isInBody && bodyResponse.contains(encodedValue);
if (isInBody || isInBodyEncoded) {
return LocationType.BODY;
}
return LocationType.UNKNOWN;
return ExtractionStrategy.getLocationAndValue(bodyResponse, value,
LocationType.BODY);
}
}
Original file line number Diff line number Diff line change
@@ -1,26 +1,21 @@
package com.blazemeter.jmeter.correlation.core.automatic.extraction.location;

import com.blazemeter.jmeter.correlation.core.automatic.ExtractorGenerator;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.jmeter.samplers.SampleResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CookieExtractionStrategy implements ExtractionStrategy {

private static final Logger LOG = LoggerFactory.getLogger(CookieExtractionStrategy.class);

@Override
public LocationType identifyLocationInResponse(SampleResult response, String value) {
public Pair<LocationType, String> identifyLocationInResponse(SampleResult response,
String value) {
String setCookiesFromHeaders = getCleanedResponseHeaders(response.getResponseHeaders());
// We get the cookies from the response
boolean isInSetCookie = setCookiesFromHeaders.contains(value);
String encodedValue = ExtractorGenerator.encodeValue(value);
boolean isInSetCookieEncoded = !isInSetCookie && setCookiesFromHeaders.contains(encodedValue);

if (isInSetCookie || isInSetCookieEncoded) {
return LocationType.COOKIE;
}

return LocationType.UNKNOWN; // Placeholder
return ExtractionStrategy.getLocationAndValue(setCookiesFromHeaders, value,
LocationType.COOKIE);
}

private static String getCleanedResponseHeaders(String responseHeadersRaw) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,24 @@
package com.blazemeter.jmeter.correlation.core.automatic.extraction.location;

import com.blazemeter.jmeter.correlation.core.automatic.replacement.method.ReplacementString;
import java.util.Arrays;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.jmeter.samplers.SampleResult;

public interface ExtractionStrategy {
LocationType identifyLocationInResponse(SampleResult response, String value);

Pair<LocationType, String> identifyLocationInResponse(SampleResult response, String value);

static Pair<LocationType, String> getLocationAndValue(String content, String value,
LocationType location) {
// Lambda need a final mutable variable, we use the string array for that
final String[] appliedValue = new String[1];
return Arrays.stream(ReplacementString.values())
.filter(r -> {
appliedValue[0] = r.applyFunction(value);
return content.contains(appliedValue[0]);
}).findFirst()
.map(string -> Pair.of(location, appliedValue[0]))
.orElseGet(() -> Pair.of(LocationType.UNKNOWN, ""));
}
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
package com.blazemeter.jmeter.correlation.core.automatic.extraction.location;

import com.blazemeter.jmeter.correlation.core.automatic.ExtractorGenerator;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.jmeter.samplers.SampleResult;

public class HeaderExtractionStrategy implements ExtractionStrategy {

@Override
public LocationType identifyLocationInResponse(SampleResult response, String value) {
public Pair<LocationType, String> identifyLocationInResponse(SampleResult response,
String value) {
// Logic to determine if the argument is in the headers
String headersWithoutSetCookies =
getCleanedResponseHeaders(String.valueOf(response.getResponseHeaders()));
boolean isInRawHeaders = headersWithoutSetCookies.contains(value);
String encodedValue = ExtractorGenerator.encodeValue(value);
boolean isInEncodedHeaders = !isInRawHeaders && headersWithoutSetCookies.contains(encodedValue);
// Return LocationType.HEADER if found, otherwise return LocationType.UNKNOWN
if (isInRawHeaders || isInEncodedHeaders) {
return LocationType.HEADER;
}
return LocationType.UNKNOWN; // Placeholder
return ExtractionStrategy.getLocationAndValue(headersWithoutSetCookies, value,
LocationType.HEADER);
}

private static String getCleanedResponseHeaders(String responseHeadersRaw) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.blazemeter.jmeter.correlation.core.automatic.JsonUtils;
import com.blazemeter.jmeter.correlation.core.replacements.CorrelationReplacement;
import com.blazemeter.jmeter.correlation.core.replacements.JsonCorrelationReplacement;
import com.blazemeter.jmeter.correlation.core.suggestions.method.ComparisonMethod.ReplacementParameters;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
Expand All @@ -18,7 +19,7 @@ public class ReplacementJsonStrategy implements ReplacementStrategy {

@Override
public CorrelationReplacement<?> generateReplacement(TestElement usage, Appearances appearance,
String referenceName) {
ReplacementParameters replacementParameters) {
if (!(usage instanceof HTTPSamplerBase)) {
return null;
}
Expand All @@ -40,8 +41,12 @@ public CorrelationReplacement<?> generateReplacement(TestElement usage, Appearan
return null;
}
path = "$" + path;
JsonCorrelationReplacement<?> replacement = new JsonCorrelationReplacement<>(path);
replacement.setVariableName(referenceName);
JsonCorrelationReplacement<?> replacement =
replacementParameters.getReplacementString() == ReplacementString.NONE
? new JsonCorrelationReplacement<>(path) : new JsonCorrelationReplacement<>(path,
replacementParameters.getReplacementString().getExpression(
replacementParameters.getRefName()), Boolean.toString(false));
replacement.setVariableName(replacementParameters.getRefName());
return replacement;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,21 @@
import com.blazemeter.jmeter.correlation.core.automatic.Appearances;
import com.blazemeter.jmeter.correlation.core.replacements.CorrelationReplacement;
import com.blazemeter.jmeter.correlation.core.replacements.RegexCorrelationReplacement;
import com.blazemeter.jmeter.correlation.core.suggestions.method.ComparisonMethod.ReplacementParameters;
import org.apache.jmeter.testelement.TestElement;

public class ReplacementRegexStrategy implements ReplacementStrategy {

@Override
public CorrelationReplacement<?> generateReplacement(TestElement usage, Appearances appearance,
String referenceName) {
ReplacementParameters replacementParameters) {
String regex = ReplacementRegex.match(appearance.getName(), appearance.getSource());
RegexCorrelationReplacement<?> replacement = new RegexCorrelationReplacement<>(regex);
replacement.setVariableName(referenceName);
RegexCorrelationReplacement<?> replacement =
replacementParameters.getReplacementString() == ReplacementString.NONE
? new RegexCorrelationReplacement<>(regex) : new RegexCorrelationReplacement<>(regex,
replacementParameters.getReplacementString()
.getExpression(replacementParameters.getRefName()), Boolean.toString(false));
replacement.setVariableName(replacementParameters.getRefName());
return replacement;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

import com.blazemeter.jmeter.correlation.core.automatic.Appearances;
import com.blazemeter.jmeter.correlation.core.replacements.CorrelationReplacement;
import com.blazemeter.jmeter.correlation.core.suggestions.method.ComparisonMethod.ReplacementParameters;
import org.apache.jmeter.testelement.TestElement;

public interface ReplacementStrategy {

CorrelationReplacement<?> generateReplacement(TestElement usage, Appearances appearance,
String referenceName);
ReplacementParameters replacementParameters);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.blazemeter.jmeter.correlation.core.automatic.replacement.method;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.function.Function;

public enum ReplacementString {
NONE("", s -> s),
URL_DECODE("__urldecode", s -> {
try {
return URLDecoder.decode(s, StandardCharsets.UTF_8.name());
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}),
URL_ENCODE("__urlencode", s -> {
try {
return URLEncoder.encode(s, StandardCharsets.UTF_8.name());
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
});

private final String replacementString;
private final Function<String, String> replacementFunction;

ReplacementString(String replacementString, Function<String, String> replacementFunction) {
this.replacementString = replacementString;
this.replacementFunction = replacementFunction;
}

public String getExpression(String refName) {
if (replacementString.isEmpty()) {
return "";
} else {
return String.format("${%s(${%s})}", this.replacementString, refName);
}
}

public String applyFunction(String value) {
return replacementFunction.apply(value);
}
}
Loading

0 comments on commit de76670

Please sign in to comment.