You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jmeter-dev@jakarta.apache.org by se...@apache.org on 2004/09/25 22:59:50 UTC
cvs commit: jakarta-jmeter/xdocs/usermanual functions.xml component_reference.xml
sebb 2004/09/25 13:59:50
Modified: bin Tag: rel-2_0 jmeter.properties
src/functions/org/apache/jmeter/functions Tag: rel-2_0
PackageTest.java BeanShell.java
src/protocol/java/org/apache/jmeter/protocol/java/sampler
Tag: rel-2_0 BeanShellSampler.java
xdocs/usermanual Tag: rel-2_0 functions.xml
component_reference.xml
Added: bin Tag: rel-2_0 BeanShellSampler.bshrc
BeanShellFunction.bshrc
bin/testfiles Tag: rel-2_0 BeanShellTest.bsh
Log:
Update BeanShell sampler and Function to add initialisation file;
update documentation on Bsh variables; add new unit tests and files
Revision Changes Path
No revision
No revision
1.100.2.7 +5 -1 jakarta-jmeter/bin/jmeter.properties
Index: jmeter.properties
===================================================================
RCS file: /home/cvs/jakarta-jmeter/bin/jmeter.properties,v
retrieving revision 1.100.2.6
retrieving revision 1.100.2.7
diff -u -r1.100.2.6 -r1.100.2.7
--- jmeter.properties 21 Sep 2004 00:41:14 -0000 1.100.2.6
+++ jmeter.properties 25 Sep 2004 20:59:50 -0000 1.100.2.7
@@ -283,6 +283,10 @@
#
# Define the server initialisation file
#beanshell.server.file=initial.bsh
+#
+# Define the intialisation files for BeanShell Sampler and Function elements
+#beanshell.sampler.init=BeanShellSampler.bshrc
+#beanshell.function.init=BeanShellFunction.bshrc
#TestBeanGui
#
No revision
Index: jmeter.properties
===================================================================
RCS file: /home/cvs/jakarta-jmeter/bin/jmeter.properties,v
retrieving revision 1.100.2.6
retrieving revision 1.100.2.7
diff -u -r1.100.2.6 -r1.100.2.7
--- jmeter.properties 21 Sep 2004 00:41:14 -0000 1.100.2.6
+++ jmeter.properties 25 Sep 2004 20:59:50 -0000 1.100.2.7
@@ -283,6 +283,10 @@
#
# Define the server initialisation file
#beanshell.server.file=initial.bsh
+#
+# Define the intialisation files for BeanShell Sampler and Function elements
+#beanshell.sampler.init=BeanShellSampler.bshrc
+#beanshell.function.init=BeanShellFunction.bshrc
#TestBeanGui
#
No revision
Index: jmeter.properties
===================================================================
RCS file: /home/cvs/jakarta-jmeter/bin/jmeter.properties,v
retrieving revision 1.100.2.6
retrieving revision 1.100.2.7
diff -u -r1.100.2.6 -r1.100.2.7
--- jmeter.properties 21 Sep 2004 00:41:14 -0000 1.100.2.6
+++ jmeter.properties 25 Sep 2004 20:59:50 -0000 1.100.2.7
@@ -283,6 +283,10 @@
#
# Define the server initialisation file
#beanshell.server.file=initial.bsh
+#
+# Define the intialisation files for BeanShell Sampler and Function elements
+#beanshell.sampler.init=BeanShellSampler.bshrc
+#beanshell.function.init=BeanShellFunction.bshrc
#TestBeanGui
#
1.1.2.1 +30 -0 jakarta-jmeter/bin/Attic/BeanShellSampler.bshrc
1.1.2.1 +30 -0 jakarta-jmeter/bin/Attic/BeanShellFunction.bshrc
No revision
No revision
1.10.2.6 +35 -4 jakarta-jmeter/src/functions/org/apache/jmeter/functions/PackageTest.java
Index: PackageTest.java
===================================================================
RCS file: /home/cvs/jakarta-jmeter/src/functions/org/apache/jmeter/functions/PackageTest.java,v
retrieving revision 1.10.2.5
retrieving revision 1.10.2.6
diff -u -r1.10.2.5 -r1.10.2.6
--- PackageTest.java 23 Sep 2004 23:12:50 -0000 1.10.2.5
+++ PackageTest.java 25 Sep 2004 20:59:50 -0000 1.10.2.6
@@ -38,6 +38,7 @@
import org.apache.jmeter.threads.JMeterContext;
import org.apache.jmeter.threads.JMeterContextService;
import org.apache.jmeter.threads.JMeterVariables;
+import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.jorphan.util.JMeterStopThreadException;
import org.apache.log.Logger;
@@ -167,6 +168,7 @@
public void BSH1() throws Exception
{
+ String fn = "testfiles/BeanShellTest.bsh";
BeanShell bsh;
try
{
@@ -190,6 +192,16 @@
assertEquals("2",bsh.execute());
assertEquals("2",vars.get("VAR"));
+ // Check some initial variables
+ bsh = BSHFParams("return threadName",null,null);
+ assertEquals(Thread.currentThread().getName(),bsh.execute());
+ bsh = BSHFParams("return log.getClass().getName()",null,null);
+ assertEquals(log.getClass().getName(),bsh.execute());
+
+ // Check source works
+ bsh = BSHFParams("source (\"testfiles/BeanShellTest.bsh\")",null,null);
+ assertEquals("9876",bsh.execute());
+
// Check persistence
bsh = BSHFParams("${SCR1}",null,null);
@@ -202,10 +214,29 @@
vars.put("SCR1","x=var1");
assertEquals("11",bsh.execute());
- vars.put("SCR1","x");
- assertEquals("11",bsh.execute());
+ vars.put("SCR1","++x");
+ assertEquals("12",bsh.execute());
+ vars.put("VAR1","test");
+ vars.put("SCR1","vars.get(\"VAR1\")");
+ assertEquals("test",bsh.execute());
+
+
+ // Check init file functioning
+ JMeterUtils.getJMeterProperties()
+ .setProperty(BeanShell.INIT_FILE,fn);
+ bsh = BSHFParams("${SCR2}",null,null);
+ vars.put("SCR2","getprop(\""+BeanShell.INIT_FILE+"\")");
+ assertEquals(fn,bsh.execute());// Check that bsh has read the file
+ vars.put("SCR2","getprop(\"avavaav\",\"default\")");
+ assertEquals("default",bsh.execute());
+ vars.put("SCR2","++i");
+ assertEquals("1",bsh.execute());
+ vars.put("SCR2","++i");
+ assertEquals("2",bsh.execute());
+
}
+
public void SplitTest1() throws Exception
{
SplitFunction split=null;
1.3.2.2 +62 -20 jakarta-jmeter/src/functions/org/apache/jmeter/functions/BeanShell.java
Index: BeanShell.java
===================================================================
RCS file: /home/cvs/jakarta-jmeter/src/functions/org/apache/jmeter/functions/BeanShell.java,v
retrieving revision 1.3.2.1
retrieving revision 1.3.2.2
diff -u -r1.3.2.1 -r1.3.2.2
--- BeanShell.java 23 Sep 2004 23:07:37 -0000 1.3.2.1
+++ BeanShell.java 25 Sep 2004 20:59:50 -0000 1.3.2.2
@@ -19,6 +19,7 @@
package org.apache.jmeter.functions;
import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.LinkedList;
@@ -27,6 +28,8 @@
import org.apache.jmeter.engine.util.CompoundVariable;
import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.samplers.Sampler;
+import org.apache.jmeter.threads.JMeterContext;
+import org.apache.jmeter.threads.JMeterContextService;
import org.apache.jmeter.threads.JMeterVariables;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.logging.LoggingManager;
@@ -47,7 +50,8 @@
protected static Logger log = LoggingManager.getLoggerForClass();
private static final List desc = new LinkedList();
- private static final String KEY = "__BeanShell";
+ private static final String KEY = "__BeanShell"; //$NON-NLS-1$
+ public static final String INIT_FILE = "beanshell.function.init"; //$NON-NLS-1$
static {
@@ -75,12 +79,13 @@
throws InvalidVariableException
{
- if (setObj == null) // did we find BeanShell?
+ if (bshSet == null) // did we find BeanShell?
{
throw new InvalidVariableException("BeanShell not found");
}
- JMeterVariables vars = getVariables();
+ JMeterContext jmctx = JMeterContextService.getContext();
+ JMeterVariables vars = jmctx.getVariables();
String script = ((CompoundVariable) values[0]).execute();
String varName = "";
@@ -96,20 +101,23 @@
{
// Pass in some variables
- if (currentSampler != null) {
- setObj.invoke(instance, new Object[] {"Sampler",currentSampler});
+ if (currentSampler != null)
+ {
+ bshInvoke(bshSet,"Sampler",currentSampler); //$NON-NLS-1$
}
if (previousResult != null)
{
- setObj.invoke(instance, new Object[] {"SampleResult",previousResult});
+ bshInvoke(bshSet,"SampleResult",previousResult); //$NON-NLS-1$
}
-
- setObj.invoke(instance, new Object[] {"log",log});
- setObj.invoke(instance, new Object[] {"t",this});
+
+ // Allow access to context and variables directly
+ bshInvoke(bshSet,"ctx",jmctx); //$NON-NLS-1$
+ bshInvoke(bshSet,"vars",vars); //$NON-NLS-1$
+ bshInvoke(bshSet,"threadName",Thread.currentThread().getName()); //$NON-NLS-1$
// Execute the script
- Object bshOut = eval.invoke(instance, new Object[]{script});
+ Object bshOut = bshInvoke(bshEval,script,null);
if (bshOut != null) {
resultStr = bshOut.toString();
}
@@ -120,7 +128,7 @@
}
catch (Exception ex) // Mainly for bsh.EvalError
{
- log.warn("",ex);
+ log.warn("Error running BSH script",ex);
}
log.debug("Output="+resultStr);
@@ -137,12 +145,37 @@
}
transient private Object instance;
- transient private Method setObj;
- transient private Method eval;
+ transient private Method bshSet;
+ transient private Method bshEval;
+ transient private Method bshSource;
//TODO move to common class (in jorphan?) so can be shared with other BSH modules
- private void setupBeanShell()
+
+ // Helper method for invoking bsh methods
+ private Object bshInvoke(Method m, String s, Object o)
+ {
+ Object r=null;
+ try {
+ if (o == null)
+ {
+ r = m.invoke(instance, new Object[] {s});
+ }
+ else
+ {
+ r = m.invoke(instance, new Object[] {s, o});
+ }
+ } catch (IllegalArgumentException e) {
+ log.error("Error invoking bsh method "+m.getName()+"\n",e);
+ } catch (IllegalAccessException e) {
+ log.error("Error invoking bsh method "+m.getName()+"\n",e);
+ } catch (InvocationTargetException e) {
+ log.error("Error invoking bsh method "+m.getName()+"\n",e);
+ }
+ return r;
+ }
+
+ private void setupBeanShell()
{
ClassLoader loader = Thread.currentThread().getContextClassLoader();
@@ -153,12 +186,17 @@
Class string = String.class;
Class object = Object.class;
- eval = Interpreter.getMethod(
- "eval",
+ bshEval = Interpreter.getMethod(
+ "eval", //$NON-NLS-1$
new Class[] {string});
- setObj = Interpreter.getMethod(
- "set",
+ bshSet = Interpreter.getMethod(
+ "set", //$NON-NLS-1$
new Class[] {string,object});
+
+ bshSource = Interpreter.getMethod(
+ "source", //$NON-NLS-1$
+ new Class[] {string});
+
}
catch(ClassNotFoundException e ){
log.error("Beanshell Interpreter not found");
@@ -168,6 +206,10 @@
log.error("Problem starting BeanShell server ",e);
}
+ // These don't vary between executes, so can be done once
+ bshInvoke(bshSet,"log",log); //$NON-NLS-1$
+ String initFile = JMeterUtils.getPropDefault(INIT_FILE,null);
+ if (initFile!=null) bshInvoke(bshSource,initFile,null);
}
/* (non-Javadoc)
No revision
No revision
1.1.2.1 +20 -0 jakarta-jmeter/bin/testfiles/Attic/BeanShellTest.bsh
No revision
No revision
1.6.2.1 +22 -5 jakarta-jmeter/src/protocol/java/org/apache/jmeter/protocol/java/sampler/BeanShellSampler.java
Index: BeanShellSampler.java
===================================================================
RCS file: /home/cvs/jakarta-jmeter/src/protocol/java/org/apache/jmeter/protocol/java/sampler/BeanShellSampler.java,v
retrieving revision 1.6
retrieving revision 1.6.2.1
diff -u -r1.6 -r1.6.2.1
--- BeanShellSampler.java 11 Mar 2004 01:20:18 -0000 1.6
+++ BeanShellSampler.java 25 Sep 2004 20:59:50 -0000 1.6.2.1
@@ -18,6 +18,7 @@
package org.apache.jmeter.protocol.java.sampler;
+import java.io.FileNotFoundException;
import java.io.IOException;
//import bsh.EvalError;
@@ -26,6 +27,7 @@
import org.apache.jmeter.samplers.AbstractSampler;
import org.apache.jmeter.samplers.Entry;
import org.apache.jmeter.samplers.SampleResult;
+import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.jorphan.util.JOrphanUtils;
import org.apache.log.Logger;
@@ -42,13 +44,28 @@
public static final String FILENAME = "BeanShellSampler.filename"; //$NON-NLS-1$
public static final String SCRIPT = "BeanShellSampler.query"; //$NON-NLS-1$
public static final String PARAMETERS = "BeanShellSampler.parameters"; //$NON-NLS-1$
+ public static final String INIT_FILE = "beanshell.sampler.init"; //$NON-NLS-1$
private Interpreter bshInterpreter;
public BeanShellSampler()
{
+ String init="";
try{
bshInterpreter = new Interpreter();
+ init = JMeterUtils.getPropDefault(INIT_FILE,null);
+ if (init != null)
+ {
+ try
+ {
+ bshInterpreter.source(null);
+ bshInterpreter.set("log",log); //$NON-NLS-1$
+ } catch (IOException e){
+ log.warn("Error processing init file "+init+" "+e);
+ } catch (Exception e){
+ log.warn("Error processing init file "+init+" "+e);
+ }
+ }
} catch (NoClassDefFoundError e){
bshInterpreter=null;
}
@@ -98,9 +115,9 @@
}
//TODO - set some more variables?
- bshInterpreter.set("Label",getLabel());
- bshInterpreter.set("FileName",getFilename());
- bshInterpreter.set("SampleResult",res);
+ bshInterpreter.set("Label",getLabel()); //$NON-NLS-1$
+ bshInterpreter.set("FileName",getFilename()); //$NON-NLS-1$
+ bshInterpreter.set("SampleResult",res); //$NON-NLS-1$
bshInterpreter.set("Parameters",getParameters());// as a single line
bshInterpreter.set("bsh.args",JOrphanUtils.split(getParameters()," "));
No revision
No revision
1.14.2.9 +58 -4 jakarta-jmeter/xdocs/usermanual/functions.xml
Index: functions.xml
===================================================================
RCS file: /home/cvs/jakarta-jmeter/xdocs/usermanual/functions.xml,v
retrieving revision 1.14.2.8
retrieving revision 1.14.2.9
diff -u -r1.14.2.8 -r1.14.2.9
--- functions.xml 23 Sep 2004 11:44:31 -0000 1.14.2.8
+++ functions.xml 25 Sep 2004 20:59:50 -0000 1.14.2.9
@@ -34,7 +34,24 @@
Parentheses surround the parameters sent to the function. The actual parameters vary from function
to function. Functions that require no parameters can leave off the parentheses. The function itself
is wrapped in ${}.</p>
-
+<p>List of functions:</p>
+<ul>
+ <li><a href="#__regexFunction">regexFunction - regular expression evaluator</a></li>
+ <li><a href="#__counter">counter</a></li>
+ <li><a href="#__threadNum">threadNum - get thread number</a></li>
+ <li><a href="#__intSum">intSum - add variables</a></li>
+ <li><a href="#__StringFromFile">StringFromFile - read a line from a file</a></li>
+ <li><a href="#__machineName">machineName - get the local machine name</a></li>
+ <li><a href="#__javaScript">JavaScript (Apache Rhino)</a></li>
+ <li><a href="#__Random">random number</a></li>
+ <li><a href="#__CSVRead">CSVRead -read from CSV delimited file</a></li>
+ <li><a href="#__property">read a property</a></li>
+ <li><a href="#__P">P -read a property</a></li>
+ <li><a href="#__log">log - log a message</a></li>
+ <li><a href="#__logn">log - log a message</a></li>
+ <li><a href="#__BeanShell">BeanShell - run BeanShell</a></li>
+ <li><a href="#__split">split - Split a string into variables</a></li>
+</ul>
<subsection name="16.1 What can functions do" anchor="what_can_do">
<p>There are two kinds of functions: user-defined static values, and built-in functions.<br/>
@@ -175,7 +192,10 @@
</properties>
</component>
+<!-- Alternate spelling -->
+<a name="__StringFromFile"/>
<component index="16.5.5" name="_StringFromFile">
+
<description>
<p>
The StringFromFile function can be used to read strings from a text file.
@@ -418,7 +438,34 @@
<description>
<p>
The BeanShell function evaluates the script passed to it, and returns the result.
- </p>
+</p>
+<p>
+Note that a different Interpreter is used for each independent occurence of the function
+in a test script, but the same Interpreter is used for subsequent invocations.
+This means that variables persist across calls to the function.
+</p>
+<p>
+A single instance of a function may be called from multiple threads.
+However the function execute() method is synchronised.
+</p>
+<p>
+If the property "beanshell.function.init" is defined, it is passed to the Interpreter
+as the name of a sourced file. This can be used to define common methods and variables. There is a
+sample init file in the bin directory: BeanShellFunction.bshrc.
+</p>
+<p>
+The following variables are set before the script is executed:
+<ul>
+<li>log - the logger for the BeanShell function (*)</li>
+<li>ctx - the current JMeter context variable</li>
+<li>vars - the current JMeter variables</li>
+<li>threadName - the threadName</li>
+<li>Sampler the current Sampler, if any</li>
+<li>SampleResult - the current SampleResult, if any</li>
+</ul>
+(*) means that this is set before the init file, if any, is processed.
+Other variables vary from invocation to invocation.
+</p>
</description>
<properties>
@@ -427,6 +474,13 @@
computed by this function.</property>
</properties>
+<p>
+Example:
+<pre>
+${__BeanShell(123*456)} - returns 56088
+${__BeanShell(source("function.bsh"))} - processes the script in function.bsh
+</pre>
+</p>
</component>
<component index="16.5.14" name="__split">
1.87.2.7 +29 -18 jakarta-jmeter/xdocs/usermanual/component_reference.xml
Index: component_reference.xml
===================================================================
RCS file: /home/cvs/jakarta-jmeter/xdocs/usermanual/component_reference.xml,v
retrieving revision 1.87.2.6
retrieving revision 1.87.2.7
diff -u -r1.87.2.6 -r1.87.2.7
--- component_reference.xml 5 Jun 2004 14:44:28 -0000 1.87.2.6
+++ component_reference.xml 25 Sep 2004 20:59:50 -0000 1.87.2.7
@@ -403,28 +403,37 @@
<component name="BeanShell Sampler" index="15.1.9" screenshot="">
<center><h2>(Beta Code)</h2></center>
- <description><p>This sampler allows you to write a sampler using the BeanShell scripting language.<br></br>
-
- <br></br>
- Please note that the BeanShell jar file is not included with JMeter; it needs to be separately downloaded.
- For full details on using BeanShell, please see the BeanShell web-site at http://www.beanshell.org/.
-
- </p>
+ <description><p>This sampler allows you to write a sampler using the BeanShell scripting language.
+</p><p>
+ <b>Please note that the BeanShell jar file is not included with JMeter; it needs to be separately downloaded.
+ <br/>
+ For full details on using BeanShell, please see the BeanShell web-site at http://www.beanshell.org/.</b>
+</p>
</description>
<properties>
<property name="Name" required="no">Descriptive name for this controller that is shown in the tree.</property>
<property name="Parameters" required="no">List of parameters to be passed to the script file or the script.</property>
- <property name="Script File" required="no">Name of a file to be used as a BeanShell script</property>
- <property name="Script" required="no">Script to be passed to BeanShell</property>
+ <property name="Script File" required="(yes)">Name of a file to be used as a BeanShell script</property>
+ <property name="Script" required="(yes)">Script to be passed to BeanShell</property>
</properties>
-<p>If a script file is supplied, that will be used, otherwise the script will be used.</p>
- <p>Before invoking the script, some variable are set up in the BeanShell interpreter:
+<p>
+N.B. Each Sampler instance has its own BeanShell interpeter,
+and Samplers are only called from a single thread
+</p><p>
+If the property "beanshell.sampler.init" is defined, it is passed to the Interpreter
+as the name of a sourced file.
+This can be used to define common methods and variables.
+There is a sample init file in the bin directory: BeanShellFunction.bshrc.
+</p><p>
+If a script file is supplied, that will be used, otherwise the script will be used.</p>
+ <p>Before invoking the script, some variables are set up in the BeanShell interpreter:
</p>
<p>The contents of the Parameters field is put into the variable "Parameters".
The string is also split into separate tokens using a single space as the separator, and the resulting list
is stored in the String array bsh.args.</p>
<p>The full list of variables that is set up is as follows:</p>
<ul>
+ <li>log - the Logger</li>
<li>Label - the Sampler label</li>
<li>FileName - the file name, if any</li>
<li>Parameters - text from the Parameters field</li>
@@ -446,12 +455,14 @@
methods in the SampleResult. For example, the script has access to the methods
setStopThread(boolean) and setStopTest(boolean).
- Here is a simple example script:</p>
+ Here is a simple (not very useful!) example script:</p>
<pre>
- if (bsh.args[0].equalsIgnoreCase("StopThread")) {
- SampleResult.StopThread(bsh.args[1]);
- }
+if (bsh.args[0].equalsIgnoreCase("StopThread")) {
+ log.info("Stop Thread detected!");
+ SampleResult.StopThread(bsh.args[1]);
+}
+return "Data from sample with Label "+Label;
</pre>
</component>
---------------------------------------------------------------------
To unsubscribe, e-mail: jmeter-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: jmeter-dev-help@jakarta.apache.org