Author: fschumacher
Date: Tue Oct  7 16:54:46 2014
New Revision: 1629926

URL: http://svn.apache.org/r1629926
Log:
Bug 57032 - Make regexes in HTTP Script Recorder more useful.

When a regex starts and ends with a paren, it will not be surrounded
by boundary matchers anymore. That way boundary characters can be
included in the match.

Bugzilla Id: 57032

Modified:
    
jmeter/trunk/src/core/org/apache/jmeter/engine/util/ReplaceFunctionsWithStrings.java
    jmeter/trunk/test/src/org/apache/jmeter/engine/util/TestValueReplacer.java
    jmeter/trunk/xdocs/changes.xml
    jmeter/trunk/xdocs/usermanual/component_reference.xml

Modified: 
jmeter/trunk/src/core/org/apache/jmeter/engine/util/ReplaceFunctionsWithStrings.java
URL: 
http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/engine/util/ReplaceFunctionsWithStrings.java?rev=1629926&r1=1629925&r2=1629926&view=diff
==============================================================================
--- 
jmeter/trunk/src/core/org/apache/jmeter/engine/util/ReplaceFunctionsWithStrings.java
 (original)
+++ 
jmeter/trunk/src/core/org/apache/jmeter/engine/util/ReplaceFunctionsWithStrings.java
 Tue Oct  7 16:54:46 2014
@@ -79,7 +79,7 @@ public class ReplaceFunctionsWithStrings
             String value = entry.getValue();
             if (regexMatch) {
                 try {
-                    pattern = compiler.compile("\\b("+value+")\\b");
+                    pattern = compiler.compile(constructPattern(value));
                     input = Util.substitute(pm, pattern,
                             new StringSubstitution(FUNCTION_REF_PREFIX + key + 
FUNCTION_REF_SUFFIX),
                             input, Util.SUBSTITUTE_ALL);
@@ -92,4 +92,12 @@ public class ReplaceFunctionsWithStrings
         }
         return new StringProperty(prop.getName(), input);
     }
+
+    private String constructPattern(String value) {
+        if (value.startsWith("(") && value.endsWith(")")) {
+            return value;
+        }
+       return "\\b(" + value + ")\\b";
+    }
+
 }

Modified: 
jmeter/trunk/test/src/org/apache/jmeter/engine/util/TestValueReplacer.java
URL: 
http://svn.apache.org/viewvc/jmeter/trunk/test/src/org/apache/jmeter/engine/util/TestValueReplacer.java?rev=1629926&r1=1629925&r2=1629926&view=diff
==============================================================================
--- jmeter/trunk/test/src/org/apache/jmeter/engine/util/TestValueReplacer.java 
(original)
+++ jmeter/trunk/test/src/org/apache/jmeter/engine/util/TestValueReplacer.java 
Tue Oct  7 16:54:46 2014
@@ -47,7 +47,8 @@ public class TestValueReplacer extends J
             // The following used to be jacks_password, but the Arguments 
class uses
             // HashMap for which the order is not defined.
             variables.addParameter("password", "his_password");
-            variables.addParameter("regex", ".*");
+            variables.addParameter("normal_regex", "Hello .*");
+            variables.addParameter("bounded_regex", "(<.*>)");
             JMeterVariables vars = new JMeterVariables();
             vars.put("server", "jakarta.apache.org");
             JMeterContextService.getContext().setVariables(vars);
@@ -72,6 +73,25 @@ public class TestValueReplacer extends J
             assertEquals("${password}", args.get(1).getStringValue());
         }
 
