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

BSF JavaScript Preprocessor cannot access sampler variable on first interation #2180

Closed
asfimport opened this issue Dec 7, 2008 · 6 comments

Comments

@asfimport
Copy link
Collaborator

Thomas Johnson (Bug 46359):
The BSF JavaScript Preprocessor is unable to access the Sampler variable in the first iteration, citing the following exception:

org.apache.bsf.BSFException: JavaScript Error: Internal Error: org.mozilla.javascript.EcmaError: ReferenceError: "sampler" is not defined.

Steps to Reproduce:
1-Create a Thread Group set to run for two or more iterations
2-Add a Sampler to the Thread Group (tested with an HTTP Sampler)
3-Add a BSF PreProcessor to the Sampler
4-Use javascript as the BSF Language
5-Enter a simple script that references the "sampler" variable. Tested with OUT.println("hello"); OUT.println(sampler);
6-Run

Expected Results:

  • All iterations produce console output "hello\n[sampler information]"

Actual Results:

  • First Iteration, only "hello" is output to console.
  • Log Output: 2008/12/07 12:21:51 WARN - jmeter.modifiers.BSFPreProcessor: Problem in BSF script org.apache.bsf.BSFException: JavaScr
    ipt Error: Internal Error: org.mozilla.javascript.EcmaError: ReferenceError: "sampler" is not defined.
  • Second and further iterations "hello\n[sampler information]"

Affects Versions:

  • Trunk revision 722843
  • Release 2.3.2

Created attachment dynamic-forms.jmx: Test Case illustrating issue

