Skip to content

Commit

Permalink
Merge pull request #72 from Blazemeter/RELEASE_2.5.1
Browse files Browse the repository at this point in the history
Release v2.5.1
  • Loading branch information
Baraujo25 authored Jul 3, 2024
2 parents b7b1821 + 1ba0e5b commit fb004f4
Show file tree
Hide file tree
Showing 31 changed files with 494 additions and 317 deletions.
4 changes: 2 additions & 2 deletions CUSTOM_EXTENSIONS.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<h4 align="center">Correlations Recorder Plugin for JMeter</h4>
<h4 align="center">Auto Correlation Recorder Plugin for JMeter</h4>
<p align="center">Custom implementation of Correlations</p>

# Summary
Expand Down Expand Up @@ -181,4 +181,4 @@ Review these links for a further understanding of correlating concepts and examp

* [Siebel's Custom Extension explained](customizing/siebel_extension_explanations.md): an explanation of Siebel CRM’s Custom Extension.
* [Extensions and useful methods in the Flow](customizing/the_flow_explanation.md): detailed explanation of how correlation works.
* [Examples](examples): basic structure for a Correlation Extension.
* [Examples](examples): basic structure for a Correlation Extension.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Correlations Recorder Plugin for JMeter
# Auto Correlations Recorder Plugin for JMeter

![BlazeMeter Labs](docs/src/.vuepress/public/images/blazemeter-labs-logo.png)

Welcome to the Correlation Recorder's JMeter Plugin, the main and extensive documentation can be seen in [this link](https://blazemeter.github.io/CorrelationRecorder/).
Welcome to the Auto Correlation Recorder's JMeter Plugin, the main and extensive documentation can be seen in [this link](https://blazemeter.github.io/CorrelationRecorder/).

## Usage

Expand Down
6 changes: 3 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
<groupId>com.blazemeter</groupId>
<artifactId>jmeter-bzm-correlation-recorder</artifactId>
<packaging>jar</packaging>
<version>2.5</version>
<name>Correlation Recorder as JMeter plugin</name>
<description>Correlation Recorder Plugin for JMeter</description>
<version>2.5.1</version>
<name>Auto Correlation Recorder</name>
<description>Auto Correlation Recorder as JMeter Plugin</description>
<url>https://github.com/Blazemeter/CorrelationRecorder</url>

<licenses>
Expand Down
16 changes: 16 additions & 0 deletions releases.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[
{
"version": "2.5.1",
"what_is_new": "Draft template feature and performance improvements",
"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 @@ -92,7 +92,7 @@ public class CorrelationProxyControl extends ProxyControl implements
private static final String TEMPLATE_PATH = "CorrelationProxyControl.templatePath";
private static final String CORRELATION_HISTORY_ID =
"CorrelationProxyControl.correlationHistoryId";
private static final String RECORDER_NAME = "bzm - Correlation Recorder";
private static final String RECORDER_NAME = "bzm - Auto Correlation Recorder";
// we use reflection to be able to call these non visible methods and not have to re implement
// them.
private static final Method FIND_FIRST_NODE_OF_TYPE = getProxyControlMethod("findFirstNodeOfType",
Expand Down Expand Up @@ -291,7 +291,7 @@ public CorrelationRulesTestElement getCorrelationRulesTestElement() {

@Override
public synchronized void deliverSampler(HTTPSamplerBase sampler, TestElement[] testElements,
SampleResult result) {
SampleResult result) {
if (pendingProxies.containsKey(Thread.currentThread())) {
pendingProxies.get(Thread.currentThread()).update(sampler, testElements, result);
} else {
Expand Down Expand Up @@ -384,7 +384,7 @@ private void deliverCompletedProxy(PendingProxy proxy) {
HTTPSamplerBase sampler = proxy.getSampler();
if (sampler != null) {
sampler.setProperty("TestPlan.comments", "ORIGINAL_NAME USED BY CR, DON'T DELETE." +
" Prepend addition comments if necessary.;ORIGINAL_NAME=" + sampler.getName());
" Prepend addition comments if necessary.;ORIGINAL_NAME=" + sampler.getName());
}
// Ideal solution would be an invisible field or something like the following,
// but it is not being saved to testplan
Expand Down Expand Up @@ -526,13 +526,16 @@ public JMeterTreeNode findTargetControllerNode() {

@Override
public void onSaveTemplate(Builder builder) throws IOException, ConfigurationException {
Template template = builder
Template template = getTemplate(builder);
localConfiguration.saveTemplate(template);
}

public Template getTemplate(Builder builder) {
return builder
.withGroups(getGroups())
.withComponents(getCorrelationComponents())
.withResponseFilters(getResponseFilter())
.build();

localConfiguration.saveTemplate(template);
}

public List<RulesGroup> getGroups() {
Expand Down Expand Up @@ -614,7 +617,7 @@ public void onLoadTemplate(String repositoryOwner, String id, String templateVer
}

private void append(String loadedComponents, List<RulesGroup> loadedGroups,
String loadedFilters) {
String loadedFilters) {

String actualComponents = getCorrelationComponents();
setCorrelationComponents(loadedComponents.isEmpty() ? actualComponents
Expand Down Expand Up @@ -775,8 +778,8 @@ public List<String> checkURL(String id, String url) {

@Override
public boolean refreshRepositories(String localConfigurationRoute,
Consumer<Integer> setProgressConsumer,
Consumer<String> setStatusConsumer) {
Consumer<Integer> setProgressConsumer,
Consumer<String> setStatusConsumer) {
return localConfiguration.refreshRepositories(localConfigurationRoute, setProgressConsumer,
setStatusConsumer);
}
Expand Down Expand Up @@ -806,8 +809,8 @@ private List<CorrelationRule> getCorrelationRulesFromTestElement(
}

private void updateExtractorFromTestElement(CorrelationRuleTestElement e,
CorrelationRule correlationRule,
String referenceName) {
CorrelationRule correlationRule,
String referenceName) {
try {
//Only when no Extractor was selected, this method returns null
correlationRule.setCorrelationExtractor(e.getCorrelationExtractor());
Expand All @@ -818,8 +821,8 @@ private void updateExtractorFromTestElement(CorrelationRuleTestElement e,
}

private void updateReplacementFromTestElement(CorrelationRuleTestElement e,
CorrelationRule correlationRule,
String referenceName) {
CorrelationRule correlationRule,
String referenceName) {
try {
//Only when no Replacement was selected, this method returns null
correlationRule.setCorrelationReplacement(e.getCorrelationReplacement());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public CorrelationProxyControlGui() {
wizard = new CorrelationWizard();
wizard.setRepositoriesSupplier(this::getRepositories);
wizard.setAddRuleConsumer(rulesContainer.obtainRulesExporter());
wizard.setBuildTemplateProvider((builderTemplate) -> model.getTemplate(builderTemplate));
wizard.init();

rulesContainer.setOnWizardDisplayMethod(() -> wizard.displayMethodSelection());
Expand Down Expand Up @@ -138,7 +139,7 @@ private JTabbedPane findTabbedPane() {

@Override
public String getStaticLabel() {
return "bzm - Correlation Recorder";
return "bzm - Auto Correlation Recorder";
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public class CorrelationSuggestion {
private final List<SampleResult> appearances = new ArrayList<>();
private final List<TestElement> usages = new ArrayList<>();
private final List<ExtractionSuggestion> extractionSuggestions = new ArrayList<>();
private final List<String> extractionSuggestionsString = new ArrayList<>();
private final List<ReplacementSuggestion> replacementSuggestions = new ArrayList<>();
private String method = "Replay";

Expand Down Expand Up @@ -91,6 +92,7 @@ public List<TestElement> getUsages() {

public void addExtractionSuggestion(ExtractionSuggestion extractionSuggestion) {
extractionSuggestions.add(extractionSuggestion);
extractionSuggestionsString.add(extractionSuggestion.toString());
}

public void addReplacementSuggestion(ReplacementSuggestion replacementSuggestion) {
Expand All @@ -101,6 +103,10 @@ public List<ExtractionSuggestion> getExtractionSuggestions() {
return extractionSuggestions;
}

public List<String> getExtractionSuggestionsString() {
return extractionSuggestionsString;
}

public List<ReplacementSuggestion> getReplacementSuggestions() {
return replacementSuggestions;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -152,15 +151,26 @@ public List<Integer> getIndexes() {
return indexes;
}

public static List<Integer> getIndexes(String v, String text) {
if (v.isEmpty()) {
public static List<Integer> getIndexes(String search, String text) {
if (text.isEmpty()) {
return new ArrayList<>();
}

return IntStream.range(0, text.length() - v.length() + 1)
.filter(index -> text.substring(index, index + v.length()).equalsIgnoreCase(v))
.boxed()
.collect(Collectors.toList());
List<Integer> list = new ArrayList<>();
final int len = search.length();
final int max = text.length() - len;
int foundIndex = -1;
int i = 0;
while (i <= max) {
foundIndex = StringUtils.indexOf(text, search, i);
if (foundIndex != -1) {
list.add(foundIndex);
i = foundIndex;
} else {
break; // When not found, break the search by position
}
i++;
}
return list;
}

public void generateExtractors() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ public class JMeterElementUtils {
protected static final String URL_PARAM_SEPARATOR = "&";
protected static final String URL_PARAM_VALUE_SEPARATOR = "=";
private static final Logger LOG = LoggerFactory.getLogger(JMeterElementUtils.class);

private Configuration configuration;

public JMeterElementUtils() {
Expand Down Expand Up @@ -245,16 +246,18 @@ private boolean isIgnoredHeader(String key) {
}

public static boolean isJson(String value) {
boolean startJson = StringUtils.startsWithAny(
StringUtils.trim(StringUtils.truncate(value, 100)), "{", "[");
if (value.isEmpty() || !startJson) {
return false;
}
boolean isJson = true;
try {
new JSONObject(value);
} catch (JSONException ex) {
try {
new JSONArray(value);
} catch (JSONException exception) {
return false;
}
JsonPath.parse(value);
} catch (Exception ex) {
isJson = false;
}
return true;
return isJson;
}

public static boolean isXml(String xml) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,34 @@
package com.blazemeter.jmeter.correlation.core.automatic;

import com.fasterxml.jackson.databind.JsonNode;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import org.apache.commons.lang3.StringUtils;

public class JsonUtils {

public static String findPath(JsonNode node, String valueToFind) {
if (node.asText().equals(valueToFind)) {
return "";
}
String key;
Entry<String, JsonNode> entry;
JsonNode value;
String currentPath;
if (node.isObject()) {
Iterator<Entry<String, JsonNode>> it = node.fields();
while (it.hasNext()) {
Entry<String, JsonNode> entry = it.next();
String key = handleSpecialCharactersInJsonKey(entry.getKey());
JsonNode value = entry.getValue();
String currentPath = findPath(value, valueToFind);
entry = it.next();
key = handleSpecialCharactersInJsonKey(entry.getKey());
value = entry.getValue();
currentPath = findPath(value, valueToFind);
if (currentPath != null) {
return "." + key + (currentPath);
}
}
} else if (node.isArray()) {
for (int i = 0; i < node.size(); i++) {
String currentPath = findPath(node.get(i), valueToFind);
currentPath = findPath(node.get(i), valueToFind);
if (currentPath != null) {
return (currentPath.startsWith(".") ? "." : "..") + currentPath;
}
Expand All @@ -35,9 +38,7 @@ public static String findPath(JsonNode node, String valueToFind) {
}

private static String handleSpecialCharactersInJsonKey(String key) {
List<String> specialCharacters = Arrays.asList(".", "$", "@", "[", "]", "?", "(", ")");
boolean containJsonPathExpression = specialCharacters.stream().anyMatch(key::contains);
if (containJsonPathExpression) {
if (StringUtils.containsAny(key, ".$@[]?()")) {
return "['" + key + "']";
}
return key;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.blazemeter.jmeter.correlation.core.automatic.extraction.location.HeaderExtractionStrategy;
import com.blazemeter.jmeter.correlation.core.automatic.extraction.location.LocationType;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import org.apache.jmeter.samplers.SampleResult;

Expand All @@ -17,16 +18,20 @@
public class ResponseAnalyzer {

private final List<ExtractionStrategy> strategies = Arrays.asList(
new BodyExtractionStrategy(),
new HeaderExtractionStrategy(),
new CookieExtractionStrategy()
new CookieExtractionStrategy(),
new BodyExtractionStrategy()
);

private HashMap<String, StructureType> resposeStructureTypeCache =
new HashMap<String, StructureType>();

/**
* Identifies the location of an argument in a response.
* Uses a list of {@link ExtractionStrategy} to identify the location.
*
* @param response The response to analyze
* @param value The value to search in the response
* @param value The value to search in the response
* @return The location of the argument in the response
* @see ExtractionStrategy
*/
Expand All @@ -46,25 +51,30 @@ public LocationType identifyArgumentLocation(SampleResult response, String value
* StructureType#XML}, {@link StructureType#RAW_TEXT} or {@link StructureType#UNKNOWN}.
* This is particularly useful when the argument is in the body of the response and we need to
* know the structure of the body to generate the extractor.
* @param response The response to analyze
*
* @param response The response to analyze
* @param locationType The location of the argument in the response
* @return The structure of the argument in the response
* @see StructureType
*/
public StructureType identifyStructureType(SampleResult response, LocationType locationType) {
if (locationType == LocationType.HEADER || locationType == LocationType.COOKIE) {
return StructureType.RAW_TEXT;
} else if (locationType == LocationType.BODY) {
if (JMeterElementUtils.isJson(response.getResponseDataAsString())) {
return StructureType.JSON;
}

if (JMeterElementUtils.isXml(response.getResponseDataAsString())) {
return StructureType.XML;
StructureType structureType = StructureType.UNKNOWN;
String responseKey = response.getSampleLabel() + ":" + locationType;
if (resposeStructureTypeCache.containsKey(responseKey)) {
return resposeStructureTypeCache.get(responseKey);
} else {
if (locationType == LocationType.HEADER || locationType == LocationType.COOKIE) {
return StructureType.RAW_TEXT;
} else if (locationType == LocationType.BODY) {
if (JMeterElementUtils.isJson(response.getResponseDataAsString())) {
structureType = StructureType.JSON;
} else {
structureType = StructureType.RAW_TEXT;
}
}

return StructureType.RAW_TEXT;
}
return StructureType.UNKNOWN;
resposeStructureTypeCache.put(responseKey, structureType);
return structureType;
}

}
Loading

0 comments on commit fb004f4

Please sign in to comment.