+        public void testReverseReplacementXml() throws Exception {
+            ValueReplacer replacer = new ValueReplacer(variables);
+            
assertTrue(variables.getUserDefinedVariables().containsKey("bounded_regex"));
+            
assertTrue(variables.getUserDefinedVariables().containsKey("normal_regex"));
+            assertTrue(replacer.containsKey("bounded_regex"));
+            assertTrue(replacer.containsKey("normal_regex"));
+            TestElement element = new TestPlan();
+            element.setProperty(new StringProperty("domain", 
"<this><is>xml</this></is>"));
+            List<Object> argsin = new ArrayList<Object>();
+            argsin.add("<this><is>xml</this></is>");
+            argsin.add("And I say: Hello World.");
+            element.setProperty(new CollectionProperty("args", argsin));
+            replacer.reverseReplace(element, true);
+            @SuppressWarnings("unchecked")
+            List<JMeterProperty> args = (List<JMeterProperty>) 
element.getProperty("args").getObjectValue();
+            assertEquals("${bounded_regex}", 
element.getPropertyAsString("domain"));
+            assertEquals("${bounded_regex}", args.get(0).getStringValue());
+        }
+
         public void testReplace() throws Exception {
             ValueReplacer replacer = new ValueReplacer();
             
replacer.setUserDefinedVariables(variables.getUserDefinedVariables());

Modified: jmeter/trunk/xdocs/changes.xml
URL: 
http://svn.apache.org/viewvc/jmeter/trunk/xdocs/changes.xml?rev=1629926&r1=1629925&r2=1629926&view=diff
==============================================================================
--- jmeter/trunk/xdocs/changes.xml (original)
+++ jmeter/trunk/xdocs/changes.xml Tue Oct  7 16:54:46 2014
@@ -85,7 +85,7 @@ and/or DNS load balancing.</p>
 <ch_title>Smarter Recording of Http Test Plans</ch_title>
 <p>Test Script Recorder has been improved in many ways</p>
 <ul>
-    <li>Better matching of Variables in Requests, making Test Script Recorder 
variabilize your sampler during recording much intelligently (@Felix remove 
this when you commit your patch)</li>
+    <li>Better matching of Variables in Requests, making Test Script Recorder 
variabilize your sampler during recording more versatile</li>
     <li>Ability to filter from View Results Tree the Samples that are excluded 
from recording, this lets you concentrate on recorded Samplers analysis and not 
bother with useless Sample Results</li>
     <li>Better defaults for recording, since this version Recorder will number 
created Samplers letting you find them much easily in View Results Tree. 
Grouping of Samplers under Transaction Controller will
     will be smarter making all requests emitted by a web page be children as 
new Transaction Controller</li>

Modified: jmeter/trunk/xdocs/usermanual/component_reference.xml
URL: 
http://svn.apache.org/viewvc/jmeter/trunk/xdocs/usermanual/component_reference.xml?rev=1629926&r1=1629925&r2=1629926&view=diff
==============================================================================
--- jmeter/trunk/xdocs/usermanual/component_reference.xml (original)
+++ jmeter/trunk/xdocs/usermanual/component_reference.xml Tue Oct  7 16:54:46 
2014
@@ -6025,7 +6025,7 @@ Both Chrome and Internet Explorer use th
         as a comma-separated list of headers.
         </property>
         <property name="Add Assertions" required="Yes">Add a blank assertion 
to each sampler?</property>
-        <property name="Regex Matching" required="Yes">Use Regex Matching when 
replacing variables? If checked replacement will use word boundaries, ie it 
will only replace word matching values of variable, not part of a word. A word 
boundary follows Perl5 definition and is equivalent to \b.</property>
+        <property name="Regex Matching" required="Yes">Use Regex Matching when 
replacing variables? If checked replacement will use word boundaries, ie it 
will only replace word matching values of variable, not part of a word. A word 
boundary follows Perl5 definition and is equivalent to \b. More information 
below in the paragraph about "User Defined Variable replacement".</property>
         <property name="Type" required="Yes">Which type of sampler to generate 
(the Java default or HTTPClient)</property>
         <property name="Redirect Automatically" required="Yes">Set Redirect 
Automatically in the generated samplers?</property>
         <property name="Follow Redirects" required="Yes">Set Follow Redirects 
in the generated samplers?<br/>
@@ -6163,21 +6163,42 @@ place User Defined Variables directly wi
 <note>Please note that matching is case-sensitive.</note>
 
 <p>Replacement by Variables: by default, the Proxy server looks for all 
occurences of UDV values. 
-If you define the variable "WEB" with the value "www", for example, 
-the string "www" will be replaced by ${WEB} wherever it is found.
+If you define the variable <code>WEB</code> with the value <code>www</code>, 
for example,
+the string <code>www</code> will be replaced by <code>${WEB}</code> wherever 
it is found.
 To avoid this happening everywhere, set the "Regex Matching" check-box.
-This tells the proxy server to treat values as Regexes (using ORO).
-<br></br>
-If you want to match a whole string only, enclose it in ^$, e.g. "^thus$".
-<br></br>
-If you want to match /images at the start of a string only, use the value 
"^/images".
-Jakarta ORO also supports zero-width look-ahead, so one can match /images/... 
-but retain the trailing / in the output by using "^/images(?=/)".
-Note that the current version of Jakara ORO does not support look-behind - 
i.e. "(?&amp;lt;=...) or (?&amp;lt;!...)".
-<br></br>
-If there are any problems interpreting any variables as patterns, these are 
reported in jmeter.log,
-so be sure to check this if UDVs are not working as expected.
-</p>
+This tells the proxy server to treat values as Regexes (using the perl5 
compatible regex matchers provided by ORO).</p>
+
+<p>If "Regex Matching" is selected every variable will be compiled into a perl 
compatible regex enclosed in
+<code>\b(</code> and <code>)\b</code>. That way each match will start and end 
at a word boundary.</p>
+
+<note>Note that the boundary characters are not part of the matching group, 
e.g. <code>n.*</code> to match <code>name</code> out
+of <code>You can call me 'name'</code>.</note>
+
+<p>If you don't want your regex to be enclosed with those boundary matchers, 
you have to enclose your
+regex within parens, e.g <code>('.*?')</code> to match <code>'name'</code> out 
of <code>You can call me 'name'</code>.</p>
+
+<note>
+The variables will be checked in random order. So ensure, that the potential 
matches don't overlap.
+Overlapping matchers would be <code>.*</code> (which matches anything) and 
<code>www</code> (which
+matches <code>www</code> only). Non-overlapping matchers would be 
<code>a+</code> (matches a sequence
+of <cod>a</cod>'s) and <code>b+</code> (matches a sequence of 
<code>b</code>'s).
+</note>
+
+<p>If you want to match a whole string only, enclose it in <code>(^</code> and 
<code>$)</code>, e.g. <code>(^thus$)</code>.
+The parens are neccessary, since the normally added boundary characters will 
prevent <code>^</code> and
+<code>$</code> to match.</p>
+
+<p>If you want to match <code>/images</code> at the start of a string only, 
use the value <code>(^/images)</code>.
+Jakarta ORO also supports zero-width look-ahead, so one can match 
<code>/images/...</code>
+but retain the trailing <code>/</code> in the output by using 
<code>(^/images(?=/))</code>".</p>
+
+<note>
+Note that the current version of Jakara ORO does not support look-behind - 
i.e. <code>(?&amp;lt;=...)</code> or <code>(?&amp;lt;!...)</code>.
+</note>
+
+<p>If there are any problems interpreting any variables as patterns, these are 
reported in jmeter.log,
+so be sure to check this if UDVs are not working as expected.</p>
+
 <p>When you are done recording your test samples, stop the proxy server (hit 
the &quot;stop&quot; button).  Remember to reset
 your browser's proxy settings.  Now, you may want to sort and re-order the 
test script, add timers, listeners, a
 cookie manager, etc.</p>


Reply via email to