dynamic-forms.jmx
<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="2.1">
  <hashTree>
    <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true">
      <stringProp name="TestPlan.comments"></stringProp>
      <boolProp name="TestPlan.functional_mode">false</boolProp>
      <boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
      <elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
        <collectionProp name="Arguments.arguments"/>
      </elementProp>
      <stringProp name="TestPlan.user_define_classpath"></stringProp>
    </TestPlan>
    <hashTree>
      <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group" enabled="true">
        <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
          <boolProp name="LoopController.continue_forever">false</boolProp>
          <stringProp name="LoopController.loops">2</stringProp>
        </elementProp>
        <stringProp name="ThreadGroup.num_threads">1</stringProp>
        <stringProp name="ThreadGroup.ramp_time">1</stringProp>
        <longProp name="ThreadGroup.start_time">1228306873000</longProp>
        <longProp name="ThreadGroup.end_time">1228306873000</longProp>
        <boolProp name="ThreadGroup.scheduler">false</boolProp>
        <stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
        <stringProp name="ThreadGroup.duration"></stringProp>
        <stringProp name="ThreadGroup.delay"></stringProp>
      </ThreadGroup>
      <hashTree>
        <CookieManager guiclass="CookiePanel" testclass="CookieManager" testname="HTTP Cookie Manager" enabled="true">
          <collectionProp name="CookieManager.cookies">
            <elementProp name="JSESSIONID" elementType="Cookie" testname="JSESSIONID">
              <stringProp name="Cookie.value">DEADBEE</stringProp>
              <stringProp name="Cookie.domain">www.blastradius.com</stringProp>
              <stringProp name="Cookie.path">/</stringProp>
              <boolProp name="Cookie.secure">false</boolProp>
              <longProp name="Cookie.expires">0</longProp>
              <boolProp name="Cookie.path_specified">true</boolProp>
              <boolProp name="Cookie.domain_specified">true</boolProp>
            </elementProp>
          </collectionProp>
          <boolProp name="CookieManager.clearEachIteration">false</boolProp>
          <stringProp name="CookieManager.policy">rfc2109</stringProp>
        </CookieManager>
        <hashTree/>
        <HTTPSampler guiclass="HttpTestSampleGui" testclass="HTTPSampler" testname="HTTP Request" enabled="true">
          <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
            <collectionProp name="Arguments.arguments">
              <elementProp name="foo" elementType="HTTPArgument">
                <boolProp name="HTTPArgument.always_encode">false</boolProp>
                <stringProp name="Argument.value">bar</stringProp>
                <stringProp name="Argument.metadata">=</stringProp>
                <boolProp name="HTTPArgument.use_equals">true</boolProp>
                <stringProp name="Argument.name">foo</stringProp>
              </elementProp>
              <elementProp name="foo1" elementType="HTTPArgument">
                <boolProp name="HTTPArgument.always_encode">false</boolProp>
                <stringProp name="Argument.value">baz</stringProp>
                <stringProp name="Argument.metadata">=</stringProp>
                <boolProp name="HTTPArgument.use_equals">true</boolProp>
                <stringProp name="Argument.name">foo1</stringProp>
              </elementProp>
              <elementProp name="foo2" elementType="HTTPArgument">
                <boolProp name="HTTPArgument.always_encode">false</boolProp>
                <stringProp name="Argument.value">quux</stringProp>
                <stringProp name="Argument.metadata">=</stringProp>
                <boolProp name="HTTPArgument.use_equals">true</boolProp>
                <stringProp name="Argument.name">foo2</stringProp>
              </elementProp>
            </collectionProp>
          </elementProp>
          <stringProp name="HTTPSampler.domain">www.blastradius.com</stringProp>
          <stringProp name="HTTPSampler.port"></stringProp>
          <stringProp name="HTTPSampler.protocol"></stringProp>
          <stringProp name="HTTPSampler.contentEncoding"></stringProp>
          <stringProp name="HTTPSampler.path">/</stringProp>
          <stringProp name="HTTPSampler.method">POST</stringProp>
          <boolProp name="HTTPSampler.follow_redirects">false</boolProp>
          <boolProp name="HTTPSampler.auto_redirects">true</boolProp>
          <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
          <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
          <stringProp name="HTTPSampler.FILE_NAME"></stringProp>
          <stringProp name="HTTPSampler.FILE_FIELD"></stringProp>
          <stringProp name="HTTPSampler.mimetype"></stringProp>
          <boolProp name="HTTPSampler.monitor">false</boolProp>
          <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
        </HTTPSampler>
        <hashTree>
          <BeanShellPreProcessor guiclass="TestBeanGUI" testclass="BeanShellPreProcessor" testname="BeanShell PreProcessor" enabled="true">
            <stringProp name="filename"></stringProp>
            <stringProp name="parameters"></stringProp>
            <boolProp name="resetInterpreter">false</boolProp>
            <stringProp name="script">System.out.println(&quot;---&quot;);
System.out.println(&quot;BeanShell&quot;);
System.out.println(&quot;Context: &quot; + (ctx == null));
System.out.println(&quot;Variables: &quot; + (vars == null));
System.out.println(&quot;Sampler: &quot; + (sampler == null));</stringProp>
          </BeanShellPreProcessor>
          <hashTree/>
          <BSFPreProcessor guiclass="TestBeanGUI" testclass="BSFPreProcessor" testname="BSF PreProcessor" enabled="true">
            <stringProp name="scriptLanguage">jexl</stringProp>
            <stringProp name="parameters"></stringProp>
            <stringProp name="filename"></stringProp>
            <stringProp name="script">OUT.println(&quot;BSF Jexl&quot;);
OUT.println(&quot;Context: &quot; + (ctx == null));
OUT.println(&quot;Variables: &quot; + (vars == null));
OUT.println(&quot;Sampler: &quot; + (sampler == null));</stringProp>
          </BSFPreProcessor>
          <hashTree/>
          <BSFPreProcessor guiclass="TestBeanGUI" testclass="BSFPreProcessor" testname="BSF PreProcessor" enabled="true">
            <stringProp name="filename"></stringProp>
            <stringProp name="parameters"></stringProp>
            <stringProp name="script">OUT.println(&quot;BSF JS&quot;);
