Author: sebb
Date: Mon Feb 1 00:17:15 2010
New Revision: 905149
URL: http://svn.apache.org/viewvc?rev=905149&view=rev
Log:
Add Sampler scope selection to XPathExtractor
Modified:
jakarta/jmeter/trunk/docs/images/screenshots/xpath_extractor.png
jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/RegexExtractor.java
jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/XPathExtractor.java
jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/gui/RegexExtractorGui.java
jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/gui/XPathExtractorGui.java
jakarta/jmeter/trunk/src/core/org/apache/jmeter/testelement/AbstractScopedTestElement.java
jakarta/jmeter/trunk/test/src/org/apache/jmeter/extractor/TestXPathExtractor.java
jakarta/jmeter/trunk/xdocs/changes.xml
jakarta/jmeter/trunk/xdocs/images/screenshots/xpath_extractor.png
jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml
Modified: jakarta/jmeter/trunk/docs/images/screenshots/xpath_extractor.png
URL:
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/docs/images/screenshots/xpath_extractor.png?rev=905149&r1=905148&r2=905149&view=diff
==============================================================================
Binary files - no diff available.
Modified:
jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/RegexExtractor.java
URL:
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/RegexExtractor.java?rev=905149&r1=905148&r2=905149&view=diff
==============================================================================
---
jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/RegexExtractor.java
(original)
+++
jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/RegexExtractor.java
Mon Feb 1 00:17:15 2010
@@ -177,17 +177,7 @@
}
private List<MatchResult> processMatches(String regex, SampleResult
result, int matchNumber) {
- List<SampleResult> sampleList = new ArrayList<SampleResult>();
-
- String scope = fetchScope();
- if (isScopeParent(scope) || isScopeAll(scope)) {
- sampleList.add(result);
- }
- if (isScopeChildren(scope) || isScopeAll(scope)) {
- for (SampleResult subResult : result.getSubResults()) {
- sampleList.add(subResult);
- }
- }
+ List<SampleResult> sampleList = getSampleList(result);
if (log.isDebugEnabled()) {
log.debug("Regex = " + regex);
Modified:
jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/XPathExtractor.java
URL:
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/XPathExtractor.java?rev=905149&r1=905148&r2=905149&view=diff
==============================================================================
---
jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/XPathExtractor.java
(original)
+++
jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/XPathExtractor.java
Mon Feb 1 00:17:15 2010
@@ -22,6 +22,8 @@
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
@@ -29,7 +31,7 @@
import org.apache.jmeter.assertions.AssertionResult;
import org.apache.jmeter.processor.PostProcessor;
import org.apache.jmeter.samplers.SampleResult;
-import org.apache.jmeter.testelement.AbstractTestElement;
+import org.apache.jmeter.testelement.AbstractScopedTestElement;
import org.apache.jmeter.testelement.property.BooleanProperty;
import org.apache.jmeter.threads.JMeterContext;
import org.apache.jmeter.threads.JMeterVariables;
@@ -77,7 +79,7 @@
*
* See Bugzilla: 37183
*/
-public class XPathExtractor extends AbstractTestElement implements
+public class XPathExtractor extends AbstractScopedTestElement implements
PostProcessor, Serializable {
private static final Logger log = LoggingManager.getLoggerForClass();
@@ -105,6 +107,10 @@
return new StringBuilder(s1).append("_").append(s2).toString(); //
$NON-NLS-1$
}
+ private String concat(String s1, int i){
+ return new StringBuilder(s1).append("_").append(i).toString(); //
$NON-NLS-1$
+ }
+
/**
* Do the job - extract value from (X)HTML response using XPath Query.
* Return value as variable defined by REFNAME. Returns DEFAULT value
@@ -119,12 +125,42 @@
JMeterVariables vars = context.getVariables();
String refName = getRefName();
vars.put(refName, getDefaultValue());
- vars.put(concat(refName,MATCH_NR), "0"); // In case parse fails //
$NON-NLS-1$
+ final String matchNR = concat(refName,MATCH_NR);
+ int prevCount=0; // number of previous matches
+ try {
+ prevCount=Integer.parseInt(vars.get(matchNR));
+ } catch (NumberFormatException e) {
+ // ignored
+ }
+ vars.put(matchNR, "0"); // In case parse fails // $NON-NLS-1$
vars.remove(concat(refName,"1")); // In case parse fails // $NON-NLS-1$
+ List<SampleResult> samples = getSampleList(previousResult);
try{
- Document d = parseResponse(previousResult);
- getValuesForXPath(d,getXPathQuery(),vars, refName);
+ List<String> matches = new ArrayList<String>();
+ for (SampleResult res : samples) {
+ Document d = parseResponse(res);
+ getValuesForXPath(d,getXPathQuery(),matches);
+ }
+ final int matchCount = matches.size();
+ vars.put(matchNR, String.valueOf(matchCount));
+ if (matchCount > 0){
+ String value = matches.get(0);
+ if (value != null) {
+ vars.put(refName, value);
+ }
+ for(int i=0; i < matchCount; i++){
+ value = matches.get(i);
+ if (value != null) {
+ vars.put(concat(refName,i+1),matches.get(i));
+ }
+ }
+ }
+ vars.remove(concat(refName,matchCount+1)); // Just in case
+ // Clear any other remaining variables
+ for(int i=matchCount+2; i <= prevCount; i++) {
+ vars.remove(concat(refName,i));
+ }
}catch(IOException e){// e.g. DTD not reachable
final String errorMessage = "IOException on ("+getXPathQuery()+")";
log.error(errorMessage,e);
@@ -253,7 +289,6 @@
{
//TODO: validate contentType for reasonable types?
- //TODO: is it really necessary to recode the data?
// NOTE: responseData encoding is server specific
// Therefore we do byte -> unicode -> byte conversion
// to ensure UTF-8 encoding as required by XPathUtil
@@ -269,20 +304,20 @@
/**
* Extract value from Document d by XPath query.
- * @param d
- * @param query
+ * @param d the document
+ * @param query the query to execute
+ * @param matchStrings list of matched strings (may include nulls)
+ *
* @throws TransformerException
*/
- private void getValuesForXPath(Document d,String query, JMeterVariables
vars, String refName)
- throws TransformerException
- {
+ private void getValuesForXPath(Document d,String query, List<String>
matchStrings)
+ throws TransformerException {
String val = null;
- XObject xObject = XPathAPI.eval(d, query);
+ XObject xObject = XPathAPI.eval(d, query);
final int objectType = xObject.getType();
if (objectType == XObject.CLASS_NODESET) {
NodeList matches = xObject.nodelist();
int length = matches.getLength();
- vars.put(concat(refName,MATCH_NR), String.valueOf(length));
for (int i = 0 ; i < length; i++) {
Node match = matches.item(i);
if ( match instanceof Element){
@@ -300,25 +335,16 @@
} else {
val = match.getNodeValue();
}
- if ( val!=null){
- if (i==0) {// Treat 1st match specially
- vars.put(refName,val);
- }
- vars.put(concat(refName,String.valueOf(i+1)),val);
- }
+ matchStrings.add(val);
}
- vars.remove(concat(refName,String.valueOf(length+1)));
} else if (objectType == XObject.CLASS_NULL
|| objectType == XObject.CLASS_UNKNOWN
|| objectType == XObject.CLASS_UNRESOLVEDVARIABLE) {
log.warn("Unexpected object type: "+xObject.getTypeString()+"
returned for: "+getXPathQuery());
- } else {
+ } else {
val = xObject.toString();
- vars.put(concat(refName, MATCH_NR), "1");
- vars.put(refName, val);
- vars.put(concat(refName, "1"), val);
- vars.remove(concat(refName, "2"));
- }
+ matchStrings.add(val);
+ }
}
public void setWhitespace(boolean selected) {
Modified:
jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/gui/RegexExtractorGui.java
URL:
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/gui/RegexExtractorGui.java?rev=905149&r1=905148&r2=905149&view=diff
==============================================================================
---
jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/gui/RegexExtractorGui.java
(original)
+++
jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/gui/RegexExtractorGui.java
Mon Feb 1 00:17:15 2010
@@ -32,6 +32,7 @@
import org.apache.jmeter.extractor.RegexExtractor;
import org.apache.jmeter.processor.gui.AbstractPostProcessorGui;
+import org.apache.jmeter.testelement.AbstractScopedTestElement;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.gui.JLabeledTextField;
@@ -99,7 +100,7 @@
* @see org.apache.jmeter.gui.JMeterGUIComponent#createTestElement()
*/
public TestElement createTestElement() {
- RegexExtractor extractor = new RegexExtractor();
+ AbstractScopedTestElement extractor = new RegexExtractor();
modifyTestElement(extractor);
return extractor;
}
Modified:
jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/gui/XPathExtractorGui.java
URL:
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/gui/XPathExtractorGui.java?rev=905149&r1=905148&r2=905149&view=diff
==============================================================================
---
jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/gui/XPathExtractorGui.java
(original)
+++
jakarta/jmeter/trunk/src/components/org/apache/jmeter/extractor/gui/XPathExtractorGui.java
Mon Feb 1 00:17:15 2010
@@ -44,16 +44,21 @@
private static final long serialVersionUID = 240L;
- private JLabeledTextField defaultField;
+ private final JLabeledTextField defaultField =
+ new
JLabeledTextField(JMeterUtils.getResString("default_value_field"));//$NON-NLS-1$
- private JLabeledTextField xpathQueryField;
+ private final JLabeledTextField xpathQueryField =
+ new
JLabeledTextField(JMeterUtils.getResString("xpath_extractor_query"));//$NON-NLS-1$
- private JLabeledTextField refNameField;
+ private final JLabeledTextField refNameField =
+ new
JLabeledTextField(JMeterUtils.getResString("ref_name_field"));//$NON-NLS-1$
- private JCheckBox getFragment; // Should we return fragment as text,
rather than text of fragment?
-
- private XMLConfPanel xml;
+ // Should we return fragment as text, rather than text of fragment?
+ private final JCheckBox getFragment =
+ new
JCheckBox(JMeterUtils.getResString("xpath_extractor_fragment"));//$NON-NLS-1$
+ private final XMLConfPanel xml = new XMLConfPanel();
+
public String getLabelResource() {
return "xpath_extractor_title"; //$NON-NLS-1$
}
@@ -67,6 +72,7 @@
public void configure(TestElement el) {
super.configure(el);
XPathExtractor xpe = (XPathExtractor) el;
+ showScopeSettings(xpe);
xpathQueryField.setText(xpe.getXPathQuery());
defaultField.setText(xpe.getDefaultValue());
refNameField.setText(xpe.getRefName());
@@ -85,6 +91,7 @@
super.configureTestElement(extractor);
if ( extractor instanceof XPathExtractor){
XPathExtractor xpath = (XPathExtractor)extractor;
+ saveScopeSettings(xpath);
xpath.setDefaultValue(defaultField.getText());
xpath.setRefName(refNameField.getText());
xpath.setXPathQuery(xpathQueryField.getText());
@@ -112,11 +119,10 @@
Box box = Box.createVerticalBox();
box.add(makeTitlePanel());
- xml = new XMLConfPanel();
+ box.add(createScopePanel());
xml.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(),
JMeterUtils
.getResString("xpath_assertion_option"))); //$NON-NLS-1$
box.add(xml);
- getFragment = new
JCheckBox(JMeterUtils.getResString("xpath_extractor_fragment"));//$NON-NLS-1$
box.add(getFragment);
box.add(makeParameterPanel());
add(box, BorderLayout.NORTH);
@@ -124,10 +130,6 @@
private JPanel makeParameterPanel() {
- xpathQueryField = new
JLabeledTextField(JMeterUtils.getResString("xpath_extractor_query"));//$NON-NLS-1$
- defaultField = new
JLabeledTextField(JMeterUtils.getResString("default_value_field"));//$NON-NLS-1$
- refNameField = new
JLabeledTextField(JMeterUtils.getResString("ref_name_field"));//$NON-NLS-1$
-
JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
initConstraints(gbc);
Modified:
jakarta/jmeter/trunk/src/core/org/apache/jmeter/testelement/AbstractScopedTestElement.java
URL:
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/core/org/apache/jmeter/testelement/AbstractScopedTestElement.java?rev=905149&r1=905148&r2=905149&view=diff
==============================================================================
---
jakarta/jmeter/trunk/src/core/org/apache/jmeter/testelement/AbstractScopedTestElement.java
(original)
+++
jakarta/jmeter/trunk/src/core/org/apache/jmeter/testelement/AbstractScopedTestElement.java
Mon Feb 1 00:17:15 2010
@@ -18,6 +18,11 @@
package org.apache.jmeter.testelement;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.jmeter.samplers.SampleResult;
+
/**
* <p>
* Super-class for TestElements that can be applied to main sample,
sub-samples or both.
@@ -94,4 +99,26 @@
public void setScopeAll() {
setProperty(SCOPE, SCOPE_ALL);
}
+
+ /**
+ * Generate a list of qualifying sample results,
+ * depending on the scope.
+ *
+ * @param result current sample
+ * @return list containing the current sample and/or its child samples
+ */
+ protected List<SampleResult> getSampleList(SampleResult result) {
+ List<SampleResult> sampleList = new ArrayList<SampleResult>();
+
+ String scope = fetchScope();
+ if (isScopeParent(scope) || isScopeAll(scope)) {
+ sampleList.add(result);
+ }
+ if (isScopeChildren(scope) || isScopeAll(scope)) {
+ for (SampleResult subResult : result.getSubResults()) {
+ sampleList.add(subResult);
+ }
+ }
+ return sampleList;
+ }
}
Modified:
jakarta/jmeter/trunk/test/src/org/apache/jmeter/extractor/TestXPathExtractor.java
URL:
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/test/src/org/apache/jmeter/extractor/TestXPathExtractor.java?rev=905149&r1=905148&r2=905149&view=diff
==============================================================================
---
jakarta/jmeter/trunk/test/src/org/apache/jmeter/extractor/TestXPathExtractor.java
(original)
+++
jakarta/jmeter/trunk/test/src/org/apache/jmeter/extractor/TestXPathExtractor.java
Mon Feb 1 00:17:15 2010
@@ -19,6 +19,8 @@
package org.apache.jmeter.extractor;
+import java.io.UnsupportedEncodingException;
+
import junit.framework.TestCase;
import org.apache.jmeter.samplers.SampleResult;
@@ -31,6 +33,8 @@
private SampleResult result;
+ private String data;
+
private JMeterVariables vars;
public TestXPathExtractor(String name) {
@@ -42,15 +46,15 @@
private final static String VAL_NAME = "value";
private final static String VAL_NAME_NR = "value_matchNr";
@Override
- public void setUp() {
+ public void setUp() throws UnsupportedEncodingException {
jmctx = JMeterContextService.getContext();
extractor = new XPathExtractor();
extractor.setThreadContext(jmctx);// This would be done by the run
command
extractor.setRefName(VAL_NAME);
extractor.setDefaultValue("Default");
result = new SampleResult();
- String data = "<book><preface
title='Intro'>zero</preface><page>one</page><page>two</page><empty></empty><a><b></b></a></book>";
- result.setResponseData(data.getBytes());
+ data = "<book><preface
title='Intro'>zero</preface><page>one</page><page>two</page><empty></empty><a><b></b></a></book>";
+ result.setResponseData(data.getBytes("UTF-8"));
vars = new JMeterVariables();
jmctx.setVariables(vars);
jmctx.setPreviousResult(result);
@@ -150,6 +154,56 @@
assertEquals("<a><b/></a>", vars.get(VAL_NAME));
}
+ public void testScope(){
+ extractor.setXPathQuery("/book/preface");
+ extractor.process();
+ assertEquals("zero", vars.get(VAL_NAME));
+ assertEquals("1", vars.get(VAL_NAME_NR));
+ assertEquals("zero", vars.get(VAL_NAME+"_1"));
+ assertNull(vars.get(VAL_NAME+"_2"));
+
+ extractor.setScopeChildren(); // There aren't any
+ extractor.process();
+ assertEquals("Default", vars.get(VAL_NAME));
+ assertEquals("0", vars.get(VAL_NAME_NR));
+ assertNull(vars.get(VAL_NAME+"_1"));
+
+ extractor.setScopeAll(); // same as Parent
+ extractor.process();
+ assertEquals("zero", vars.get(VAL_NAME));
+ assertEquals("1", vars.get(VAL_NAME_NR));
+ assertEquals("zero", vars.get(VAL_NAME+"_1"));
+ assertNull(vars.get(VAL_NAME+"_2"));
+
+ // Try to get data from subresult
+ result.sampleStart(); // Needed for addSubResult()
+ result.sampleEnd();
+ SampleResult subResult = new SampleResult();
+ subResult.sampleStart();
+ subResult.setResponseData(result.getResponseData());
+ subResult.sampleEnd();
+ result.addSubResult(subResult);
+
+
+ // Get data from both
+ extractor.setScopeAll();
+ extractor.process();
+ assertEquals("zero", vars.get(VAL_NAME));
+ assertEquals("2", vars.get(VAL_NAME_NR));
+ assertEquals("zero", vars.get(VAL_NAME+"_1"));
+ assertEquals("zero", vars.get(VAL_NAME+"_2"));
+ assertNull(vars.get(VAL_NAME+"_3"));
+
+ // get data from child
+ extractor.setScopeChildren();
+ extractor.process();
+ assertEquals("zero", vars.get(VAL_NAME));
+ assertEquals("1", vars.get(VAL_NAME_NR));
+ assertEquals("zero", vars.get(VAL_NAME+"_1"));
+ assertNull(vars.get(VAL_NAME+"_2"));
+
+ }
+
public void testInvalidXpath() throws Exception {
extractor.setXPathQuery("<");
extractor.process();
Modified: jakarta/jmeter/trunk/xdocs/changes.xml
URL:
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/xdocs/changes.xml?rev=905149&r1=905148&r2=905149&view=diff
==============================================================================
--- jakarta/jmeter/trunk/xdocs/changes.xml (original)
+++ jakarta/jmeter/trunk/xdocs/changes.xml Mon Feb 1 00:17:15 2010
@@ -178,7 +178,8 @@
<li>Added JSR223 Assertion</li>
<li>Added BSF Timer and JSR223 Timer</li>
<li>Bug 48331 - XpathExtractor does not return XML string representations for
a Nodeset</li>
-<li>Bug 48511 - add parent,child,all selection to regex extractor panel</li>
+<li>Bug 48511 - add parent,child,all selection to regex extractor</li>
+<li>Add Sampler scope selection to XPathExtractor</li>
</ul>
<h3>Functions</h3>
Modified: jakarta/jmeter/trunk/xdocs/images/screenshots/xpath_extractor.png
URL:
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/xdocs/images/screenshots/xpath_extractor.png?rev=905149&r1=905148&r2=905149&view=diff
==============================================================================
Binary files - no diff available.
Modified: jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml
URL:
http://svn.apache.org/viewvc/jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml?rev=905149&r1=905148&r2=905149&view=diff
==============================================================================
--- jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml (original)
+++ jakarta/jmeter/trunk/xdocs/usermanual/component_reference.xml Mon Feb 1
00:17:15 2010
@@ -4108,13 +4108,23 @@
</p>
</component>
-<component name="XPath Extractor" index="§-num;.8.2" width="613"
height="269" screenshot="xpath_extractor.png">
- <description>This test element allows the user to extract value from
+<component name="XPath Extractor" index="§-num;.8.2" width="612"
height="318" screenshot="xpath_extractor.png">
+ <description>This test element allows the user to extract value(s) from
structured response - XML or (X)HTML - using XPath
query language.
</description>
<properties>
- <property name="Name" required="No">Descriptive name for this element
that is shown in the tree.</property>
+ <property name="Name" required="No">Descriptive name for this element
that is shown in the tree.</property>
+ <property name="Which samples to process" required="Yes">
+ This is for use with samplers that can generate sub-samples,
+ e.g. HTTP Sampler with embedded resources, Mail Reader or samples
generated by the Transaction Controller.
+ <ul>
+ <li>Main sample only - only applies to the main sample</li>
+ <li>Sub-samples only - only applies to the sub-samples</li>
+ <li>Main sample and sub-samples - applies to both.</li>
+ </ul>
+ XPath matching is applied to all qualifying samples in turn, and all
the matching results will be returned.
+ </property>
<property name="Use Tidy (tolerant parser)" required="Yes">If
checked use Tidy to parse HTML response into XHTML.
<ul>
<li>"Use Tidy" should be checked on for HTML response. Such
response is converted to valid XHTML (XML compatible HTML) using Tidy</li>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]