correlationRules = new HashMap<>();
for (ExtractionSuggestion extractionSuggestion : extractionSuggestions) {
//TODO: We need to stop using a single Extractor and use the list
if (extractionSuggestion.getExtractor() != null) {
CorrelationRule rule = new CorrelationRule(extractionSuggestion.getName(),
extractionSuggestion.getExtractor(), null);
- correlationRules.add(rule);
- uniqueRules.add(rule);
+ if (correlationRules.containsKey(rule)) {
+ duplicateRules.add(rule);
+ } else {
+ correlationRules.put(rule, extractionSuggestion.getSequence());
+ }
}
for (CorrelationExtractor> extractor: extractionSuggestion.getExtractors()) {
CorrelationRule rule = new CorrelationRule(extractionSuggestion.getName(), extractor, null);
- correlationRules.add(rule);
- uniqueRules.add(rule);
+ if (correlationRules.containsKey(rule)) {
+ duplicateRules.add(rule);
+ } else {
+ correlationRules.put(rule, extractionSuggestion.getSequence());
+ }
}
}
for (ReplacementSuggestion replacementSuggestion : replacementSuggestions) {
CorrelationRule rule = new CorrelationRule(replacementSuggestion.getName(), null,
replacementSuggestion.getReplacementSuggestion());
- correlationRules.add(rule);
- uniqueRules.add(rule);
+ if (correlationRules.containsKey(rule)) {
+ duplicateRules.add(rule);
+ } else {
+ correlationRules.put(rule, replacementSuggestion.getSequence());
+ }
}
- if (correlationRules.size() != uniqueRules.size()) {
+ if (!duplicateRules.isEmpty()) {
LOG.warn("There are duplicated rules in the suggestion for parameter {}", paramName);
}
- return new ArrayList<>(uniqueRules);
+ return correlationRules;
}
}
diff --git a/src/main/java/com/blazemeter/jmeter/correlation/core/automatic/ExtractionSuggestion.java b/src/main/java/com/blazemeter/jmeter/correlation/core/automatic/ExtractionSuggestion.java
index 09e1036..6ef45f1 100644
--- a/src/main/java/com/blazemeter/jmeter/correlation/core/automatic/ExtractionSuggestion.java
+++ b/src/main/java/com/blazemeter/jmeter/correlation/core/automatic/ExtractionSuggestion.java
@@ -19,6 +19,7 @@ public class ExtractionSuggestion {
// This suggestion comes from the analysis of a sample result?
private boolean comesFromSampleResult = true;
private HTTPSamplerBase sampler;
+ private int sequence = 0;
public ExtractionSuggestion(CorrelationExtractor> extractors, SampleResult sampleResult) {
this.extractors.add(extractors);
@@ -47,6 +48,14 @@ public void setSampleResult(SampleResult sampleResult) {
this.sampleResult = sampleResult;
}
+ public int getSequence() {
+ return this.sequence;
+ }
+
+ public void setSequence(int sequence) {
+ this.sequence = sequence;
+ }
+
public String getValue() {
return value;
}
@@ -98,4 +107,5 @@ public String toString() {
: ", httpSamplerBase=" + sampler.getName())
+ ", \nextractor=" + extractor + '}';
}
+
}
diff --git a/src/main/java/com/blazemeter/jmeter/correlation/core/automatic/JMeterElementUtils.java b/src/main/java/com/blazemeter/jmeter/correlation/core/automatic/JMeterElementUtils.java
index f92c40d..dc23350 100644
--- a/src/main/java/com/blazemeter/jmeter/correlation/core/automatic/JMeterElementUtils.java
+++ b/src/main/java/com/blazemeter/jmeter/correlation/core/automatic/JMeterElementUtils.java
@@ -145,8 +145,7 @@ public static String getRecordingFilePath() {
}
}
- @VisibleForTesting
- protected static void convertSubTree(HashTree tree) {
+ public static void convertSubTree(HashTree tree) {
for (Object o : new ArrayList<>(tree.list())) {
JMeterTreeNode item = (JMeterTreeNode) o;
convertSubTree(tree.getTree(item));
@@ -208,7 +207,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 {
@@ -652,16 +651,16 @@ public static void addNode(JMeterTreeNode parent, JMeterTreeNode node) {
}
}
- private static JMeterTreeModel getTreeModel() {
+ public static JMeterTreeModel getTreeModel() {
return GuiPackage.getInstance().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,
@@ -868,7 +867,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
diff --git a/src/main/java/com/blazemeter/jmeter/correlation/core/automatic/ReplacementSuggestion.java b/src/main/java/com/blazemeter/jmeter/correlation/core/automatic/ReplacementSuggestion.java
index 2bfa368..3f6a788 100644
--- a/src/main/java/com/blazemeter/jmeter/correlation/core/automatic/ReplacementSuggestion.java
+++ b/src/main/java/com/blazemeter/jmeter/correlation/core/automatic/ReplacementSuggestion.java
@@ -9,6 +9,7 @@ public class ReplacementSuggestion {
private String source;
private String value;
private String name;
+ private int sequence = 0;
public ReplacementSuggestion(CorrelationReplacement> replacementSuggestion,
TestElement usage) {
@@ -32,6 +33,14 @@ public void setSource(String source) {
this.source = source;
}
+ public int getSequence() {
+ return this.sequence;
+ }
+
+ public void setSequence(int sequence) {
+ this.sequence = sequence;
+ }
+
public String getValue() {
return value;
}
@@ -58,4 +67,5 @@ public String toString() {
", name='" + name + '\'' +
'}';
}
+
}
diff --git a/src/main/java/com/blazemeter/jmeter/correlation/core/automatic/WaitingDialog.java b/src/main/java/com/blazemeter/jmeter/correlation/core/automatic/WaitingDialog.java
new file mode 100644
index 0000000..b81d2fc
--- /dev/null
+++ b/src/main/java/com/blazemeter/jmeter/correlation/core/automatic/WaitingDialog.java
@@ -0,0 +1,102 @@
+package com.blazemeter.jmeter.correlation.core.automatic;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Dialog;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.Toolkit;
+import java.awt.Window;
+import java.awt.event.WindowAdapter;
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JProgressBar;
+import javax.swing.SwingConstants;
+import javax.swing.border.EmptyBorder;
+
+public class WaitingDialog {
+
+ protected static JDialog runDialog;
+ private static JLabel label;
+ private static Window parent;
+
+ private static JDialog makeWaitingFrame(String title, String message, Component component) {
+ parent = getWindowFromComponent(component);
+ JDialog runDialog = new JDialog(parent, title);
+ runDialog.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+ runDialog.setResizable(true);
+ runDialog.add(makeProgressBar(), BorderLayout.SOUTH);
+ label = makeLabel(message);
+ runDialog.add(label);
+ runDialog.pack();
+ if (parent != null) {
+ runDialog.setLocationRelativeTo(parent);
+ } else {
+ Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
+ // calculate the new location of the window
+ int x = (dim.width - runDialog.getSize().width) / 2;
+ int y = (dim.height - runDialog.getSize().height) / 2;
+ runDialog.setLocation(x, y);
+ }
+ runDialog.setAutoRequestFocus(true);
+ return runDialog;
+ }
+
+ private static Window getWindowFromComponent(Component component) {
+ if (component == null) {
+ return null;
+ }
+ if (component.isVisible() && (component instanceof Frame || component instanceof Dialog)) {
+ return (Window) component;
+ }
+ return getWindowFromComponent(component.getParent());
+ }
+
+ public static JProgressBar makeProgressBar() {
+ JProgressBar progressBar = new JProgressBar();
+ progressBar.setIndeterminate(true);
+ return progressBar;
+ }
+
+ public static JLabel makeLabel(String message) {
+ JLabel label = new JLabel(message, SwingConstants.CENTER);
+ label.setBorder(new EmptyBorder(25, 50, 25, 50));
+ return label;
+ }
+
+ public static void displayWaitingScreen(String title, String message, Component component) {
+ disposeWaitingDialog();
+ runDialog = makeWaitingFrame(title, message, component);
+ runDialog.setVisible(true);
+ runDialog.setAlwaysOnTop(true);
+ runDialog.toFront();
+ }
+
+ public static void displayWaitingScreen(String title, String message) {
+ displayWaitingScreen(title, message, null);
+ }
+
+ public static void disposeWaitingDialog() {
+ if (runDialog != null) {
+ runDialog.dispose();
+ runDialog.setVisible(false);
+ runDialog.setAlwaysOnTop(false);
+ }
+ }
+
+ public static void addWindowAdapter(WindowAdapter adapter) {
+ runDialog.addWindowListener(adapter);
+ }
+
+ public static void changeWaitingMessage(String message) {
+ if (label != null && runDialog != null) {
+ label.setText(message);
+ runDialog.repaint();
+ runDialog.pack();
+ if (parent != null) {
+ runDialog.setLocationRelativeTo(parent);
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/blazemeter/jmeter/correlation/core/extractors/CorrelationExtractor.java b/src/main/java/com/blazemeter/jmeter/correlation/core/extractors/CorrelationExtractor.java
index 00a0372..966586a 100644
--- a/src/main/java/com/blazemeter/jmeter/correlation/core/extractors/CorrelationExtractor.java
+++ b/src/main/java/com/blazemeter/jmeter/correlation/core/extractors/CorrelationExtractor.java
@@ -32,8 +32,8 @@
*
* Contains all the methods from loading, saving and processing responses from the server.
*
- *
For a more detailed explanation on Correlation Extractors, their usages and methods, please
- * read the
+ *
For a more detailed explanation on Correlation Extractors, their usages and methods, please
+ * read the
* readme.
*
*
Along side {@link com.blazemeter.jmeter.correlation.core.replacements.CorrelationReplacement}
@@ -182,8 +182,8 @@ protected void clearJMeterVariables(JMeterVariables vars) {
* of the mode of the recording (i.e. whether we are recording or doing
* static analysis).
*/
- protected void analyze(String value, Object affectedElement, String varName) {
- AnalysisReporter.report(this, value, affectedElement, varName, target.name());
+ protected void analyze(String value, Object affectedElement) {
+ AnalysisReporter.report(this, affectedElement, target.name(), value);
}
}
diff --git a/src/main/java/com/blazemeter/jmeter/correlation/core/extractors/JsonCorrelationExtractor.java b/src/main/java/com/blazemeter/jmeter/correlation/core/extractors/JsonCorrelationExtractor.java
index 15e2ba9..83181bc 100644
--- a/src/main/java/com/blazemeter/jmeter/correlation/core/extractors/JsonCorrelationExtractor.java
+++ b/src/main/java/com/blazemeter/jmeter/correlation/core/extractors/JsonCorrelationExtractor.java
@@ -199,7 +199,7 @@ public void process(HTTPSamplerBase sampler, List children, SampleR
}
}
if (matchedValue != null) {
- analyze(matchedValue, sampler, variableName);
+ analyze(matchedValue, sampler);
addVarAndChildPostProcessor(matchedValue, matchedVariableChildPP,
createPostProcessor(matchedVariablePP, matchedMatchNr));
}
diff --git a/src/main/java/com/blazemeter/jmeter/correlation/core/extractors/RegexCorrelationExtractor.java b/src/main/java/com/blazemeter/jmeter/correlation/core/extractors/RegexCorrelationExtractor.java
index deb7b30..883e968 100644
--- a/src/main/java/com/blazemeter/jmeter/correlation/core/extractors/RegexCorrelationExtractor.java
+++ b/src/main/java/com/blazemeter/jmeter/correlation/core/extractors/RegexCorrelationExtractor.java
@@ -211,7 +211,7 @@ public void process(HTTPSamplerBase sampler, List children, SampleR
String match = regexMatcher.findMatch(field, matchNr);
String varName = multiValued ? generateVariableName() : variableName;
if (match != null && !match.equals(vars.get(varName))) {
- analyze(match, sampler, variableName);
+ analyze(match, sampler);
addVarAndChildPostProcessor(match, varName,
createPostProcessor(varName, matchNr));
}
@@ -220,7 +220,7 @@ public void process(HTTPSamplerBase sampler, List children, SampleR
if (matches.size() == 1) {
String varName = multiValued ? generateVariableName() : variableName;
String match = matches.get(0);
- analyze(match, sampler, variableName);
+ analyze(match, sampler);
addVarAndChildPostProcessor(match, varName,
createPostProcessor(varName, 1));
} else if (matches.size() > 1) {
@@ -229,7 +229,7 @@ public void process(HTTPSamplerBase sampler, List children, SampleR
}
String value = String.valueOf(matches.size());
String varName = multiValued ? generateVariableName() : variableName;
- analyze(value, sampler, variableName);
+ analyze(value, sampler);
addVarAndChildPostProcessor(value,
varName + "_matchNr", createPostProcessor(varName, matchNr));
diff --git a/src/main/java/com/blazemeter/jmeter/correlation/core/replacements/CorrelationReplacement.java b/src/main/java/com/blazemeter/jmeter/correlation/core/replacements/CorrelationReplacement.java
index a0f9d8d..4e8cc34 100644
--- a/src/main/java/com/blazemeter/jmeter/correlation/core/replacements/CorrelationReplacement.java
+++ b/src/main/java/com/blazemeter/jmeter/correlation/core/replacements/CorrelationReplacement.java
@@ -124,7 +124,7 @@ public void updateTestElem(CorrelationRuleTestElement testElem) {
* @param vars stored variables shared between requests during recording
*/
public void process(HTTPSamplerBase sampler, List children, SampleResult result,
- JMeterVariables vars) {
+ JMeterVariables vars) {
replaceTestElementProperties(sampler, vars);
for (TestElement child : children) {
if (child instanceof ConfigTestElement) {
@@ -148,20 +148,25 @@ public void process(HTTPSamplerBase sampler, List children, SampleR
private void replaceTestElementProperties(TestElement el, JMeterVariables vars) {
List props = new LinkedList<>();
PropertyIterator propertyIterator = el.propertyIterator();
+ boolean propChanged = false;
while (propertyIterator.hasNext()) {
- JMeterProperty val = replaceProperty(propertyIterator.next(), vars);
+ JMeterProperty orgProp = propertyIterator.next();
+ JMeterProperty val = replaceProperty(orgProp, vars);
+ if (!val.equals(orgProp) && !propChanged) {
+ propChanged = true;
+ }
props.add(val);
}
- el.clear();
- for (JMeterProperty jmp : props) {
- el.setProperty(jmp);
+ // Only when some property change
+ if (propChanged) {
+ el.clear();
+ for (JMeterProperty jmp : props) {
+ el.setProperty(jmp);
+ }
}
}
private JMeterProperty replaceProperty(JMeterProperty prop, JMeterVariables vars) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("About to replace in property of type: {}: {}", prop.getClass(), prop);
- }
if (prop instanceof StringProperty) {
// Must not convert TestElement.gui_class etc
if (!prop.getName().equals(TestElement.GUI_CLASS)
@@ -184,18 +189,22 @@ private JMeterProperty replaceProperty(JMeterProperty prop, JMeterVariables vars
MultiProperty multiVal = (MultiProperty) prop;
PropertyIterator propertyIterator = multiVal.iterator();
Collection newValues = new ArrayList<>();
+ boolean propChanged = false;
while (propertyIterator.hasNext()) {
- JMeterProperty val = replaceProperty(propertyIterator.next(), vars);
+ JMeterProperty orgProp = propertyIterator.next();
+ JMeterProperty val = replaceProperty(orgProp, vars);
+ if (!orgProp.equals(val) && !propChanged) {
+ propChanged = true;
+ }
newValues.add(val);
}
- multiVal.clear();
- for (JMeterProperty jmp : newValues) {
- multiVal.addProperty(jmp);
+ if (propChanged) {
+ multiVal.clear();
+ for (JMeterProperty jmp : newValues) {
+ multiVal.addProperty(jmp);
+ }
}
- } else {
- LOG.debug("Won't replace {}", prop);
}
- LOG.debug("CorrelationReplacement result: {}", prop);
return prop;
}
@@ -204,7 +213,12 @@ private JMeterProperty replaceSimpleProp(JMeterProperty prop, JMeterVariables va
if (input == null) {
return prop;
}
- return new StringProperty(prop.getName(), replaceString(input, vars));
+ String newImput = replaceString(input, vars);
+ if (newImput.equals(input)) {
+ return prop;
+ } else {
+ return new StringProperty(prop.getName(), newImput);
+ }
}
/**
@@ -223,19 +237,25 @@ private void replaceArgument(Argument arg, JMeterVariables vars) {
if (input == null) {
return;
}
+ String argName = arg.getName();
/*
To normalize the replacement on arguments for HTTP requests, we include the argument name and
'=' to the input, apply the replacement logic, and remove it afterward. This doesn't applies
when the argument has no name (eg: Data Body is a JSON/XML).
*/
- String prefix = arg.getName().isEmpty() ? "" : arg.getName() + "=";
- input = replaceString(prefix + arg.getValue(), vars).replace(prefix, "");
- arg.setValue(input);
+ String prefix = argName.isEmpty() ? "" : argName + "=";
+ String newInput = replaceString(prefix + input, vars).replace(prefix, "");
+ if (!newInput.equals(input)) {
+ arg.setValue(newInput);
+ }
/*
In order to comply backward compatibility from <=v2.5 keys (arg name) is also processed by
the replacement
*/
- arg.setName(replaceString(arg.getName(), vars));
+ String newName = replaceString(argName, vars);
+ if (!newName.equals(argName)) {
+ arg.setName(newName);
+ }
}
private void replaceHeader(Header header, JMeterVariables vars) {
@@ -243,14 +263,20 @@ private void replaceHeader(Header header, JMeterVariables vars) {
if (input == null) {
return;
}
- input = replaceString(header.getName() + ": " + header.getValue(), vars)
- .replace(header.getName() + ": ", "");
- header.setValue(input);
+ String headName = header.getName();
+ String newInput = replaceString(headName + ": " + input, vars)
+ .replace(headName + ": ", "");
+ if (!newInput.equals(input)) {
+ header.setValue(newInput);
+ }
/*
In order to comply backward compatibility from <=v2.5 keys (header name) is also processed by
the replacement
*/
- header.setName(replaceString(header.getName(), vars));
+ String newName = replaceString(headName, vars);
+ if (!newName.equals(headName)) {
+ header.setName(newName);
+ }
}
@Override
@@ -286,7 +312,6 @@ Function replaceExpressionProvider() {
String computeStringReplacement(String varName) {
String rawReplacementString = buildReplacementStringForMultivalued(varName);
String computed = expressionEvaluator.apply(rawReplacementString);
- LOG.debug("Result of {} was {}", rawReplacementString, computed);
return computed;
}
diff --git a/src/main/java/com/blazemeter/jmeter/correlation/core/replacements/JsonCorrelationReplacement.java b/src/main/java/com/blazemeter/jmeter/correlation/core/replacements/JsonCorrelationReplacement.java
index ea446ab..edbbe30 100644
--- a/src/main/java/com/blazemeter/jmeter/correlation/core/replacements/JsonCorrelationReplacement.java
+++ b/src/main/java/com/blazemeter/jmeter/correlation/core/replacements/JsonCorrelationReplacement.java
@@ -179,7 +179,7 @@ protected String replaceString(String input, JMeterVariables vars) {
}
private void analysis(String literalMatched, String currentVariableName) {
- AnalysisReporter.report(this, literalMatched, currentSampler, currentVariableName);
+ AnalysisReporter.report(this, currentSampler, currentVariableName, literalMatched);
}
private String searchVariable(JMeterVariables vars, String value, String replacementString) {
diff --git a/src/main/java/com/blazemeter/jmeter/correlation/core/replacements/RegexCorrelationReplacement.java b/src/main/java/com/blazemeter/jmeter/correlation/core/replacements/RegexCorrelationReplacement.java
index edf981b..0320495 100644
--- a/src/main/java/com/blazemeter/jmeter/correlation/core/replacements/RegexCorrelationReplacement.java
+++ b/src/main/java/com/blazemeter/jmeter/correlation/core/replacements/RegexCorrelationReplacement.java
@@ -340,7 +340,8 @@ public void update(CorrelationRuleTestElement testElem) {
}
protected void analysis(String literalMatched, String currentVariableName) {
- AnalysisReporter.report(this, literalMatched, currentSampler, currentVariableName);
+ AnalysisReporter.report(this, currentSampler, currentVariableName, literalMatched
+ );
}
@Override
diff --git a/src/main/java/com/blazemeter/jmeter/correlation/core/suggestions/InterruptibleWorkerAgreement.java b/src/main/java/com/blazemeter/jmeter/correlation/core/suggestions/InterruptibleWorkerAgreement.java
new file mode 100644
index 0000000..013cceb
--- /dev/null
+++ b/src/main/java/com/blazemeter/jmeter/correlation/core/suggestions/InterruptibleWorkerAgreement.java
@@ -0,0 +1,29 @@
+package com.blazemeter.jmeter.correlation.core.suggestions;
+
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+public interface InterruptibleWorkerAgreement extends PropertyChangeListener {
+
+ String ON_FAILURE_ENDED_PROPERTY = "END_BUSY_WAIT";
+
+ default WindowAdapter getWindowAdapter() {
+ return new WindowAdapter() {
+ @Override
+ public void windowClosed(WindowEvent e) {
+ onInterruption();
+ }
+ };
+ }
+
+ void onInterruption();
+
+ @Override
+ default void propertyChange(PropertyChangeEvent evt) {
+ onWorkerPropertyChange(evt);
+ }
+
+ void onWorkerPropertyChange(PropertyChangeEvent evt);
+}
diff --git a/src/main/java/com/blazemeter/jmeter/correlation/core/suggestions/SuggestionGenerator.java b/src/main/java/com/blazemeter/jmeter/correlation/core/suggestions/SuggestionGenerator.java
index 3cec174..24a2275 100644
--- a/src/main/java/com/blazemeter/jmeter/correlation/core/suggestions/SuggestionGenerator.java
+++ b/src/main/java/com/blazemeter/jmeter/correlation/core/suggestions/SuggestionGenerator.java
@@ -7,15 +7,17 @@
import com.blazemeter.jmeter.correlation.core.suggestions.method.CorrelationMethod;
import com.helger.commons.annotation.VisibleForTesting;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/*
-* Reminder: Maybe we can call this "SuggestionsHandler" or "SuggestionsManager"
-* to be able to handle both the generation and the application of the suggestions.
-* */
+ * Reminder: Maybe we can call this "SuggestionsHandler" or "SuggestionsManager"
+ * to be able to handle both the generation and the application of the suggestions.
+ * */
public class SuggestionGenerator {
+
private static final Logger LOG = LoggerFactory.getLogger(SuggestionGenerator.class);
private static SuggestionGenerator instance;
private CorrelationMethod correlationMethod;
@@ -62,16 +64,12 @@ public List generateSuggestions(CorrelationContext contex
}
@VisibleForTesting
- public List parseToRules(List suggestions) {
- List rules = new ArrayList<>();
+ public HashMap parseToRules(List suggestions) {
+ HashMap rules = new HashMap<>();
for (CorrelationSuggestion suggestion : suggestions) {
- List correlationRules = suggestion.toCorrelationRules();
- rules.addAll(correlationRules);
+ HashMap correlationRules = suggestion.toCorrelationRules();
+ rules.putAll(correlationRules);
}
return rules;
}
-
- public void applySuggestions(List suggestions) {
- correlationMethod.applySuggestions(suggestions);
- }
}
diff --git a/src/main/java/com/blazemeter/jmeter/correlation/core/suggestions/SuggestionsApplianceWorker.java b/src/main/java/com/blazemeter/jmeter/correlation/core/suggestions/SuggestionsApplianceWorker.java
new file mode 100644
index 0000000..5d2acda
--- /dev/null
+++ b/src/main/java/com/blazemeter/jmeter/correlation/core/suggestions/SuggestionsApplianceWorker.java
@@ -0,0 +1,180 @@
+package com.blazemeter.jmeter.correlation.core.suggestions;
+
+import com.blazemeter.jmeter.correlation.core.CorrelationRule;
+import com.blazemeter.jmeter.correlation.core.RulesGroup;
+import com.blazemeter.jmeter.correlation.core.automatic.CorrelationSuggestion;
+import com.blazemeter.jmeter.correlation.core.automatic.JMeterElementUtils;
+import com.blazemeter.jmeter.correlation.core.automatic.WaitingDialog;
+import com.blazemeter.jmeter.correlation.core.suggestions.context.AnalysisContext;
+import com.blazemeter.jmeter.correlation.core.suggestions.method.AnalysisMethod;
+import com.blazemeter.jmeter.correlation.gui.CorrelationComponentsRegistry;
+import com.blazemeter.jmeter.correlation.gui.automatic.CorrelationSuggestionsPanel;
+import java.beans.PropertyChangeEvent;
+import java.util.List;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.function.Consumer;
+import javax.swing.JOptionPane;
+import javax.swing.SwingWorker;
+import javax.swing.Timer;
+import org.apache.jmeter.exceptions.IllegalUserActionException;
+import org.apache.jmeter.gui.GuiPackage;
+import org.apache.jorphan.collections.HashTree;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SuggestionsApplianceWorker extends SwingWorker implements
+ InterruptibleWorkerAgreement {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SuggestionsApplianceWorker.class);
+ private final List suggestions;
+ private final CorrelationSuggestionsPanel suggestionPanel;
+ private final String recordingTracePath;
+ private final Consumer historyLogStep;
+ private boolean isWorkerRunning;
+ private Timer timer;
+ private HashTree recoveryTestPlan;
+
+ public SuggestionsApplianceWorker(CorrelationSuggestionsPanel panel) {
+ this.suggestions = panel.exportSelectedSuggestions();
+ this.suggestionPanel = panel;
+ this.recordingTracePath = panel.getRecordingTraceSupplier();
+ this.historyLogStep = panel.getHistoryLogStep();
+ this.addPropertyChangeListener(this);
+ }
+
+ @Override
+ protected void done() {
+ WaitingDialog.disposeWaitingDialog();
+ suggestionPanel.hideWizard();
+ }
+
+ @Override
+ protected Void doInBackground() {
+ Void result = null;
+ WaitingDialog.displayWaitingScreen("Applying suggestions",
+ "We are applying the suggestions, please wait...", suggestionPanel);
+ WaitingDialog.addWindowAdapter(getWindowAdapter());
+ saveTestPlanSnapShotForRecoveryPlan();
+ isWorkerRunning = true;
+ suggestions.clear();
+ suggestions.addAll(suggestionPanel.exportSelectedSuggestions());
+ if (suggestions.isEmpty()) {
+ isWorkerRunning = false;
+ WaitingDialog.disposeWaitingDialog();
+ JOptionPane.showMessageDialog(suggestionPanel,
+ "No suggestions selected. Please select at least one suggestion to " + "apply",
+ "No suggestions selected", JOptionPane.INFORMATION_MESSAGE);
+ return result;
+ }
+
+ historyLogStep.accept("(Save) Before apply suggestions");
+ applySuggestions();
+ historyLogStep.accept("(Save) After apply suggestions");
+
+ isWorkerRunning = false;
+ WaitingDialog.disposeWaitingDialog();
+
+ JOptionPane.showMessageDialog(suggestionPanel,
+ "The suggestions were applied successfully to your Test Plan." +
+ System.lineSeparator() + "Please review the changes and, when you are ready, " +
+ "replay to review the results.");
+
+ JMeterElementUtils.refreshJMeter();
+
+ return result;
+ }
+
+ private void saveTestPlanSnapShotForRecoveryPlan() {
+ this.recoveryTestPlan = JMeterElementUtils.getTreeModel().getTestPlan();
+ }
+
+ private void applySuggestions() {
+ /* When a set of suggestions is presented to be applied to the test as form of
+ CorrelationRules it does not matter where were generated such suggestions: Analysis Method
+ (based on template) or Comparison Method (automatic generated). It will always use the
+ Analysis Method to apply them.
+ * */
+ AnalysisContext context = buildAnalysisContext();
+ AnalysisMethod analysisMethod = new AnalysisMethod(context);
+ List rulesGroups = getRulesGroups();
+ analysisMethod.runAnalysis(rulesGroups, true);
+ }
+
+ private @NotNull AnalysisContext buildAnalysisContext() {
+ AnalysisContext context = new AnalysisContext();
+ context.setRecordingTraceFilePath(recordingTracePath);
+ context.setRecordingTestPlan(JMeterElementUtils.getNormalizedTestPlan());
+ context.setRegistry(CorrelationComponentsRegistry.getInstance());
+ return context;
+ }
+
+ private @NotNull List getRulesGroups() {
+ List correlationRules = SuggestionsUtils.parseSuggestionsToRules(suggestions);
+ return SuggestionsUtils.parseToGroup(correlationRules);
+ }
+
+ @Override
+ public void onInterruption() {
+ if (!isWorkerRunning) {
+ return;
+ }
+ SuggestionsApplianceWorker.this.cancel(true);
+ suggestionPanel.hideWizard();
+ WaitingDialog.displayWaitingScreen("Abort operation",
+ "Waiting for suggestions application to be terminated",
+ SuggestionsApplianceWorker.this.suggestionPanel);
+ timer = new Timer(3000, event -> {
+ if (SuggestionsApplianceWorker.this.isWorkerRunning) {
+ timer.restart();
+ } else {
+ WaitingDialog.disposeWaitingDialog();
+ timer.stop();
+ JOptionPane.showMessageDialog(SuggestionsApplianceWorker.this.suggestionPanel,
+ "Suggestion application stopped");
+ SuggestionsApplianceWorker.this.firePropertyChange(ON_FAILURE_ENDED_PROPERTY,
+ false,
+ true);
+ }
+ });
+ timer.setRepeats(false);
+ timer.start();
+ }
+
+ @Override
+ public void onWorkerPropertyChange(PropertyChangeEvent evt) {
+ if (evt.getPropertyName().equals("state") && evt.getNewValue().equals(StateValue.DONE)
+ && isDone()) {
+ try {
+ Void ignore = this.get();
+ } catch (InterruptedException | ExecutionException e) {
+ WaitingDialog.disposeWaitingDialog();
+ JOptionPane.showMessageDialog(suggestionPanel,
+ "There was an unexpected error while applying suggestions");
+ LOG.error("Error while applying suggestions", e);
+ Thread.currentThread().interrupt();
+ } catch (CancellationException e) {
+ // Exception captured and ignored since this case is handled by the worker itself as
+ // recovery plan when user cancels the generation of suggestions see below recovery plan
+ // when ON_FAILURE_ENDED_PROPERTY
+ }
+ } else if (evt.getPropertyName().equals(ON_FAILURE_ENDED_PROPERTY)) {
+ executeRecoveryPlan();
+ }
+
+ }
+
+ private void executeRecoveryPlan() {
+ JOptionPane.showMessageDialog(suggestionPanel, "Since application of suggestions was "
+ + "interrupted Test Plan will be recovered as it was before appliance");
+ GuiPackage guiPackage = GuiPackage.getInstance();
+ guiPackage.clearTestPlan();
+ try {
+ JMeterElementUtils.convertSubTree(recoveryTestPlan);
+ guiPackage.addSubTree(recoveryTestPlan);
+ } catch (IllegalUserActionException e) {
+ LOG.error("Error while attempting to recover TestPlan to before suggestions were applied", e);
+ }
+ }
+}
diff --git a/src/main/java/com/blazemeter/jmeter/correlation/core/suggestions/SuggestionsUtils.java b/src/main/java/com/blazemeter/jmeter/correlation/core/suggestions/SuggestionsUtils.java
index ce7be74..cc14aa2 100644
--- a/src/main/java/com/blazemeter/jmeter/correlation/core/suggestions/SuggestionsUtils.java
+++ b/src/main/java/com/blazemeter/jmeter/correlation/core/suggestions/SuggestionsUtils.java
@@ -4,7 +4,10 @@
import com.blazemeter.jmeter.correlation.core.RulesGroup;
import com.blazemeter.jmeter.correlation.core.automatic.CorrelationSuggestion;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
/**
* This is a utility class that provides methods to parse CorrelationSuggestion and
@@ -26,12 +29,13 @@ public class SuggestionsUtils {
*/
public static List parseSuggestionsToRules(
List suggestions) {
- List correlationRules = new ArrayList<>();
+ HashMap correlationRules = new HashMap<>();
for (CorrelationSuggestion suggestion : suggestions) {
- List rules = suggestion.toCorrelationRules();
- correlationRules.addAll(rules);
+ HashMap rules = suggestion.toCorrelationRules();
+ correlationRules.putAll(rules);
}
- return correlationRules;
+ // Sort the hashmap based on the sequence and return as a list
+ return sortRulesSequence(correlationRules);
}
/**
@@ -53,4 +57,27 @@ public static List parseToGroup(List rules) {
rulesGroups.add(group);
return rulesGroups;
}
+
+ /**
+ * Sorts a given {@code HashMap} of {@code CorrelationRule} objects based on their associated
+ * sequence values and returns the rules as a list in ascending order of the sequence.
+ *
+ * The method processes the entries of the provided {@code HashMap}
+ * by sorting them according to the integer values (sequence) and then collecting the keys
+ * (the {@code CorrelationRule} objects) into a list. The resulting list maintains the order of
+ * the rules based on their corresponding sequence values in ascending order.
+ *
+ * @param rulesSequence a {@code HashMap} where each key is a {@code CorrelationRule} and each
+ * value is an {@code Integer} representing the rule's sequence
+ * @return a {@code List} of rules ordered by their sequence values in ascending
+ * order
+ */
+ public static List sortRulesSequence(
+ HashMap rulesSequence) {
+ // Sort the hashmap based on the sequence and return as a list
+ return rulesSequence.entrySet().stream()
+ .sorted(Map.Entry.comparingByValue()) // Sort by Sequence
+ .map(Map.Entry::getKey) // Extract the Rules and return as a List
+ .collect(Collectors.toList());
+ }
}
diff --git a/src/main/java/com/blazemeter/jmeter/correlation/core/suggestions/method/AnalysisMethod.java b/src/main/java/com/blazemeter/jmeter/correlation/core/suggestions/method/AnalysisMethod.java
index f4b4781..13cd439 100644
--- a/src/main/java/com/blazemeter/jmeter/correlation/core/suggestions/method/AnalysisMethod.java
+++ b/src/main/java/com/blazemeter/jmeter/correlation/core/suggestions/method/AnalysisMethod.java
@@ -6,7 +6,6 @@
import com.blazemeter.jmeter.correlation.core.analysis.AnalysisReporter;
import com.blazemeter.jmeter.correlation.core.automatic.CorrelationSuggestion;
import com.blazemeter.jmeter.correlation.core.automatic.JMeterElementUtils;
-import com.blazemeter.jmeter.correlation.core.suggestions.SuggestionsUtils;
import com.blazemeter.jmeter.correlation.core.suggestions.context.AnalysisContext;
import com.blazemeter.jmeter.correlation.core.suggestions.context.CorrelationContext;
import com.blazemeter.jmeter.correlation.core.templates.Template;
@@ -25,11 +24,12 @@
import org.slf4j.LoggerFactory;
/**
- * The AnalysisMethod class implements the CorrelationMethod interface and provides
- * methods for generating correlation suggestions by analyzing the recording and replay traces
- * using the Correlation Rules in the Correlation Templates.
+ * The AnalysisMethod class implements the CorrelationMethod interface and provides methods for
+ * generating correlation suggestions by analyzing the recording and replay traces using the
+ * Correlation Rules in the Correlation Templates.
*/
public class AnalysisMethod implements CorrelationMethod {
+
private static final Logger LOG = LoggerFactory.getLogger(AnalysisMethod.class);
private AnalysisContext context;
@@ -83,14 +83,17 @@ private static List generateSuggestions() {
return correlationSuggestions;
}
- public static void run(List sampleResults,
- List samplerNodes,
- CorrelationEngine engine,
- List samplers) {
+ public static synchronized void run(List sampleResults,
+ List samplerNodes,
+ CorrelationEngine engine,
+ List samplers) {
JMeterTreeModel model = getCurrentJMeterTreeModel();
Map indexedSamplers = getSamplersIndexedByName(samplers);
for (SampleResult sampleResult : sampleResults) {
+ if (Thread.currentThread().isInterrupted()) {
+ break;
+ }
// Search the sample that match with sample result
// Get indexed sampler if exist
if (indexedSamplers.containsKey(sampleResult.getSampleLabel())) {
@@ -111,6 +114,9 @@ public static void run(List sampleResults,
}
// When children was added, propagate the child to the tree node
for (int j = initialChildCount; j < children.size(); j++) {
+ if (Thread.currentThread().isInterrupted()) {
+ break;
+ }
TestElement child = children.get(j);
// check if that children not exist in the previous node data
// this is to avoid generating duplicate extractors
@@ -173,7 +179,7 @@ private boolean isNullOrEmpty(List> list) {
return list == null || list.isEmpty();
}
- private void runAnalysis(List rulesGroups, boolean shouldCorrelate) {
+ public void runAnalysis(List rulesGroups, boolean shouldCorrelate) {
if (!shouldCorrelate) {
disableCorrelation();
} else {
@@ -231,13 +237,6 @@ private void updateRefVariable(List rulesGroups) {
}
}
- @Override
- public void applySuggestions(List suggestions) {
- List correlationRules = SuggestionsUtils.parseSuggestionsToRules(suggestions);
- List rulesGroups = SuggestionsUtils.parseToGroup(correlationRules);
- runAnalysis(rulesGroups, true);
- }
-
public AnalysisContext getContext() {
return context;
}
diff --git a/src/main/java/com/blazemeter/jmeter/correlation/core/suggestions/method/ComparisonMethod.java b/src/main/java/com/blazemeter/jmeter/correlation/core/suggestions/method/ComparisonMethod.java
index 599a58d..9ad942f 100644
--- a/src/main/java/com/blazemeter/jmeter/correlation/core/suggestions/method/ComparisonMethod.java
+++ b/src/main/java/com/blazemeter/jmeter/correlation/core/suggestions/method/ComparisonMethod.java
@@ -79,13 +79,13 @@ private static boolean hasOrphans(CorrelationSuggestion suggestion) {
* sets the value and name of the ExtractionSuggestion to the value and name of the appearance.
* Finally, it returns the populated ExtractionSuggestion.
*
- * @param result the SampleResult to use for generating the ExtractionSuggestion.
- * @param appearance the Appearances to use for setting the value and name of the
- * ExtractionSuggestion.
- * @param extractor the CorrelationExtractor to use for creating the ExtractionSuggestion.
+ * @param result the SampleResult to use for generating the ExtractionSuggestion.
+ * @param appearance the Appearances to use for setting the value and name of the
+ * ExtractionSuggestion.
+ * @param extractor the CorrelationExtractor to use for creating the ExtractionSuggestion.
* @param structureType the StructureType to use for setting the source of the
- * ExtractionSuggestion.
- * @param name the name to set for the ExtractionSuggestion.
+ * ExtractionSuggestion.
+ * @param name the name to set for the ExtractionSuggestion.
* @return the populated ExtractionSuggestion.
*/
private static ExtractionSuggestion generateCandidateExtractor(SampleResult result,
@@ -165,8 +165,8 @@ private void loadFromDynamicElements(DynamicElement replayCandidate) {
* multivalued replacement suggestions to the CorrelationSuggestion in the same way. Finally, it
* returns the populated CorrelationSuggestion.
*
- * @param element the DynamicElement to use for generating the extraction and replacement
- * suggestions.
+ * @param element the DynamicElement to use for generating the extraction and replacement
+ * suggestions.
* @param suggestion the CorrelationSuggestion to populate with the generated suggestions.
* @return the populated CorrelationSuggestion.
*/
@@ -183,13 +183,11 @@ private CorrelationSuggestion populateSuggestion(DynamicElement element,
* other appearances of the element. The extraction suggestions are added by comparing the
* element's appearances with the results and the valueToReferenceName map.
*
- * @param element the DynamicElement to use for generating the extraction
- * suggestions.
- * @param suggestion the CorrelationSuggestion to add the extraction suggestions to.
- * @param results a list of SampleResults to use for generating the extraction
- * suggestions.
+ * @param element the DynamicElement to use for generating the extraction suggestions.
+ * @param suggestion the CorrelationSuggestion to add the extraction suggestions to.
+ * @param results a list of SampleResults to use for generating the extraction suggestions.
* @param valueToReferenceName a map of values to reference names to use for generating the
- * extraction suggestions.
+ * extraction suggestions.
*/
private void addMultivaluedExtractor(DynamicElement element,
CorrelationSuggestion suggestion, List results,
@@ -218,10 +216,9 @@ private void addMultivaluedExtractor(DynamicElement element,
* extraction parameter name if it is not already mapped.
*
* @param valueToReferenceName a map of values to reference names.
- * @param suggestion the CorrelationSuggestion to add the extraction suggestions to.
- * @param result the SampleResult to use for generating the extraction suggestions.
- * @param appearances a list of Appearances to use for generating the extraction
- * suggestions.
+ * @param suggestion the CorrelationSuggestion to add the extraction suggestions to.
+ * @param result the SampleResult to use for generating the extraction suggestions.
+ * @param appearances a list of Appearances to use for generating the extraction suggestions.
*/
private void addExtractorSuggestions(Map valueToReferenceName,
CorrelationSuggestion suggestion, SampleResult result,
@@ -342,7 +339,7 @@ private String appearancesToString(List appearances) {
* returns true. Otherwise, it returns false.
*
* @param result the SampleResult to check for the value.
- * @param value the value to check for in the query string.
+ * @param value the value to check for in the query string.
* @return true if the query string contains the encoded or raw value, false otherwise.
*/
private boolean valueInUse(SampleResult result, String value) {
@@ -357,7 +354,7 @@ private boolean valueInUse(SampleResult result, String value) {
* TestElements in the appearances list. If the label of the SampleResult is found in the names of
* the TestElements, it returns true. Otherwise, it returns false.
*
- * @param result the SampleResult to check for usage of the dynamic element.
+ * @param result the SampleResult to check for usage of the dynamic element.
* @param appearances a list of TestElements that use the dynamic element.
* @return true if the SampleResult uses the dynamic element, false otherwise.
*/
@@ -375,8 +372,8 @@ private boolean reachedUsageSampler(SampleResult result, List appea
* sets the repeated flag to true and breaks the loop. Finally, it returns the value of the
* repeated flag.
*
- * @param suggestion the CorrelationSuggestion containing the list of replacement
- * suggestions to check.
+ * @param suggestion the CorrelationSuggestion containing the list of replacement suggestions to
+ * check.
* @param replacementSuggestion the replacement suggestion to check for in the list.
* @return true if the replacement suggestion is already present in the list, false otherwise.
*/
@@ -392,8 +389,8 @@ private boolean isRepeated(CorrelationSuggestion suggestion,
* sets the repeated flag to true and breaks the loop. Finally, it returns the value of the
* repeated flag.
*
- * @param suggestion the CorrelationSuggestion containing the list of extraction
- * suggestions to check.
+ * @param suggestion the CorrelationSuggestion containing the list of extraction suggestions to
+ * check.
* @param extractionSuggestion the extraction suggestion to check for in the list.
* @return true if the extraction suggestion is already present in the list, false otherwise.
*/
@@ -410,11 +407,10 @@ private boolean isRepeated(CorrelationSuggestion suggestion,
* original and other appearances. The replacement suggestions are added by comparing the
* appearances with the valueToReferenceName map.
*
- * @param element the DynamicElement to use for generating the replacement
- * suggestions.
- * @param suggestion the CorrelationSuggestion to add the replacement suggestions to.
+ * @param element the DynamicElement to use for generating the replacement suggestions.
+ * @param suggestion the CorrelationSuggestion to add the replacement suggestions to.
* @param valueToReferenceName a map of values to reference names to use for generating the
- * replacement suggestions.
+ * replacement suggestions.
*/
private void addMultivaluedReplacement(DynamicElement element,
CorrelationSuggestion suggestion,
@@ -438,10 +434,10 @@ private void addMultivaluedReplacement(DynamicElement element,
* value, and name, and adds it to the CorrelationSuggestion. It also adds the TestElement to the
* usages of the CorrelationSuggestion.
*
- * @param suggestion the CorrelationSuggestion to add the replacement suggestions to.
+ * @param suggestion the CorrelationSuggestion to add the replacement suggestions to.
* @param valueToReferenceName a map of values to reference names.
- * @param originalAppearances a list of Appearances to use for generating the replacement
- * suggestions.
+ * @param originalAppearances a list of Appearances to use for generating the replacement
+ * suggestions.
*/
private void addReplacementSuggestions(CorrelationSuggestion suggestion,
Map valueToReferenceName,
@@ -512,11 +508,6 @@ public void setContext(ComparisonContext context) {
this.context = context;
}
- @Override
- public void applySuggestions(List suggestions) {
- // Do nothing. Suggestions are applied using the same mechanism as the AnalysisMethod.
- }
-
public static class ReplacementParameters {
private final String refName;
diff --git a/src/main/java/com/blazemeter/jmeter/correlation/core/suggestions/method/CorrelationMethod.java b/src/main/java/com/blazemeter/jmeter/correlation/core/suggestions/method/CorrelationMethod.java
index e2f91d2..8dcc4e9 100644
--- a/src/main/java/com/blazemeter/jmeter/correlation/core/suggestions/method/CorrelationMethod.java
+++ b/src/main/java/com/blazemeter/jmeter/correlation/core/suggestions/method/CorrelationMethod.java
@@ -5,7 +5,6 @@
import java.util.List;
public interface CorrelationMethod {
- List generateSuggestions(CorrelationContext context);
- void applySuggestions(List suggestions);
+ List generateSuggestions(CorrelationContext context);
}
diff --git a/src/main/java/com/blazemeter/jmeter/correlation/core/suggestions/method/LegacyMethod.java b/src/main/java/com/blazemeter/jmeter/correlation/core/suggestions/method/LegacyMethod.java
index 7589203..3e31adb 100644
--- a/src/main/java/com/blazemeter/jmeter/correlation/core/suggestions/method/LegacyMethod.java
+++ b/src/main/java/com/blazemeter/jmeter/correlation/core/suggestions/method/LegacyMethod.java
@@ -14,9 +14,4 @@ public class LegacyMethod implements CorrelationMethod {
public List generateSuggestions(CorrelationContext context) {
return new ArrayList<>();
}
-
- @Override
- public void applySuggestions(List suggestions) {
- // Do nothing
- }
}
diff --git a/src/main/java/com/blazemeter/jmeter/correlation/core/templates/SiebelTemplateRemoval.java b/src/main/java/com/blazemeter/jmeter/correlation/core/templates/SiebelTemplateRemoval.java
index 8fa79d4..17d8b89 100644
--- a/src/main/java/com/blazemeter/jmeter/correlation/core/templates/SiebelTemplateRemoval.java
+++ b/src/main/java/com/blazemeter/jmeter/correlation/core/templates/SiebelTemplateRemoval.java
@@ -6,9 +6,11 @@
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.io.File;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -25,7 +27,7 @@ public class SiebelTemplateRemoval {
private static final String SIEBEL_TESTPLAN_NAME = "siebel-template.jmx";
private static final String SIEBEL_TEMPLATE_NAME = "siebel-1.0-template.json";
- private static final String CORRELATION_TEMPLATES_PATH = "/correlation-templates/";
+ private static final String CORRELATION_TEMPLATES_PATH = "correlation-templates";
private static final String SIEBEL_TEMPLATE_MD5_VALUE = "e1de737f84e2081b26b51d04acecd71a";
private static final Logger LOG = LoggerFactory.getLogger(SiebelTemplateRemoval.class);
@@ -46,27 +48,28 @@ private static void deleteTestPlan(String rootFolder) {
}
private static void deleteTemplate(String rootFolder) throws IOException {
- String acrTemplatePath = rootFolder + CORRELATION_TEMPLATES_PATH;
+ String acrTemplatePath =
+ Paths.get(rootFolder, CORRELATION_TEMPLATES_PATH).toAbsolutePath().toString();
if (!isSiebelTemplateAdded(acrTemplatePath)) {
return;
}
- deleteJsonTemplate(acrTemplatePath);
removeSiebelTemplateFromLocalRepository(acrTemplatePath);
+ deleteJsonTemplate(acrTemplatePath);
}
private static boolean isSiebelTemplateAdded(String acrTemplatePath)
throws IOException {
- File siebelTemplate = new File(
- Paths.get(acrTemplatePath, SIEBEL_TEMPLATE_NAME).toAbsolutePath().toString());
+ File siebelTemplate = new File(acrTemplatePath, SIEBEL_TEMPLATE_NAME);
return siebelTemplate.exists() && DigestUtils
- .md5Hex(Files.newInputStream(Paths.get(siebelTemplate.getPath())))
+ .md5Hex(IOUtils.toString(Files.newInputStream(Paths.get(siebelTemplate.getPath())),
+ StandardCharsets.UTF_8).replaceAll("\r", ""))
.equals(SIEBEL_TEMPLATE_MD5_VALUE);
}
private static void removeSiebelTemplateFromLocalRepository(String acrTemplatePath)
throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
- File localRepository = new File(acrTemplatePath + "local-repository.json");
+ File localRepository = new File(acrTemplatePath, "local-repository.json");
JsonNode rootNode = objectMapper.readTree(localRepository);
ObjectNode rootObjectNode = (ObjectNode) rootNode;
rootObjectNode.remove("siebel");
diff --git a/src/main/java/com/blazemeter/jmeter/correlation/gui/analysis/CorrelationTemplatesSelectionPanel.java b/src/main/java/com/blazemeter/jmeter/correlation/gui/analysis/CorrelationTemplatesSelectionPanel.java
index 61ae328..ec2391f 100644
--- a/src/main/java/com/blazemeter/jmeter/correlation/gui/analysis/CorrelationTemplatesSelectionPanel.java
+++ b/src/main/java/com/blazemeter/jmeter/correlation/gui/analysis/CorrelationTemplatesSelectionPanel.java
@@ -1,16 +1,13 @@
package com.blazemeter.jmeter.correlation.gui.analysis;
-import com.blazemeter.jmeter.commons.SwingUtils;
-import com.blazemeter.jmeter.correlation.core.analysis.Analysis;
+import com.blazemeter.jmeter.commons.SwingUtils.ButtonBuilder;
+import com.blazemeter.jmeter.correlation.core.automatic.CorrelationSuggestion;
import com.blazemeter.jmeter.correlation.core.automatic.JMeterElementUtils;
import com.blazemeter.jmeter.correlation.core.templates.CorrelationTemplatesRepositoriesConfiguration;
import com.blazemeter.jmeter.correlation.core.templates.Repository;
import com.blazemeter.jmeter.correlation.core.templates.Template;
import com.blazemeter.jmeter.correlation.core.templates.Template.Builder;
import com.blazemeter.jmeter.correlation.core.templates.TemplateVersion;
-import com.blazemeter.jmeter.correlation.core.templates.repository.Properties;
-import com.blazemeter.jmeter.correlation.core.templates.repository.RepositoryManager;
-import com.blazemeter.jmeter.correlation.core.templates.repository.RepositoryUtils;
import com.blazemeter.jmeter.correlation.core.templates.repository.TemplateProperties;
import com.blazemeter.jmeter.correlation.gui.automatic.CorrelationWizard;
import com.blazemeter.jmeter.correlation.gui.automatic.WizardStepPanel;
@@ -25,16 +22,14 @@
import java.io.File;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
-import java.util.function.BiConsumer;
import java.util.function.Function;
-import java.util.stream.Collectors;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.GroupLayout;
+import javax.swing.GroupLayout.Alignment;
import javax.swing.JButton;
import javax.swing.JEditorPane;
import javax.swing.JFileChooser;
@@ -44,7 +39,8 @@
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextField;
-import javax.swing.SwingWorker;
+import javax.swing.LayoutStyle.ComponentPlacement;
+import javax.swing.SwingWorker.StateValue;
import javax.swing.event.ListSelectionListener;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.text.DefaultCaret;
@@ -53,6 +49,7 @@
public class CorrelationTemplatesSelectionPanel extends WizardStepPanel implements ActionListener {
+ public static final String DRAFT_REPOSITORY_NAME = "Draft";
private static final long serialVersionUID = 240L;
private static final Logger LOG = LoggerFactory.getLogger(
CorrelationTemplatesSelectionPanel.class);
@@ -60,15 +57,13 @@ public class CorrelationTemplatesSelectionPanel extends WizardStepPanel implemen
private static final String CONTINUE = "continue";
private static final String CANCEL = "cancel";
private static final String RELOAD = "reload";
- private static final String DRAFT_REPOSITORY_NAME = "Draft";
- private final Analysis analysis = new Analysis();
private TemplatesSelectionTable selectionTable;
private JEditorPane informationPane;
private JTextField traceFilePath;
- private BiConsumer, String> startNonCorrelatedAnalysis;
private JButton continueButton;
private Function buildTemplate;
private Template draftTemplate;
+ private TemplateSuggestionsGeneratorWorker generateSuggestionsInWorker;
public CorrelationTemplatesSelectionPanel(CorrelationWizard wizard) {
super(wizard);
@@ -111,22 +106,21 @@ private JPanel buildInfoAndReloadPanel() {
informationLabel.setText(
"Select which Correlation Template and the version that you want to apply:");
- JButton reloadTemplates = new SwingUtils.ButtonBuilder().withActionListener(this)
- .withAction(RELOAD).withName("templateReloadButton").build();
+ JButton reloadTemplates = new ButtonBuilder().withActionListener(this).withAction(RELOAD)
+ .withName("templateReloadButton").build();
reloadTemplates.setText("Reload Templates");
reloadTemplates.setToolTipText("Reload the available Correlation Templates");
GroupLayout layout = new GroupLayout(infoAndReloadPanel);
infoAndReloadPanel.setLayout(layout);
- layout.setHorizontalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(
+ layout.setHorizontalGroup(layout.createParallelGroup(Alignment.LEADING).addGroup(
layout.createSequentialGroup().addContainerGap().addComponent(informationLabel)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED,
- GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE).addComponent(reloadTemplates)
- .addContainerGap()));
- layout.setVerticalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(
+ .addPreferredGap(ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(reloadTemplates).addContainerGap()));
+ layout.setVerticalGroup(layout.createParallelGroup(Alignment.LEADING).addGroup(
layout.createSequentialGroup().addContainerGap().addGroup(
- layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
- .addComponent(informationLabel).addComponent(reloadTemplates)).addContainerGap()));
+ layout.createParallelGroup(Alignment.BASELINE).addComponent(informationLabel)
+ .addComponent(reloadTemplates)).addContainerGap()));
return infoAndReloadPanel;
}
@@ -142,15 +136,14 @@ private JPanel buildCorrelationRulesSelectionPanel() {
GroupLayout layout = new GroupLayout(correlationRulesSelectionPanel);
correlationRulesSelectionPanel.setLayout(layout);
- layout.setHorizontalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(
+ layout.setHorizontalGroup(layout.createParallelGroup(Alignment.LEADING).addGroup(
layout.createSequentialGroup().addContainerGap().addGroup(
- layout.createParallelGroup(GroupLayout.Alignment.LEADING)
+ layout.createParallelGroup(Alignment.LEADING)
.addComponent(correlationRulesTableScrollPane, GroupLayout.DEFAULT_SIZE, 400,
Short.MAX_VALUE)).addContainerGap()));
- layout.setVerticalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(
- layout.createSequentialGroup().addContainerGap()
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ layout.setVerticalGroup(layout.createParallelGroup(Alignment.LEADING).addGroup(
+ layout.createSequentialGroup().addContainerGap().addPreferredGap(ComponentPlacement.RELATED)
.addComponent(correlationRulesTableScrollPane, GroupLayout.DEFAULT_SIZE, 200,
Short.MAX_VALUE).addContainerGap()));
@@ -201,12 +194,10 @@ private void initDraftTemplate() {
String lastModifiedDate = LocalDateTime.now()
.format(DateTimeFormatter.ofPattern("MM.dd.yyyy-HH.mm.ss"));
this.draftTemplate = buildTemplate.apply(
- new Builder().withId("draft").withRepositoryId(DRAFT_REPOSITORY_NAME)
- .withVersion("N/A")
+ new Builder().withId("draft").withRepositoryId(DRAFT_REPOSITORY_NAME).withVersion("N/A")
.withChanges("Rules extracted on: " + lastModifiedDate)
.withDescription("These are the rules which are under development in Correlation Panel")
- .withAuthor(System.getProperty("user.name") + "(you)")
- .withUrl("")
+ .withAuthor(System.getProperty("user.name") + "(you)").withUrl("")
.withDependencies(Collections.emptyList()));
}
@@ -231,12 +222,12 @@ private JPanel buildCorrelationRulesInformationPanel() {
GroupLayout layout = new GroupLayout(correlationRulesInformationPanel);
correlationRulesInformationPanel.setLayout(layout);
- layout.setHorizontalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(
+ layout.setHorizontalGroup(layout.createParallelGroup(Alignment.LEADING).addGroup(
layout.createSequentialGroup().addContainerGap()
.addComponent(scrollPane, GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE)
.addContainerGap()));
- layout.setVerticalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(
+ layout.setVerticalGroup(layout.createParallelGroup(Alignment.LEADING).addGroup(
layout.createSequentialGroup().addContainerGap()
.addComponent(scrollPane, GroupLayout.DEFAULT_SIZE, 250, Short.MAX_VALUE)
.addContainerGap()));
@@ -252,7 +243,7 @@ private JPanel buildButtonsPanel() {
traceFilePanel.setBorder(BorderFactory.createTitledBorder("Select the .jtl file to use"));
traceFilePath = new JTextField();
- SwingUtils.ButtonBuilder builder = new SwingUtils.ButtonBuilder().withActionListener(this);
+ ButtonBuilder builder = new ButtonBuilder().withActionListener(this);
traceFilePanel.add(traceFilePath);
traceFilePanel.add(
builder.withAction(BROWSE).withText("Browse").withName("templateBrowseButton").build());
@@ -303,8 +294,7 @@ protected Boolean doInBackground() {
};
worker.addPropertyChangeListener(evt -> {
- if (evt.getPropertyName().equals("state") && evt.getNewValue()
- .equals(SwingWorker.StateValue.DONE)) {
+ if (evt.getPropertyName().equals("state") && evt.getNewValue().equals(StateValue.DONE)) {
loadCorrelationTemplates();
}
});
@@ -324,68 +314,16 @@ private void validateAndContinue() {
"No Trace File Selected", JOptionPane.ERROR_MESSAGE);
return;
}
-
- onContinue();
- }
-
- private void onContinue() {
- Map> repositoryGrouped =
- selectionTable.getSelectedTemplateWithRepositoryMap();
-
- boolean isDraft = false;
- List canUseTemplates = new ArrayList<>();
- List cannotUseTemplates = new ArrayList<>();
- for (Map.Entry> entry : repositoryGrouped.entrySet()) {
- String repositoryName = entry.getKey();
- if (repositoryName.equals(DRAFT_REPOSITORY_NAME)) {
- isDraft = !draftTemplate.getGroups().isEmpty();
- continue;
- }
- List templates = entry.getValue();
- CorrelationTemplatesRepositoriesConfiguration config =
- this.wizard.getRepositoriesConfiguration();
- RepositoryManager repManager = config.getRepositoryManager(repositoryName);
-
- Map templatesAndProperties =
- repManager.getTemplatesAndProperties(
- templates);
-
- if (templatesAndProperties == null || templatesAndProperties.isEmpty()) {
- // Get all the templates and properties for the local repository and filter the selected
- templatesAndProperties = config.getCorrelationTemplatesAndPropertiesByRepositoryName(
- repositoryName, true).entrySet().stream().filter(templateEntry -> templates.stream()
- .anyMatch(
- t -> templateEntry.getKey().getId().equals(t.getName())
- && templateEntry.getKey().getVersion().equals(t.getVersion())))
- .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
- }
-
- for (Map.Entry templateEntry
- : templatesAndProperties.entrySet()) {
- TemplateProperties value = templateEntry.getValue();
- Properties properties = new Properties();
- properties.putAll(value);
-
- if (properties.canUse()) {
- canUseTemplates.add(templateEntry.getKey());
- } else {
- cannotUseTemplates.add(templateEntry.getKey());
- }
- }
- }
-
- if (!cannotUseTemplates.isEmpty()) {
+ continueButton.setEnabled(false);
+ generateSuggestionsInWorker = new TemplateSuggestionsGeneratorWorker(this);
+ if (generateSuggestionsInWorker.isSelectedCanNotUseTemplates()) {
JOptionPane.showMessageDialog(this,
"You don't have permission to use the following templates:\n"
- + cannotUseTemplates.stream().map(RepositoryUtils::getTemplateInfo)
- .collect(Collectors.joining("\n")), "Cannot use templates",
- JOptionPane.ERROR_MESSAGE);
- }
-
- if (isDraft) {
- canUseTemplates.add(draftTemplate);
+ + generateSuggestionsInWorker.getCanNotUseTemplatesName(),
+ "Templates excluded from suggestion analysis",
+ JOptionPane.INFORMATION_MESSAGE);
}
- this.startNonCorrelatedAnalysis.accept(canUseTemplates, traceFilePath.getText());
+ generateSuggestionsInWorker.execute();
}
private void browseForJtl() {
@@ -405,11 +343,6 @@ private void enableContinue(boolean enable) {
+ "Make a recording or select a .jtl of a recording to be analyzed.");
}
- public void setStartNonCorrelatedAnalysis(
- BiConsumer, String> nonCorrelatedAnalysis) {
- this.startNonCorrelatedAnalysis = nonCorrelatedAnalysis;
- }
-
public void setRecordingTrace() {
String fileName = JMeterElementUtils.getRecordingResultFileName();
boolean fileExist = fileName != null && !fileName.isEmpty();
@@ -427,17 +360,27 @@ public String getTraceFilePath() {
return traceFilePath.getText();
}
- //Reminder: this is the place where the "Analysis by Template" is called.
- public void runNonCorrelatedAnalysis(List templatesToAnalyse, String recordingTrace) {
- analysis.run(templatesToAnalyse, recordingTrace, false);
+ public void setBuildTemplate(Function buildTemplate) {
+ this.buildTemplate = buildTemplate;
}
- //Reminder: this is the "Apply Suggestions" for Analysis.
- public void runCorrelatedAnalysis(List templatesApply, String recordingTrace) {
- analysis.run(templatesApply, recordingTrace, true);
+ public void sendSuggestionsToWizard(List suggestions) {
+ wizard.loadSuggestions(suggestions);
}
- public void setBuildTemplate(Function buildTemplate) {
- this.buildTemplate = buildTemplate;
+ public Map> getSelectedTemplateWithRepositoryMap() {
+ return this.selectionTable.getSelectedTemplateWithRepositoryMap();
+ }
+
+ public Template getDraftTemplate() {
+ return draftTemplate;
+ }
+
+ public CorrelationTemplatesRepositoriesConfiguration getRepositoriesConfiguration() {
+ return wizard.getRepositoriesConfiguration();
+ }
+
+ public void enableContinueButton(boolean enable) {
+ continueButton.setEnabled(enable);
}
}
diff --git a/src/main/java/com/blazemeter/jmeter/correlation/gui/analysis/TemplateSuggestionsGeneratorWorker.java b/src/main/java/com/blazemeter/jmeter/correlation/gui/analysis/TemplateSuggestionsGeneratorWorker.java
new file mode 100644
index 0000000..ba8dc65
--- /dev/null
+++ b/src/main/java/com/blazemeter/jmeter/correlation/gui/analysis/TemplateSuggestionsGeneratorWorker.java
@@ -0,0 +1,232 @@
+package com.blazemeter.jmeter.correlation.gui.analysis;
+
+import static com.blazemeter.jmeter.correlation.gui.analysis.CorrelationTemplatesSelectionPanel.DRAFT_REPOSITORY_NAME;
+
+import com.blazemeter.jmeter.correlation.core.analysis.Analysis;
+import com.blazemeter.jmeter.correlation.core.automatic.CorrelationSuggestion;
+import com.blazemeter.jmeter.correlation.core.automatic.WaitingDialog;
+import com.blazemeter.jmeter.correlation.core.suggestions.InterruptibleWorkerAgreement;
+import com.blazemeter.jmeter.correlation.core.templates.CorrelationTemplatesRepositoriesConfiguration;
+import com.blazemeter.jmeter.correlation.core.templates.Template;
+import com.blazemeter.jmeter.correlation.core.templates.TemplateVersion;
+import com.blazemeter.jmeter.correlation.core.templates.repository.Properties;
+import com.blazemeter.jmeter.correlation.core.templates.repository.RepositoryManager;
+import com.blazemeter.jmeter.correlation.core.templates.repository.RepositoryUtils;
+import com.blazemeter.jmeter.correlation.core.templates.repository.TemplateProperties;
+import java.beans.PropertyChangeEvent;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.stream.Collectors;
+import javax.swing.JOptionPane;
+import javax.swing.SwingWorker;
+import javax.swing.Timer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TemplateSuggestionsGeneratorWorker extends
+ SwingWorker, String> implements InterruptibleWorkerAgreement {
+
+ private static final Logger LOG = LoggerFactory.getLogger(
+ TemplateSuggestionsGeneratorWorker.class);
+ private final CorrelationTemplatesSelectionPanel templatePanel;
+ private final Analysis analysis = new Analysis();
+ private final TemplateBundle templateBundle;
+ private final String traceFilePath;
+ private boolean isRunning = false;
+ private Timer timer;
+
+ public TemplateSuggestionsGeneratorWorker(CorrelationTemplatesSelectionPanel panel) {
+ this.templatePanel = panel;
+ traceFilePath = templatePanel.getTraceFilePath();
+ templateBundle = new TemplateBundle(
+ templatePanel.getSelectedTemplateWithRepositoryMap(),
+ templatePanel.getDraftTemplate(),
+ templatePanel.getRepositoriesConfiguration());
+ this.addPropertyChangeListener(this);
+ }
+
+ @Override
+ protected void process(List chunks) {
+ String message = chunks.get(chunks.size() - 1);
+ WaitingDialog.changeWaitingMessage(message);
+ }
+
+ @Override
+ protected void done() {
+ WaitingDialog.disposeWaitingDialog();
+ }
+
+ @Override
+ protected List doInBackground() {
+ WaitingDialog.displayWaitingScreen("Generating Suggestions from templates",
+ "Analysing templates",
+ templatePanel);
+ WaitingDialog.addWindowAdapter(getWindowAdapter());
+ isRunning = true;
+
+ List canUseTemplates = templateBundle.getCanUseTemplates();
+ List suggestions = new ArrayList<>();
+ for (Template version : canUseTemplates) {
+ if (isCancelled()) {
+ break;
+ }
+ publish("Running Analysis for:\n\t-" + RepositoryUtils.getTemplateInfo(version));
+ Map> generatedSuggestions =
+ analysis.run(Collections.singletonList(version),
+ traceFilePath, false);
+ for (Entry> entry
+ : generatedSuggestions.entrySet()) {
+ for (CorrelationSuggestion suggestion : entry.getValue()) {
+ suggestion.setSource(version);
+ suggestions.add(suggestion);
+ }
+ }
+ }
+ isRunning = false;
+ return suggestions;
+ }
+
+ public boolean isRunning() {
+ return isRunning;
+ }
+
+ @Override
+ public void onInterruption() {
+ if (!isRunning) {
+ return;
+ }
+ TemplateSuggestionsGeneratorWorker.this.cancel(true);
+ WaitingDialog.displayWaitingScreen("Abort operation", "Waiting for Analysis to be "
+ + "terminated", TemplateSuggestionsGeneratorWorker.this.templatePanel);
+ timer = new Timer(3000, event -> {
+ if (TemplateSuggestionsGeneratorWorker.this.isRunning()) {
+ timer.restart();
+ } else {
+ WaitingDialog.disposeWaitingDialog();
+ timer.stop();
+ JOptionPane.showMessageDialog(TemplateSuggestionsGeneratorWorker.this.templatePanel,
+ "Suggestion generation stopped");
+ TemplateSuggestionsGeneratorWorker.this.firePropertyChange(ON_FAILURE_ENDED_PROPERTY,
+ false,
+ true);
+ }
+ });
+ timer.setRepeats(false);
+ timer.start();
+ }
+
+ @Override
+ public void onWorkerPropertyChange(PropertyChangeEvent evt) {
+ if (evt.getPropertyName().equals("state") && evt.getNewValue().equals(StateValue.DONE)
+ && isDone()) {
+ List suggestions;
+ try {
+ suggestions = this.get();
+ } catch (InterruptedException | ExecutionException e) {
+ JOptionPane.showMessageDialog(templatePanel,
+ "There was an unexpected error while retrieving suggestions");
+ LOG.error("Error while generating suggestions from Templates", e);
+ Thread.currentThread().interrupt();
+ return;
+ } catch (CancellationException e) {
+ // Exception captured and ignored since this case is handled by the worker itself as
+ // recovery plan when user cancels the generation of suggestions see onInterruption()
+ return;
+ }
+ templatePanel.sendSuggestionsToWizard(suggestions);
+ templatePanel.enableContinueButton(true);
+ } else if (evt.getPropertyName().equals(ON_FAILURE_ENDED_PROPERTY)) {
+ templatePanel.enableContinueButton(true);
+ }
+ }
+
+ public boolean isSelectedCanNotUseTemplates() {
+ return templateBundle.isSelectedCanNotUseTemplates();
+ }
+
+ public String getCanNotUseTemplatesName() {
+ return templateBundle.getCanNotUseTemplatesName();
+ }
+
+ private static class TemplateBundle {
+
+ private final List canUseTemplates = new ArrayList<>();
+ private final List cannotUseTemplates = new ArrayList<>();
+ private final Map> templateWithRepositoryMap;
+ private final Template draftTemplate;
+ private final CorrelationTemplatesRepositoriesConfiguration config;
+
+ TemplateBundle(Map> templateWithRepositoryMap,
+ Template draftTemplate,
+ CorrelationTemplatesRepositoriesConfiguration config) {
+
+ this.templateWithRepositoryMap = templateWithRepositoryMap;
+ this.draftTemplate = draftTemplate;
+ this.config = config;
+ resolveSelectedTemplates();
+ }
+
+ public List getCanUseTemplates() {
+ return canUseTemplates;
+ }
+
+ public boolean isSelectedCanNotUseTemplates() {
+ return !cannotUseTemplates.isEmpty();
+ }
+
+ public String getCanNotUseTemplatesName() {
+ return cannotUseTemplates.stream().map(RepositoryUtils::getTemplateInfo)
+ .collect(Collectors.joining("\n"));
+ }
+
+ public void resolveSelectedTemplates() {
+ boolean isDraft = false;
+ for (Entry> entry : templateWithRepositoryMap.entrySet()) {
+ String repositoryName = entry.getKey();
+ if (repositoryName.equals(DRAFT_REPOSITORY_NAME)) {
+ isDraft = !draftTemplate.getGroups().isEmpty();
+ continue;
+ }
+ List templates = entry.getValue();
+ RepositoryManager repManager = config.getRepositoryManager(repositoryName);
+
+ Map templatesAndProperties =
+ repManager.getTemplatesAndProperties(
+ templates);
+
+ if (templatesAndProperties == null || templatesAndProperties.isEmpty()) {
+ // Get all the templates and properties for the local repository and filter the selected
+ templatesAndProperties =
+ config.getCorrelationTemplatesAndPropertiesByRepositoryName(
+ repositoryName, true).entrySet().stream()
+ .filter(templateEntry -> templates.stream()
+ .anyMatch(
+ t -> templateEntry.getKey().getId().equals(t.getName())
+ && templateEntry.getKey().getVersion().equals(t.getVersion())))
+ .collect(Collectors.toMap(Entry::getKey, Entry::getValue));
+ }
+
+ for (Entry templateEntry
+ : templatesAndProperties.entrySet()) {
+ TemplateProperties value = templateEntry.getValue();
+ Properties properties = new Properties();
+ properties.putAll(value);
+
+ if (properties.canUse()) {
+ canUseTemplates.add(templateEntry.getKey());
+ } else {
+ cannotUseTemplates.add(templateEntry.getKey());
+ }
+ }
+ }
+ if (isDraft) {
+ canUseTemplates.add(draftTemplate);
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/blazemeter/jmeter/correlation/gui/automatic/CorrelationHistoryFrame.java b/src/main/java/com/blazemeter/jmeter/correlation/gui/automatic/CorrelationHistoryFrame.java
index e5bc46c..03a7d48 100644
--- a/src/main/java/com/blazemeter/jmeter/correlation/gui/automatic/CorrelationHistoryFrame.java
+++ b/src/main/java/com/blazemeter/jmeter/correlation/gui/automatic/CorrelationHistoryFrame.java
@@ -4,7 +4,7 @@
import com.blazemeter.jmeter.correlation.core.automatic.CorrelationHistory;
import com.blazemeter.jmeter.correlation.core.automatic.CorrelationHistory.Step;
import com.blazemeter.jmeter.correlation.core.automatic.CorrelationSuggestion;
-import com.blazemeter.jmeter.correlation.core.automatic.JMeterElementUtils;
+import com.blazemeter.jmeter.correlation.core.automatic.WaitingDialog;
import com.blazemeter.jmeter.correlation.core.templates.Template;
import com.helger.commons.annotation.VisibleForTesting;
import java.awt.BorderLayout;
@@ -48,15 +48,14 @@
import org.slf4j.LoggerFactory;
-
/**
- * This class will allow the user see the history and select a step to roll back to.
- * It will display a list of the avaliable snapshots in the history file
- * and allow the user to select one.
- * After, based on that slection the new tree will be loaded.
+ * This class will allow the user see the history and select a step to roll back to. It will display
+ * a list of the avaliable snapshots in the history file and allow the user to select one. After,
+ * based on that slection the new tree will be loaded.
*/
public class CorrelationHistoryFrame extends JDialog implements ActionListener {
+
private static final Logger LOG = LoggerFactory.getLogger(CorrelationSuggestionsPanel.class);
private static final String DELETE = "delete";
private static final String RESTORE = "restore";
@@ -64,7 +63,6 @@ public class CorrelationHistoryFrame extends JDialog implements ActionListener {
private static final String CREATE = "create";
protected CorrelationHistory history;
- protected JDialog runDialog;
@VisibleForTesting
protected JTable table;
@@ -150,10 +148,10 @@ private JPanel makeCorrelationHistoryPanel() {
.build();
createCheckpointButton = builder.withAction(CREATE)
- .withName("createIteration")
- .withText("Create Checkpoint")
- .withToolTip("Create a snapshot of the jmx state as history iteration.")
- .build();
+ .withName("createIteration")
+ .withText("Create Checkpoint")
+ .withToolTip("Create a snapshot of the jmx state as history iteration.")
+ .build();
JPanel buttonsPanel = new JPanel();
buttonsPanel.add(deleteButton);
@@ -188,20 +186,6 @@ public void loadSteps(List steps) {
model.loadSteps(steps);
}
- protected void displayWaitingScreen(String message) {
- runDialog = JMeterElementUtils.makeWaitingFrame(message);
- runDialog.pack();
- runDialog.repaint();
- runDialog.setAlwaysOnTop(true);
- runDialog.setVisible(true);
- runDialog.toFront();
- }
-
- public void disposeWaitingDialog() {
- runDialog.dispose();
- runDialog.setVisible(false);
- }
-
@Override
public void actionPerformed(ActionEvent e) {
HistoryTableModel tableModel = (HistoryTableModel) this.table.getModel();
@@ -220,13 +204,13 @@ public void actionPerformed(ActionEvent e) {
case RESTORE:
if (tableModel.getSelectedSteps().isEmpty()) {
JOptionPane.showMessageDialog(this,
- "Please select one iteration to restore");
+ "Please select one iteration to restore");
} else if (tableModel.getSelectedSteps().size() > 1) {
JOptionPane.showMessageDialog(this,
- "You can't restore more than one iteration at a time.");
+ "You can't restore more than one iteration at a time.");
} else {
try {
- this.displayWaitingScreen("Restoring iteration.");
+ WaitingDialog.displayWaitingScreen("History Manager", "Restoring iteration.");
this.restoreStep(tableModel.getSelectedSteps().get(0));
HistoryFrameSwingWorker worker = new HistoryFrameSwingWorker(this);
worker.execute();
@@ -275,6 +259,7 @@ public void zipHistory() {
}
public static class HistoryTableModel extends DefaultTableModel {
+
private final List columns = Arrays.asList("", "Timestamp", "Description", "Notes");
private final List stepList = new ArrayList<>();
private final Map> suggestionsMap =
@@ -398,6 +383,7 @@ public Step getStep() {
}
public static class HistoryFrameSwingWorker extends SwingWorker {
+
private final CorrelationHistoryFrame frame;
public HistoryFrameSwingWorker(CorrelationHistoryFrame frame) {
@@ -413,9 +399,10 @@ protected String doInBackground() throws Exception {
@Override
protected void done() {
- frame.disposeWaitingDialog();
+ WaitingDialog.disposeWaitingDialog();
+ //frame.disposeWaitingDialog();
JOptionPane.showMessageDialog(frame,
- "Iteration restored.");
+ "Iteration restored.");
frame.setVisible(false);
}
}
diff --git a/src/main/java/com/blazemeter/jmeter/correlation/gui/automatic/CorrelationSuggestionsPanel.java b/src/main/java/com/blazemeter/jmeter/correlation/gui/automatic/CorrelationSuggestionsPanel.java
index b013443..307bc7e 100644
--- a/src/main/java/com/blazemeter/jmeter/correlation/gui/automatic/CorrelationSuggestionsPanel.java
+++ b/src/main/java/com/blazemeter/jmeter/correlation/gui/automatic/CorrelationSuggestionsPanel.java
@@ -1,14 +1,14 @@
package com.blazemeter.jmeter.correlation.gui.automatic;
+import static com.blazemeter.jmeter.correlation.core.suggestions.SuggestionsUtils.sortRulesSequence;
+
import com.blazemeter.jmeter.commons.SwingUtils;
import com.blazemeter.jmeter.correlation.core.CorrelationRule;
import com.blazemeter.jmeter.correlation.core.automatic.Configuration;
import com.blazemeter.jmeter.correlation.core.automatic.CorrelationSuggestion;
-import com.blazemeter.jmeter.correlation.core.automatic.JMeterElementUtils;
import com.blazemeter.jmeter.correlation.core.suggestions.SuggestionGenerator;
-import com.blazemeter.jmeter.correlation.core.suggestions.context.AnalysisContext;
+import com.blazemeter.jmeter.correlation.core.suggestions.SuggestionsApplianceWorker;
import com.blazemeter.jmeter.correlation.core.suggestions.context.ComparisonContext;
-import com.blazemeter.jmeter.correlation.core.suggestions.method.AnalysisMethod;
import com.blazemeter.jmeter.correlation.core.suggestions.method.ComparisonMethod;
import com.blazemeter.jmeter.correlation.core.templates.Template;
import com.blazemeter.jmeter.correlation.core.templates.TemplateVersion;
@@ -16,7 +16,6 @@
import com.blazemeter.jmeter.correlation.core.templates.repository.RepositoryManager;
import com.blazemeter.jmeter.correlation.core.templates.repository.RepositoryUtils;
import com.blazemeter.jmeter.correlation.core.templates.repository.TemplateProperties;
-import com.blazemeter.jmeter.correlation.gui.CorrelationComponentsRegistry;
import com.helger.commons.annotation.VisibleForTesting;
import java.awt.BorderLayout;
import java.awt.Dimension;
@@ -31,6 +30,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.function.Consumer;
import java.util.stream.Collectors;
import javax.swing.GroupLayout;
import javax.swing.JButton;
@@ -64,13 +64,13 @@ public class CorrelationSuggestionsPanel extends WizardStepPanel implements Acti
private static final String MANUAL_REPLAY = "replay";
private static final String CLEAR_SUGGESTIONS = "clear";
private static final String EXPORT_AS_RULES = "export";
+ protected boolean isSuggestionsApplied;
private final String iconSize = JMeterUtils.getPropDefault(
JMeterToolBar.TOOLBAR_ICON_SIZE, JMeterToolBar.DEFAULT_TOOLBAR_ICON_SIZE);
private final String toolbarPath = "toolbar/" + iconSize + "/";
private JTabbedPane tabbedPane;
private JTable table;
private JList reportList = new JList<>();
- private Runnable autoCorrelateMethod;
private Runnable replaySelectionMethod;
private final boolean isExtraDebuggingEnabled = JMeterUtils.getPropDefault(
"correlation.debug.extra_debugging", false);
@@ -78,7 +78,6 @@ public class CorrelationSuggestionsPanel extends WizardStepPanel implements Acti
public CorrelationSuggestionsPanel(CorrelationWizard wizard) {
super(wizard);
init();
- setupDefaultAutoCorrelateMethod();
}
private void init() {
@@ -268,7 +267,7 @@ public void actionPerformed(ActionEvent e) {
String action = e.getActionCommand();
switch (action) {
case CORRELATE:
- SwingUtilities.invokeLater(autoCorrelateMethod);
+ SwingUtilities.invokeLater(this::applySuggestions);
return;
case MANUAL_REPLAY:
SwingUtilities.invokeLater(this::manualReplayAndGenerateSuggestions);
@@ -289,41 +288,9 @@ private void manualReplayAndGenerateSuggestions() {
replayTestPlan();
}
- private void setupDefaultAutoCorrelateMethod() {
- autoCorrelateMethod = this::applySuggestions;
- }
-
- // Reminder: This method is called when the Suggestions came from Comparison methods.
public void applySuggestions() {
- List suggestions = exportSelectedSuggestions();
- if (suggestions.isEmpty()) {
- JOptionPane.showMessageDialog(this,
- "No suggestions selected. Please select at least one suggestion to "
- + "apply", "No suggestions selected",
- JOptionPane.INFORMATION_MESSAGE);
- return;
- }
-
- AnalysisContext context = new AnalysisContext();
- String recordingTraceFilePath = getRecordingTraceSupplier.get();
- context.setRecordingTraceFilePath(recordingTraceFilePath);
- context.setRecordingTestPlan(JMeterElementUtils.getNormalizedTestPlan());
- context.setRegistry(CorrelationComponentsRegistry.getInstance());
-
- logStepConsumer.accept("(Save) Before apply suggestions");
- SuggestionGenerator generator
- = SuggestionGenerator.getInstance(new AnalysisMethod(context));
- generator.applySuggestions(suggestions);
- logStepConsumer.accept("(Save) After apply suggestions");
- JMeterElementUtils.refreshJMeter();
-
- if (isExtraDebuggingEnabled) {
- displayAppliedResults();
- }
- }
-
- public void setAutoCorrelateMethod(Runnable autoCorrelateMethod) {
- this.autoCorrelateMethod = autoCorrelateMethod;
+ SuggestionsApplianceWorker suggestionsApplianceWorker = new SuggestionsApplianceWorker(this);
+ suggestionsApplianceWorker.execute();
}
public void setReplaySelectionMethod(Runnable replaySelectionMethod) {
@@ -369,15 +336,18 @@ private void exportSuggestions() {
JOptionPane.INFORMATION_MESSAGE);
}
- Set rules = new HashSet<>();
+ HashMap rulesSequence = new HashMap<>();
for (CorrelationSuggestion suggestion : suggestions) {
Template source = suggestion.getSource();
// Automatic or Template based
if (source == null || templateContains(canExport, source)) {
- rules.addAll(suggestion.toCorrelationRules());
+ rulesSequence.putAll(suggestion.toCorrelationRules());
}
}
+ // Sort the hashmap based on the sequence and return as a list
+ List rules = sortRulesSequence(rulesSequence);
+
exportRulesConsumer.accept(new ArrayList<>(rules));
if (isDraft) {
showExportingMessage(
@@ -468,6 +438,18 @@ public void loadSuggestionsMap(Map> sugges
model.loadSuggestionsMap(suggestions);
}
+ public void hideWizard() {
+ wizard.hideWizard();
+ }
+
+ public String getRecordingTraceSupplier() {
+ return getRecordingTraceSupplier.get();
+ }
+
+ public Consumer getHistoryLogStep() {
+ return logStepConsumer;
+ }
+
public static class SuggestionsTableModel extends DefaultTableModel {
//Extended table will also show "New Value" column
diff --git a/src/main/java/com/blazemeter/jmeter/correlation/gui/automatic/CorrelationWizard.java b/src/main/java/com/blazemeter/jmeter/correlation/gui/automatic/CorrelationWizard.java
index c79662a..1b88f8f 100644
--- a/src/main/java/com/blazemeter/jmeter/correlation/gui/automatic/CorrelationWizard.java
+++ b/src/main/java/com/blazemeter/jmeter/correlation/gui/automatic/CorrelationWizard.java
@@ -3,13 +3,13 @@
import static org.slf4j.LoggerFactory.getLogger;
import com.blazemeter.jmeter.correlation.core.CorrelationRule;
-import com.blazemeter.jmeter.correlation.core.analysis.AnalysisReporter;
import com.blazemeter.jmeter.correlation.core.automatic.CorrelationHistory;
import com.blazemeter.jmeter.correlation.core.automatic.CorrelationSuggestion;
import com.blazemeter.jmeter.correlation.core.automatic.JMeterElementUtils;
import com.blazemeter.jmeter.correlation.core.automatic.ReplayReport;
import com.blazemeter.jmeter.correlation.core.automatic.ReplayWorker;
import com.blazemeter.jmeter.correlation.core.automatic.ReplayWorker.ReplayWorkerArrivalContext;
+import com.blazemeter.jmeter.correlation.core.automatic.WaitingDialog;
import com.blazemeter.jmeter.correlation.core.suggestions.SuggestionGenerator;
import com.blazemeter.jmeter.correlation.core.templates.CorrelationTemplatesRepositoriesConfiguration;
import com.blazemeter.jmeter.correlation.core.templates.LocalConfiguration;
@@ -20,12 +20,9 @@
import com.helger.commons.annotation.VisibleForTesting;
import java.awt.Component;
import java.awt.GridLayout;
-import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
import java.util.Map;
-import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
@@ -37,12 +34,11 @@
import org.slf4j.Logger;
/**
- * This class will be the main class for the correlation wizard.
- * It will display the different steps to configure the correlation:
- * 1. Display the "Select the method of correlation" JPanel
- * 2. Display the CorrelationRulesSelectionPanel for the Template's Selection
- * (this should be the AnalysisPanel)
- * 3. Display the CorrelationSuggestionsPanel so the User can select which suggestions to apply
+ * This class will be the main class for the correlation wizard. It will display the different steps
+ * to configure the correlation: 1. Display the "Select the method of correlation" JPanel 2. Display
+ * the CorrelationRulesSelectionPanel for the Template's Selection (this should be the
+ * AnalysisPanel) 3. Display the CorrelationSuggestionsPanel so the User can select which
+ * suggestions to apply
*/
public class CorrelationWizard extends JDialog {
@@ -97,63 +93,27 @@ private void initCorrelateByRulesPanels() {
templateSelectionPanel.setGetCorrelationHistorySupplier(() -> history);
}
templateSelectionPanel.setBuildTemplate(buildTemplate);
-
- templateSelectionPanel.setStartNonCorrelatedAnalysis(startNonCorrelatedAnalysis());
}
- private BiConsumer, String> startNonCorrelatedAnalysis() {
- return (selectedTemplates, tracePath) -> {
- history.addAnalysisStep("Before applying rules analysis",
- JMeterElementUtils.saveTestPlanSnapshot(), tracePath);
-
- List suggestions = new ArrayList<>();
- for (Template version : selectedTemplates) {
- templateSelectionPanel.runNonCorrelatedAnalysis(Collections.singletonList(version),
- tracePath);
- List generatedSuggestions =
- AnalysisReporter.generateCorrelationSuggestions();
-
- for (CorrelationSuggestion suggestion : generatedSuggestions) {
- suggestion.setSource(version);
- suggestions.add(suggestion);
- }
- }
-
- if (suggestions.isEmpty()) {
- JOptionPane.showMessageDialog(this,
- "The analysis was completed successfully, but we did not find any suggestions." +
- System.lineSeparator() + "Please review the rules you are applying and try again.");
- hideWizard();
- return;
- }
- suggestionsPanel.loadSuggestions(suggestions);
- suggestionsPanel.setReplaySelectionMethod(this::displayMethodSelection);
-
- // Reminder: This is called when the Suggestions were generated by Analysis
-
- displaySuggestions();
- suggestionsPanel.displaySuggestionsTab();
+ public void loadSuggestions(List suggestions) {
+ if (suggestions.isEmpty()) {
JOptionPane.showMessageDialog(this,
- "The analysis was completed successfully!" + System.lineSeparator() +
- "We generated the following suggestions for you. " + System.lineSeparator() +
- System.lineSeparator() + "Please review them and apply them if you agree with them.");
- };
- }
-
- private void applySuggestionsFromTemplate(List selectedTemplates, String tracePath) {
- history.addAnalysisStep("Before applying correlations",
- JMeterElementUtils.saveTestPlanSnapshot(), tracePath);
- templateSelectionPanel.runCorrelatedAnalysis(selectedTemplates, tracePath);
+ "The analysis was completed successfully, but we did not find any suggestions." +
+ System.lineSeparator() + "Please review the rules you are applying and try again.");
+ hideWizard();
+ return;
+ }
+ suggestionsPanel.loadSuggestions(suggestions);
+ suggestionsPanel.setReplaySelectionMethod(this::displayMethodSelection);
+ displaySuggestions();
+ suggestionsPanel.displaySuggestionsTab();
JOptionPane.showMessageDialog(this,
- "The suggestions were applied successfully to your Test Plan." +
- System.lineSeparator() + "Please review the changes and, when you are ready, " +
- "replay to review the results.");
- history.addAnalysisStep("After applying correlations",
- JMeterElementUtils.saveTestPlanSnapshot(), tracePath);
- hideWizard();
+ "The analysis was completed successfully!" + System.lineSeparator() +
+ "We generated the following suggestions for you. " + System.lineSeparator() +
+ System.lineSeparator() + "Please review them and apply them if you agree with them.");
}
- private void hideWizard() {
+ public void hideWizard() {
setVisible(false);
}
@@ -202,27 +162,6 @@ private boolean isNonGui() {
public void loadAndDisplaySuggestions() {
suggestionsPanel.setReplaySelectionMethod(this::displayMethodSelection);
- suggestionsPanel.setAutoCorrelateMethod(() -> {
- displayApplyingSuggestionsWaitingScreen();
- SwingWorker swAnalysis = new SwingWorker() {
- @Override
- protected String doInBackground() {
- suggestionsPanel.applySuggestions();
- return null;
- }
-
- @Override
- protected void done() {
- disposeWaitingDialog();
- JOptionPane.showMessageDialog(CorrelationWizard.this,
- "The suggestions were applied successfully to your Test Plan." +
- System.lineSeparator() + "Please review the changes and, when you are ready, " +
- "replay to review the results.");
- hideWizard();
- }
- };
- swAnalysis.execute();
- });
if (replayWorker == null) {
setupReplayWorker();
@@ -250,7 +189,7 @@ protected String doInBackground() {
@Override
protected void done() {
- disposeWaitingDialog();
+ WaitingDialog.disposeWaitingDialog();
displaySuggestions();
}
};
@@ -378,7 +317,7 @@ private boolean isEmpty(String str) {
}
public void endReplayAndReport() {
- disposeWaitingDialog();
+ WaitingDialog.disposeWaitingDialog();
showReport();
}
@@ -424,7 +363,7 @@ public static int wantToAutoCorrelate(ReplayReport report, Component parent) {
public void onFailReplay(Exception ex) {
LOG.error("Error while replaying the recording. {}", ex.getMessage(), ex);
- disposeWaitingDialog();
+ WaitingDialog.disposeWaitingDialog();
toggleWizardVisibility();
JOptionPane.showMessageDialog(this,
"Error while replaying the recording. " + System.lineSeparator() +
@@ -433,33 +372,17 @@ public void onFailReplay(Exception ex) {
}
public void displayReplayWaitingScreen() {
- displayWaitingScreen("We are replaying the test plan, please wait...");
- }
-
- protected void displayWaitingScreen(String message) {
- runDialog = JMeterElementUtils.makeWaitingFrame(message);
- runDialog.pack();
- runDialog.repaint();
- runDialog.setAlwaysOnTop(true);
- runDialog.setVisible(true);
- runDialog.toFront();
- }
-
- public void disposeWaitingDialog() {
- runDialog.dispose();
- runDialog.setVisible(false);
+ WaitingDialog.displayWaitingScreen("Replaying Test Plan",
+ "We are replaying the test plan, please wait...");
}
protected void startReplayWorker() {
replayWorker.execute();
}
- public void displayApplyingSuggestionsWaitingScreen() {
- displayWaitingScreen("We are applying the suggestions, please wait...");
- }
-
public void displayGeneratingSuggestionsWaitingScreen() {
- displayWaitingScreen("We are generating suggestions, please wait...");
+ WaitingDialog.displayWaitingScreen("Generating suggestions",
+ "We are generating suggestions, please wait...");
}
public CorrelationTemplatesRepositoriesConfiguration getRepositoriesConfiguration() {
diff --git a/src/test/java/com/blazemeter/jmeter/correlation/core/analysis/AnalysisReporterTest.java b/src/test/java/com/blazemeter/jmeter/correlation/core/analysis/AnalysisReporterTest.java
index bcbd27c..b1cbe35 100644
--- a/src/test/java/com/blazemeter/jmeter/correlation/core/analysis/AnalysisReporterTest.java
+++ b/src/test/java/com/blazemeter/jmeter/correlation/core/analysis/AnalysisReporterTest.java
@@ -1,6 +1,7 @@
package com.blazemeter.jmeter.correlation.core.analysis;
import static org.assertj.core.api.Assertions.assertThat;
+
import com.blazemeter.jmeter.correlation.JMeterTestUtils;
import com.blazemeter.jmeter.correlation.core.CorrelationEngine;
import com.blazemeter.jmeter.correlation.core.CorrelationRulePartTestElement;
@@ -23,14 +24,9 @@
@RunWith(MockitoJUnitRunner.class)
public class AnalysisReporterTest extends AnalysisTest {
- @Mock
- private CorrelationComponentsRegistry registry;
- private CorrelationEngine engine = new CorrelationEngine();
-
@Before
public void setup() throws IOException {
JMeterTestUtils.setupUpdatedJMeter();
- engine = new CorrelationEngine();
AnalysisReporter.startCollecting();
}
@@ -43,8 +39,8 @@ public void tearDown() {
public void shouldAddExtractorInformationWhenReportWithRegexCorrExtractor() throws IOException {
extractor.setVariableName(VALUE_NAME);
HTTPSamplerBase loggedUserRequest = createLoggedUserRequest();
- AnalysisReporter.report(extractor, TOKEN_VALUE, loggedUserRequest, VALUE_NAME);
- AnalysisReporter.Report report = AnalysisReporter.getReport(extractor);
+ AnalysisReporter.report(extractor, loggedUserRequest, extractor.getTarget().toString(),
+ TOKEN_VALUE);
String reportString = AnalysisReporter.getReporter().getReportAsString();
assertThat(reportString)
.isEqualToIgnoringWhitespace(getExpectedReport(extractor));
@@ -55,19 +51,19 @@ public void shouldAddReplacementInformationWhenReportWithRegexCorrReplacement()
throws IOException {
replacement.setVariableName(VALUE_NAME);
HTTPSamplerBase loggedUserRequest = createLoggedUserRequest();
- AnalysisReporter.report(replacement, TOKEN_VALUE, loggedUserRequest, VALUE_NAME);
+ AnalysisReporter.report(replacement, loggedUserRequest, TOKEN_VALUE);
String reportString = AnalysisReporter.getReporter().getReportAsString();
List>> parts = Collections
.singletonList(Pair.of(LOGGED_REQUEST_NAME, replacement));
assertThat(reportString)
- .isEqualToIgnoringWhitespace(getExpectedAnalysisReport(parts));
+ .isEqualToIgnoringWhitespace(getExpectedReport(parts));
}
@Test
public void shouldNotAddReportsWhenNotCollecting() {
AnalysisReporter.stopCollecting();
extractor.setVariableName(VALUE_NAME);
- AnalysisReporter.report(extractor, TOKEN_VALUE, LOGGED_REQUEST_NAME, VALUE_NAME);
+ AnalysisReporter.report(extractor, (Object) LOGGED_REQUEST_NAME, VALUE_NAME, TOKEN_VALUE);
String reportString = AnalysisReporter.getReporter().getReportAsString();
assertThat(reportString).isEqualToIgnoringWhitespace(AnalysisReporter.NO_REPORT);
}
@@ -87,7 +83,8 @@ public void shouldGenerateCorrelationSuggestionsWhenGenerateCorrelationSuggestio
throws IOException {
extractor.setVariableName(VALUE_NAME);
HTTPSamplerBase loggedUserRequest = createLoggedUserRequest();
- AnalysisReporter.report(extractor, TOKEN_VALUE, loggedUserRequest, VALUE_NAME);
+ AnalysisReporter.report(extractor, loggedUserRequest, extractor.getTarget().toString(),
+ TOKEN_VALUE);
List suggestions = AnalysisReporter.generateCorrelationSuggestions();
List expectedSuggestions = Collections
.singletonList(createExpectedSuggestions(loggedUserRequest));
@@ -99,12 +96,11 @@ private CorrelationSuggestion createExpectedSuggestions(HTTPSamplerBase affected
suggestion.setParamName(VALUE_NAME);
suggestion.setOriginalValue(TOKEN_VALUE);
ExtractionSuggestion extractionSuggestion
- = new ExtractionSuggestion((RegexCorrelationExtractor>) extractor, affectedRequest);
-
+ = new ExtractionSuggestion(extractor, affectedRequest);
extractionSuggestion.setName(VALUE_NAME);
- extractionSuggestion.setSource("Correlation Analysis");
+ extractionSuggestion.setSource(extractor.getTarget().toString());
extractionSuggestion.setValue(TOKEN_VALUE);
suggestion.addExtractionSuggestion(extractionSuggestion);
return suggestion;
}
-}
\ No newline at end of file
+}
diff --git a/src/test/java/com/blazemeter/jmeter/correlation/core/analysis/AnalysisTest.java b/src/test/java/com/blazemeter/jmeter/correlation/core/analysis/AnalysisTest.java
index 60a49e9..c8bcc97 100644
--- a/src/test/java/com/blazemeter/jmeter/correlation/core/analysis/AnalysisTest.java
+++ b/src/test/java/com/blazemeter/jmeter/correlation/core/analysis/AnalysisTest.java
@@ -1,6 +1,7 @@
package com.blazemeter.jmeter.correlation.core.analysis;
import static com.blazemeter.jmeter.correlation.TestUtils.findTestFile;
+
import com.blazemeter.jmeter.correlation.core.CorrelationRulePartTestElement;
import com.blazemeter.jmeter.correlation.core.extractors.CorrelationExtractor;
import com.blazemeter.jmeter.correlation.core.extractors.RegexCorrelationExtractor;
@@ -15,9 +16,8 @@
import org.apache.jmeter.save.SaveService;
public class AnalysisTest {
- protected final String LOG_REQUEST_NAME = "/login-1";
+
protected final String LOGGED_REQUEST_NAME = "/loggedUser-2";
- protected final String CALL_REQUEST_NAME = "/callToAction-3";
protected final String VALUE_NAME = "token";
protected final String TOKEN_VALUE = "abc123";
@@ -37,55 +37,43 @@ protected String getExpectedReport(
StringBuilder reportBuilder = new StringBuilder();
String RL = System.lineSeparator();
reportBuilder.append("Correlations Report:").append(RL)
- .append("Total rules appliances=")
+ .append(" Total rules appliances=")
.append(parts.size()).append(".").append(RL);
reportBuilder.append(" Details by rule part:").append(RL);
for (Pair> part : parts) {
CorrelationRulePartTestElement> element = part.getRight();
- reportBuilder.append(" Type='").append(element.getClass().getSimpleName())
- .append("'. Rule Part=")
- .append(element.toString()).append(RL);
- reportBuilder.append(" Can be applied to 1 elements.").append(RL);
- reportBuilder.append(" Entries: ").append(RL);
- reportBuilder.append(" - {value='").append(TOKEN_VALUE).append("' ")
- .append(getAction(element))
- .append(" at 'Correlation Analysis' in '")
- .append(part.getLeft()).append("' with variable name 'token'}").append(RL);
+ reportBuilder.append(" Type=").append(element.getClass().getSimpleName()).append(RL)
+ .append(" Reference Name=")
+ .append(getRefVarName(part.getRight())).append(RL)
+ .append(" Rule Part=").append(part.getRight()).append(RL);
+
+ reportBuilder.append("\t\tCan be applied to 1 elements.").append(RL);
+ reportBuilder.append("\t\t Entries: ").append(RL);
+ reportBuilder.append(" - { value='")
+ .append(TOKEN_VALUE)
+ .append("' at '")
+ .append(getLocationFrom(part.getRight())).append("' ")
+ .append("in '")
+ .append(part.getLeft()).append("'}").append(RL);
}
return reportBuilder.toString();
}
- protected String getExpectedAnalysisReport(
- List>> parts) {
- StringBuilder reportBuilder = new StringBuilder();
- String RL = System.lineSeparator();
- reportBuilder.append("Correlations Report:").append(RL)
- .append("Total rules appliances=")
- .append(parts.size()).append(".").append(RL);
-
- reportBuilder.append(" Details by rule part:").append(RL);
- for (Pair> part : parts) {
- CorrelationRulePartTestElement> element = part.getRight();
- reportBuilder.append(" Type='").append(element.getClass().getSimpleName())
- .append("'. Rule Part=")
- .append(element.toString()).append(RL);
- reportBuilder.append(" Can be applied to 1 elements.").append(RL);
- reportBuilder.append(" Entries: ").append(RL);
- reportBuilder.append(" - {value='").append(TOKEN_VALUE).append("' ")
- .append(getAction(element))
- .append(" at 'Correlation Analysis' in '")
- .append(part.getLeft()).append("' with variable name 'token'}").append(RL);
+ private String getLocationFrom(CorrelationRulePartTestElement> right) {
+ if (right instanceof CorrelationExtractor) {
+ return ((CorrelationExtractor>) right).getTarget().toString();
}
- return reportBuilder.toString();
+ return "Correlation Analysis";
}
- private static String getAction(CorrelationRulePartTestElement> part) {
- if (part instanceof CorrelationExtractor) {
- return "extracted";
+ private String getRefVarName(CorrelationRulePartTestElement> right) {
+ if (right instanceof CorrelationExtractor) {
+ return ((CorrelationExtractor>) right).getVariableName();
+ } else if (right instanceof CorrelationReplacement) {
+ return ((CorrelationReplacement>) right).getVariableName();
}
-
- return "replaced";
+ return "Unsupported CorrelationPartTestElement";
}
protected HTTPSamplerBase createLoggedUserRequest() throws IOException {
diff --git a/src/test/java/com/blazemeter/jmeter/correlation/core/suggestions/SuggestionGeneratorIT.java b/src/test/java/com/blazemeter/jmeter/correlation/core/suggestions/SuggestionGeneratorIT.java
index 67ed7d2..44c41e2 100644
--- a/src/test/java/com/blazemeter/jmeter/correlation/core/suggestions/SuggestionGeneratorIT.java
+++ b/src/test/java/com/blazemeter/jmeter/correlation/core/suggestions/SuggestionGeneratorIT.java
@@ -12,6 +12,7 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
import java.util.Optional;
import org.assertj.core.api.JUnitSoftAssertions;
@@ -25,6 +26,7 @@
@RunWith(MockitoJUnitRunner.class)
public class SuggestionGeneratorIT {
+
private static final Logger LOG = LoggerFactory.getLogger(SuggestionGeneratorIT.class);
@Rule
@@ -128,7 +130,7 @@ private boolean didntLoadTestPlanToContextSuccessfully() {
return false;
}
-// @Test // Need to mock the node supplier
+ // @Test // Need to mock the node supplier
public void shouldReturnListWhenGenerateSuggestionsWithValidContext() {
if (didntLoadedTemplateToContextSuccessfully()) {
return;
@@ -143,14 +145,16 @@ public void shouldReturnListWhenGenerateSuggestionsWithValidContext() {
}
analysisContext.setRegistry(CorrelationComponentsRegistry.getNewInstance());
- List suggestions = suggestionGenerator.generateSuggestions(analysisContext);
+ List suggestions = suggestionGenerator.generateSuggestions(
+ analysisContext);
softly.assertThat(suggestions).isNotEmpty();
softly.assertThat(suggestions.size()).isEqualTo(1);
}
private boolean didntLoadRecordingTraceToContextSuccessfully() {
String recordingTraceFilepath = "/recordings/recordingTrace/recordingWithNonces.jtl";
- Optional recordingTraceOptional = TestUtils.getFilePathFromResources(recordingTraceFilepath,
+ Optional recordingTraceOptional = TestUtils.getFilePathFromResources(
+ recordingTraceFilepath,
getClass());
if (!recordingTraceOptional.isPresent()) {
LOG.error("Recording trace not found at '{}'. Skipping test.", recordingTraceFilepath);
@@ -161,7 +165,7 @@ private boolean didntLoadRecordingTraceToContextSuccessfully() {
return false;
}
-// @Test
+ // @Test
public void shouldReturnListOfRulesWhenParseToRulesWhenApplySuggestions() {
if (didntLoadedTemplateToContextSuccessfully()) {
return;
@@ -176,29 +180,15 @@ public void shouldReturnListOfRulesWhenParseToRulesWhenApplySuggestions() {
}
analysisContext.setRegistry(CorrelationComponentsRegistry.getNewInstance());
- List suggestions = suggestionGenerator.generateSuggestions(analysisContext);
+ List suggestions = suggestionGenerator.generateSuggestions(
+ analysisContext);
softly.assertThat(suggestions).isNotEmpty();
softly.assertThat(suggestions.size()).isEqualTo(1);
- List correlationRules = suggestionGenerator.parseToRules(suggestions);
+ HashMap correlationRules = suggestionGenerator.parseToRules(
+ suggestions);
softly.assertThat(correlationRules).isNotEmpty();
softly.assertThat(correlationRules.size()).isEqualTo(2);
}
- @Test
- public void shouldSuccessfullyModifyTestPlanWhen() {
- if (didntLoadedTemplateToContextSuccessfully()) {
- return;
- }
-
- if (didntLoadTestPlanToContextSuccessfully()) {
- return;
- }
-
- if (didntLoadRecordingTraceToContextSuccessfully()) {
- return;
- }
- analysisContext.setRegistry(CorrelationComponentsRegistry.getNewInstance());
- suggestionGenerator.applySuggestions(suggestionGenerator.generateSuggestions(analysisContext));
- }
}
diff --git a/src/test/java/com/blazemeter/jmeter/correlation/core/suggestions/SuggestionGeneratorTest.java b/src/test/java/com/blazemeter/jmeter/correlation/core/suggestions/SuggestionGeneratorTest.java
index c92fe9d..52380a7 100644
--- a/src/test/java/com/blazemeter/jmeter/correlation/core/suggestions/SuggestionGeneratorTest.java
+++ b/src/test/java/com/blazemeter/jmeter/correlation/core/suggestions/SuggestionGeneratorTest.java
@@ -2,6 +2,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
+
import com.blazemeter.jmeter.correlation.core.automatic.CorrelationSuggestion;
import com.blazemeter.jmeter.correlation.core.suggestions.context.CorrelationContext;
import com.blazemeter.jmeter.correlation.core.suggestions.method.CorrelationMethod;
@@ -18,6 +19,7 @@
@RunWith(MockitoJUnitRunner.class)
public class SuggestionGeneratorTest {
+
@Mock
private CorrelationMethod method;
private SuggestionGenerator suggestionGenerator;
@@ -33,11 +35,6 @@ private CorrelationMethod getCorrelationMethod() {
public List generateSuggestions(CorrelationContext context) {
return new ArrayList<>();
}
-
- @Override
- public void applySuggestions(List suggestions) {
- // Do nothing
- }
};
}
@@ -73,4 +70,4 @@ public void shouldCallMethodGenerateSuggestions() {
suggestionGenerator.generateSuggestions(getBasicCorrelationContext());
verify(method).generateSuggestions(any());
}
-}
\ No newline at end of file
+}
diff --git a/src/test/java/com/blazemeter/jmeter/correlation/core/templates/SiebelTemplateRemovalTest.java b/src/test/java/com/blazemeter/jmeter/correlation/core/templates/SiebelTemplateRemovalTest.java
index 36e8583..963de06 100644
--- a/src/test/java/com/blazemeter/jmeter/correlation/core/templates/SiebelTemplateRemovalTest.java
+++ b/src/test/java/com/blazemeter/jmeter/correlation/core/templates/SiebelTemplateRemovalTest.java
@@ -14,6 +14,7 @@
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.List;
+import org.jetbrains.annotations.NotNull;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -21,28 +22,23 @@
public class SiebelTemplateRemovalTest {
-
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
- private File siebelJsonFile;
- private File localRepoFile;
-
@Before
public void setUp() throws Exception {
File binDir = temporaryFolder.newFolder("bin");
File templatesDir = new File(binDir, "templates");
+ assert templatesDir.mkdirs();
File correlationTemplatesDir = new File(binDir, "correlation-templates");
- templatesDir.mkdirs();
- correlationTemplatesDir.mkdirs();
+ assert correlationTemplatesDir.mkdirs();
File siebelTemplateFile = new File(templatesDir, "siebel-template.jmx");
- siebelTemplateFile.createNewFile();
- siebelJsonFile = new File(correlationTemplatesDir, "siebel-1.0-template.json");
- siebelJsonFile.createNewFile();
+ assert siebelTemplateFile.createNewFile();
+ File siebelJsonFile = new File(correlationTemplatesDir, "siebel-1.0-template.json");
+ assert siebelJsonFile.createNewFile();
writeSiebelJsonTemplate(siebelJsonFile);
-
- localRepoFile = new File(correlationTemplatesDir, "local-repository.json");
- localRepoFile.createNewFile();
+ File localRepoFile = new File(correlationTemplatesDir, "local-repository.json");
+ assert localRepoFile.createNewFile();
writeLocalRepository(localRepoFile);
}
@@ -79,6 +75,9 @@ public static File findFile(File directory, String fileName) {
if (files != null) {
for (File file : files) {
ret = findFile(file, fileName);
+ if (ret != null) {
+ break;
+ }
}
}
return ret;
@@ -90,19 +89,23 @@ public static boolean fileExists(File directory, String fileName) {
@Test
public void shouldRemoveSiebelTestPlanWhenDelete() throws Exception {
- SiebelTemplateRemoval.delete(temporaryFolder.getRoot().getAbsolutePath() + "/bin");
+ SiebelTemplateRemoval.delete(getTempBinPath());
assertFalse(fileExists(temporaryFolder.getRoot(), "siebel-template.jmx"));
}
+ private @NotNull String getTempBinPath() {
+ return Paths.get(temporaryFolder.getRoot().getAbsolutePath(), "bin").toString();
+ }
+
@Test
public void shouldDeleteJsonTemplateWhenDelete() throws Exception {
- SiebelTemplateRemoval.delete(temporaryFolder.getRoot().getAbsolutePath() + "/bin");
+ SiebelTemplateRemoval.delete(getTempBinPath());
assertFalse(fileExists(temporaryFolder.getRoot(), "siebel-1.0-template.json"));
}
@Test
public void shouldRemoveSiebelFromLocalRepositoryWhenDelete() throws Exception {
- SiebelTemplateRemoval.delete(temporaryFolder.getRoot().getAbsolutePath() + "/bin");
+ SiebelTemplateRemoval.delete(getTempBinPath());
File file = findFile(temporaryFolder.getRoot(), "local-repository.json");
List lines = Files.readAllLines(file.toPath().toAbsolutePath());
assertTrue(lines.size() == 1 && lines.get(0).equals("{ }"));
diff --git a/src/test/java/com/blazemeter/jmeter/correlation/gui/automatic/CorrelationSuggestionsPanelTest.java b/src/test/java/com/blazemeter/jmeter/correlation/gui/automatic/CorrelationSuggestionsPanelTest.java
index 06e3b7c..ec04eb0 100644
--- a/src/test/java/com/blazemeter/jmeter/correlation/gui/automatic/CorrelationSuggestionsPanelTest.java
+++ b/src/test/java/com/blazemeter/jmeter/correlation/gui/automatic/CorrelationSuggestionsPanelTest.java
@@ -4,15 +4,21 @@
import com.blazemeter.jmeter.correlation.SwingTestRunner;
import com.blazemeter.jmeter.correlation.core.automatic.CorrelationSuggestion;
import java.awt.event.ActionListener;
+import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
+import java.util.function.Supplier;
+
+import com.blazemeter.jmeter.correlation.core.automatic.JMeterElementUtils;
import org.assertj.core.api.JUnitSoftAssertions;
import org.assertj.swing.fixture.FrameFixture;
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+import us.abstracta.jmeter.javadsl.core.engines.JmeterEnvironment;
@RunWith(SwingTestRunner.class)
public class CorrelationSuggestionsPanelTest {
@@ -20,14 +26,15 @@ public class CorrelationSuggestionsPanelTest {
public JUnitSoftAssertions softly = new JUnitSoftAssertions();
private FrameFixture frame;
private CorrelationSuggestionsPanel panel;
+ private Supplier getRecordingTraceSupplier = () -> "";
+ public JmeterEnvironment jmeterEnvironment;
- @Mock
- private ActionListener listener;
@Before
public void setUp() throws Exception {
- panel = new CorrelationSuggestionsPanel(null);
+ panel = new CorrelationSuggestionsPanel(new CorrelationWizard());
frame = showInFrame(panel);
+ jmeterEnvironment = new JmeterEnvironment();
}
@After
@@ -67,4 +74,18 @@ public void shouldLoadSuggestionsWhenLoadSuggestions() {
softly.assertThat(currentSuggestionsCount).isNotEqualTo(initialSuggestionsCount);
softly.assertThat(currentSuggestionsCount).isEqualTo(1);
}
-}
\ No newline at end of file
+
+ @Ignore
+ @Test
+ public void shouldNotifyWhenApplySuggestionsButton() throws InterruptedException {
+ panel.loadSuggestions(generateSuggestions(10));
+ panel.setGetRecordingTraceSupplier(getRecordingTraceSupplier);
+ clickApply();
+ Thread.sleep(60000);
+ //frame.dialog().label("We are applying the suggestions, please wait...").requireVisible();
+ frame.optionPane().requireMessage("The suggestions were applied successfully to your Test Plan.\n" +
+ "Please review the changes and, when you are ready, replay to review the results.");
+ }
+
+ private void clickApply() {frame.button("correlateButton").click();}
+}
diff --git a/src/test/java/com/blazemeter/jmeter/correlation/gui/automatic/CorrelationWizardIT.java b/src/test/java/com/blazemeter/jmeter/correlation/gui/automatic/CorrelationWizardIT.java
index c672d60..6d93189 100644
--- a/src/test/java/com/blazemeter/jmeter/correlation/gui/automatic/CorrelationWizardIT.java
+++ b/src/test/java/com/blazemeter/jmeter/correlation/gui/automatic/CorrelationWizardIT.java
@@ -90,11 +90,6 @@ public void shouldExportSelectedTemplateVersionsWhenContinueClicked()
List selectedVersions = new ArrayList<>();
int initialSize = 0;
AtomicReference jtlTracePath = new AtomicReference<>();
- wizard.getTemplateSelectionPanel()
- .setStartNonCorrelatedAnalysis((selectedTemplates, jtlTrace) -> {
- selectedVersions.addAll(selectedTemplates);
- jtlTracePath.set(jtlTrace);
- });
templateSelectionPressContinue();
softly.assertThat(jtlTracePath.get()).isNotNull().as("JTL Trace Path");
@@ -113,11 +108,6 @@ public void shouldLoadTemplateVersionsWhenReloadClicked() {
List selectedVersions = new ArrayList<>();
int initialSize = 0;
AtomicReference jtlTracePath = new AtomicReference<>();
- wizard.getTemplateSelectionPanel()
- .setStartNonCorrelatedAnalysis((selectedTemplates, jtlTrace) -> {
- selectedVersions.addAll(selectedTemplates);
- jtlTracePath.set(jtlTrace);
- });
templateSelectionPressReloadTemplates();
templateSelectionPressContinue();