OUT.println(&quot;Context: &quot; + (ctx == null));
OUT.println(&quot;Variables: &quot; + (vars == null));
OUT.println(&quot;Sampler: &quot; + (sampler == null));</stringProp>
            <stringProp name="scriptLanguage">javascript</stringProp>
          </BSFPreProcessor>
          <hashTree/>
          <BSFPostProcessor guiclass="TestBeanGUI" testclass="BSFPostProcessor" testname="BSF PostProcessor" enabled="true">
            <stringProp name="filename"></stringProp>
            <stringProp name="parameters"></stringProp>
            <stringProp name="script">OUT.println(&quot;BSF JS (post)&quot;);
OUT.println(&quot;Context: &quot; + (ctx == null));
OUT.println(&quot;Variables: &quot; + (vars == null));
OUT.println(&quot;Sampler: &quot; + (sampler == null));</stringProp>
            <stringProp name="scriptLanguage">javascript</stringProp>
          </BSFPostProcessor>
          <hashTree/>
        </hashTree>
        <ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="View Results Tree" enabled="true">
          <boolProp name="ResultCollector.error_logging">false</boolProp>
          <objProp>
            <name>saveConfig</name>
            <value class="SampleSaveConfiguration">
              <time>true</time>
              <latency>true</latency>
              <timestamp>true</timestamp>
              <success>true</success>
              <label>true</label>
              <code>true</code>
              <message>true</message>
              <threadName>true</threadName>
              <dataType>true</dataType>
              <encoding>false</encoding>
              <assertions>true</assertions>
              <subresults>true</subresults>
              <responseData>false</responseData>
              <samplerData>false</samplerData>
              <xml>true</xml>
              <fieldNames>false</fieldNames>
              <responseHeaders>false</responseHeaders>
              <requestHeaders>false</requestHeaders>
              <responseDataOnError>false</responseDataOnError>
              <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
              <assertionsResultsToSave>0</assertionsResultsToSave>
              <bytes>true</bytes>
            </value>
          </objProp>
          <stringProp name="filename"></stringProp>
        </ResultCollector>
        <hashTree/>
      </hashTree>
    </hashTree>
  </hashTree>
</jmeterTestPlan>

Severity: normal
OS: Mac OS X 10.4

@asfimport
Copy link
Collaborator Author

Thomas Johnson (migrated from Bugzilla):
In version 2.3.2, this issue affects both the Pre and Post Processors. As of the current trunk (722032) this only affects the Pre Processor.

@asfimport
Copy link
Collaborator Author

Sebb (migrated from Bugzilla):
Thanks for the report and test case.

This appears to be due to a bug in either BSF or Rhino, not JMeter.

It does not appear to be possible to define a script variable with a null value to Javascript using BSF. Furthermore, any variables which are defined after the null value will also be inaccessible.

The null variable in this case is "prev", so a work-round is to ensure that there is at least one previous sample result.

The JMeter code can be rearanged to define the "prev" variable last, but obviously that is also only a work-round.

@asfimport
Copy link
Collaborator Author

Thomas Johnson (migrated from Bugzilla):
Some research indicates that BSF used to have an issue with registering (but not declaring) a null bean back in mid-2004 (Ref 1).

From the snippet below, a quick run of the test case shows that BSF Jexl handles the null "prev" object just fine. As BSF Jexl and JS get set up by the same code, it is most likely that the issue lies in or close to Rhino itself.

-- Test Case output --
BSF Jexl
Context: false
Variables: false
Sampler: false
BSF JS
Context: false
Variables: false

-- References --
(1) Commits fixing BSF issue 20355: http://markmail.org/message/ymna5ppb4556og4k

@asfimport
Copy link
Collaborator Author

Sebb (migrated from Bugzilla):
As far as I can tell, the problem is in BSF, in the Javascript engine wrapper.

I raised https://issues.apache.org/jira/browse/BSF-22 for the error.

@asfimport
Copy link
Collaborator Author

Sebb (migrated from Bugzilla):
I've added a temporary work-round in r724446 and r724445.

This is in the current nightlies (from r724447) if you want to try it out.

@asfimport
Copy link
Collaborator Author

Sebb (migrated from Bugzilla):
Please reopen if the fix does not work

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant