Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add fail option for regex extractor #6256

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.util.regex.PatternSyntaxException;

import org.apache.commons.text.StringEscapeUtils;
import org.apache.jmeter.assertions.AssertionResult;
import org.apache.jmeter.processor.PostProcessor;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.testelement.AbstractScopedTestElement;
Expand Down Expand Up @@ -71,6 +72,8 @@ public class RegexExtractor extends AbstractScopedTestElement implements PostPro

private static final String UNDERSCORE = "_"; // $NON-NLS-1$

private static final String FAILIFNOTFOUND = "RegexExtractor.fail_if_not_found";
vlsi marked this conversation as resolved.
Show resolved Hide resolved

private static final boolean USE_JAVA_REGEX = !JMeterUtils.getPropDefault(
"jmeter.regex.engine", "oro").equalsIgnoreCase("oro");

Expand Down Expand Up @@ -126,6 +129,9 @@ private void extractWithOroRegex(SampleResult previousResult, JMeterVariables va
try {
pattern = JMeterUtils.getPatternCache().getPattern(regex, Perl5Compiler.READ_ONLY_MASK);
List<MatchResult> matches = processMatches(pattern, regex, previousResult, matchNumber, vars);
if(matches.isEmpty() && isFailIfNotFound()){
failResult(previousResult);
}
int prevCount = 0;
String prevString = vars.get(refName + REF_MATCH_NR);
if (prevString != null) {
Expand Down Expand Up @@ -184,6 +190,9 @@ private void extractWithJavaRegex(SampleResult previousResult, JMeterVariables v
try {
pattern = JMeterUtils.compilePattern(regex);
List<java.util.regex.MatchResult> matches = processMatches(pattern, previousResult, matchNumber, vars);
if(matches.isEmpty() && isFailIfNotFound()){
failResult(previousResult);
}
int prevCount = 0;
String prevString = vars.get(refName + REF_MATCH_NR);
if (prevString != null) {
Expand Down Expand Up @@ -234,6 +243,22 @@ private void extractWithJavaRegex(SampleResult previousResult, JMeterVariables v
}
}

private void failResult(SampleResult previousResult){
AssertionResult res = new AssertionResult(getName());
res.setFailure(true);
String sourceDescription = useUrl() ? "URL"
: useHeaders() ? "response headers"
: useRequestHeaders() ? "request headers"
: useCode() ? "response code"
: useMessage() ? "response message"
: useUnescapedBody() ? "unescaped body"
: useBodyAsDocument() ? "document"
: "body"; // Covers both empty and USE_BODY cases
res.setFailureMessage("Pattern not found in " + sourceDescription + " - " + getRegex());
previousResult.addAssertionResult(res);
previousResult.setSuccessful(false);
}

private String getInputString(SampleResult result) {
String inputString = useUrl() ? result.getUrlAsString() // Bug 39707
: useHeaders() ? result.getResponseHeaders()
Expand Down Expand Up @@ -688,4 +713,14 @@ public boolean useMessage() {
public void setUseField(String actionCommand) {
set(getSchema().getMatchTarget(), actionCommand);
}

public void setFailIfNotFound(Boolean isFailing){
log.warn("Setting fail as " + isFailing);
setProperty(FAILIFNOTFOUND, isFailing);
}

public boolean isFailIfNotFound(){
return getPropertyAsBoolean(FAILIFNOTFOUND);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import javax.swing.ButtonGroup;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;

Expand All @@ -52,6 +53,7 @@ public class RegexExtractorGui extends AbstractPostProcessorGui {
private JLabeledTextField defaultField;
private JLabeledTextField matchNumberField;
private JLabeledTextField refNameField;
private JLabel failResultField;
private JRadioButton useBody;
private JRadioButton useUnescapedBody;
private JRadioButton useBodyAsDocument;
Expand All @@ -62,6 +64,7 @@ public class RegexExtractorGui extends AbstractPostProcessorGui {
private JRadioButton useMessage;
private ButtonGroup group;
private JCheckBox emptyDefaultValue;
private JCheckBox failResult;

public RegexExtractorGui() {
super();
Expand Down Expand Up @@ -93,6 +96,7 @@ public void configure(TestElement el) {
emptyDefaultValue.setSelected(re.isEmptyDefaultValue());
matchNumberField.setText(re.getMatchNumberAsString());
refNameField.setText(re.getRefName());
failResult.setSelected(re.isFailIfNotFound());
}
}

Expand Down Expand Up @@ -124,6 +128,7 @@ public void modifyTestElement(TestElement extractor) {
regex.setDefaultValue(defaultField.getText());
regex.setDefaultEmptyValue(emptyDefaultValue.isSelected());
regex.setMatchNumber(matchNumberField.getText());
regex.setFailIfNotFound(failResult.isSelected());
}
}

Expand All @@ -142,6 +147,7 @@ public void clearGui() {
emptyDefaultValue.setSelected(false);
refNameField.setText(""); //$NON-NLS-1$
matchNumberField.setText(""); //$NON-NLS-1$
failResult.setSelected(false);
}

private void init() { // WARNING: called from ctor so must not be overridden (i.e. must be private or final)
Expand Down Expand Up @@ -208,6 +214,8 @@ private JPanel makeParameterPanel() {
templateField = new JLabeledTextField(JMeterUtils.getResString("template_field")); //$NON-NLS-1$
refNameField = new JLabeledTextField(JMeterUtils.getResString("ref_name_field")); //$NON-NLS-1$
matchNumberField = new JLabeledTextField(JMeterUtils.getResString("match_num_field")); //$NON-NLS-1$
failResultField = new JLabel(JMeterUtils.getResString("fail_if_not_matched_field"));
failResult = new JCheckBox();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you use JEditableCheckBox here?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

emptyDefaultValue is also a JCheckBox(), so what would a JEditableCheckbox do better?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm using JLabel + JCheckBox here because it's nicer to have the label in the same row as the others and the checkbox in the column of the input fields

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JEditableCheckbox would allow using ${..} expressions while JCheckBox, see #5944

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, although the JEditableCheckbox is a nice feature to paramaterize scripts, I don't think it's a good usecase on this specific checkbox. I don't see a reason to parameterize a specific regex extractor. The other checkboxes on the Regex Extractor aren't an editable checkbox as well.
I can give it a try tho, If it doesn't help, it doesn't hurt


JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
Expand All @@ -220,6 +228,8 @@ private JPanel makeParameterPanel() {
resetContraints(gbc);
addField(panel, matchNumberField, gbc);
resetContraints(gbc);
addField(panel, failResultField, failResult, gbc);
resetContraints(gbc);
gbc.weighty = 1;

defaultField = new JLabeledTextField(JMeterUtils.getResString("default_value_field")); //$NON-NLS-1$
Expand Down Expand Up @@ -253,6 +263,14 @@ private static void addField(JPanel panel, JLabeledTextField field, GridBagConst
panel.add(item.get(1), gbc.clone());
}

private static void addField(JPanel panel, JLabel label, JCheckBox checkBox, GridBagConstraints gbc) {
panel.add(label, gbc.clone());
gbc.gridx++;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
panel.add(checkBox, gbc.clone());
}

// Next line
private static void resetContraints(GridBagConstraints gbc) {
gbc.gridx = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public void setUp() {
extractor.setThreadContext(jmctx);
extractor.setRefName("regVal");
result = new SampleResult();
result.setSuccessful(true);
String data = "<company-xmlext-query-ret><row><value field=\"RetCode\">LIS_OK</value>\n" +
"<value field=\"RetCodeExtension\"></value><value field=\"alias\"></value>\n" +
"<value field=\"positioncount\"></value><value field=\"invalidpincount\">0</value>\n" +
Expand Down Expand Up @@ -480,4 +481,100 @@ public void testScope2() {
final String found = vars.get("regVal");
assertTrue(found.equals("ONE") || found.equals("TWO"));
}

@Test
public void testFailIfNotFound() {
extractor.setRegex("notfound");
extractor.setTemplate("$1$");
extractor.setMatchNumber(1);
extractor.setFailIfNotFound(true);
extractor.process();
assertFalse(result.isSuccessful(), "Result should be marked as failed");
assertEquals(1, result.getAssertionResults().length, "Should have one assertion result");
assertEquals("Pattern not found in body - notfound",
result.getAssertionResults()[0].getFailureMessage(),
"Should have correct failure message with source");
}

@Test
public void testFailIfNotFoundWhenFound() {
extractor.setRegex("<value field=\"RetCode\">([^<]+)</value>");
extractor.setTemplate("$1$");
extractor.setMatchNumber(1);
extractor.setFailIfNotFound(true);
extractor.process();
assertTrue(result.isSuccessful(), "Result should remain successful when pattern is found");
assertEquals(0, result.getAssertionResults().length, "Should have no assertion results");
}

@Test
public void testNotFailIfNotFoundWhenNotFound() {
extractor.setRegex("notfound");
extractor.setTemplate("$1$");
extractor.setMatchNumber(1);
extractor.setFailIfNotFound(false);
extractor.process();
assertTrue(result.isSuccessful(), "Result should remain successful when failIfNotFound is false");
assertEquals(0, result.getAssertionResults().length, "Should have no assertion results");
}

@Test
public void testFailIfNotFoundWithMatchAll() {
extractor.setRegex("notfound");
extractor.setTemplate("$1$");
extractor.setMatchNumber(-1);
extractor.setFailIfNotFound(true);
extractor.process();
assertFalse(result.isSuccessful(), "Result should be marked as failed");
assertEquals("0", vars.get("regVal_matchNr"), "matchNr should be 0 when no matches found");
assertEquals(1, result.getAssertionResults().length, "Should have one assertion result");
}

@Test
public void testFailIfNotFoundWithRandomMatch() {
extractor.setRegex("notfound");
extractor.setTemplate("$1$");
extractor.setMatchNumber(0);
extractor.setFailIfNotFound(true);
extractor.process();
assertFalse(result.isSuccessful(), "Result should be marked as failed");
assertNull(vars.get("regVal_matchNr"), "matchNr should not be set for random match mode");
}

@Test
public void testFailIfNotFoundWithDifferentSources() {
extractor.setUseField(RegexExtractor.USE_HDRS); // Headers
extractor.setRegex("notfound");
extractor.setFailIfNotFound(true);
extractor.process();
assertEquals("Pattern not found in response headers - notfound",
result.getAssertionResults()[0].getFailureMessage());

result = new SampleResult(); // Reset result
result.setSuccessful(true);
jmctx.setPreviousResult(result);
extractor.setUseField(RegexExtractor.USE_URL); // URL
extractor.process();
assertEquals("Pattern not found in URL - notfound",
result.getAssertionResults()[0].getFailureMessage());

result = new SampleResult();
result.setSuccessful(true);
jmctx.setPreviousResult(result);
extractor.setUseField(RegexExtractor.USE_CODE); // Response code
extractor.process();
assertEquals("Pattern not found in response code - notfound",
result.getAssertionResults()[0].getFailureMessage());
}

@Test
public void testFailIfNotFoundWithEmptyResponse() {
result.setResponseData("", null);
extractor.setRegex("something");
extractor.setFailIfNotFound(true);
extractor.process();
assertFalse(result.isSuccessful(), "Result should be marked as failed");
assertEquals("Pattern not found in body - something",
result.getAssertionResults()[0].getFailureMessage());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@ export_transactions_menu=Export transactions for report
export_transactions_names_action=Export transactions for report
export_transactions_title=Export Transactions Result
expression_field=CSS Selector expression\:
fail_if_not_matched_field=Fail if not matched
field_name=Field name
file=File
file_already_in_use=That file is already in use
Expand Down
Loading