You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@jmeter.apache.org by Mark Miller <ma...@gmail.com> on 2009/12/04 07:17:30 UTC

Accessing and asserting remote file system resources using BeanShell

First off, a nod of appreciation to the contributors for this fantastic
tool.

I am using Jmeter to validate the integrity of some complex integrations.
For these tests I use LDAP, HTTP, JDBC, and SOAP samplers extensively. It is
providing great value.

There is one final piece of my vision that I am struggling to achieve: I
want to 'sample' from remotely running BeanShell servers by sending code
that will find, read, and send back the contents of configuration files (for
example) which I can then continue to evaluate in the sampler or with
subsequent assertions. I've proven with basic BeanShell that I can do this
in a crude, raw fashion outside of Jmeter.

I have tried two approaches inside Jmeter:

1) Using a TCPSampler and sending java to the BeanShell telnet port
(port+1).
2) Using a BeanShell sampler and directly invoking the bsh.Remote class.
(see code below)

import bsh.Remote;
i = new Remote();
ResponseMessage = (i.eval("bsh://localhost:9000","print(0);"));

The main crux, it seems, is that the connection returns nothing until the
BeanShell server itself exits. I also tried sending an exit() over to the
server which allows it to send an exit code back - but also terminates the
server process. So that doesn't do the trick. (Nor do I get the String data
I am looking for, just an exit code.)

I'm not quite on the right track with this. But I think the utility of the
idea is so obvious that someone may have crossed this bridge.

Anyone done anything like this and can provide some insights or point me in
the right direction?

I do appreciate your thoughts on this.

-- 
Mark Miller

Re: Accessing and asserting remote file system resources using BeanShell

Posted by sebb <se...@gmail.com>.
On 06/12/2009, Mark Miller <ma...@gmail.com> wrote:
> I was able to craft a simple solution to this using a BeanShell sampler.
>
>  My original problem was not being able to disconnect from the remote
>  BeanShell server and that hung the jmeter test.
>
>  My solution was to implement a custom EOF indicator and a custom remote
>  requester to detect the custom EOF.
>
>  There are three moving parts to this:
>
>  1) It expects that there is a listening BeanShell server on the remote host.
>  I put the bsh-2.0b4.jar on the remote host as well as a simple script to
>  initialize the server:
>
>  $ cat startserver.bsh
>  print("Starting BeanShell server...");
>  server(9000);
>
>  I execute that script:
>
>  java -cp bsh-2.0b4.jar bsh.Interpreter startserver.bsh
>  Starting BeanShell server...
>  Httpd started on port: 9000
>  Sessiond started on port: 9001
>
>  2) Then (back on the local test box) I created a simple script that could
>  read a file and print its contents.
>  # catfile.bsh
>  import java.io.*;
>  File f = new File("/opt/foo/some.xml");
>  FileInputStream fin = new FileInputStream(f);
>  fileContent = new byte[(int)f.length()];
>  fin.read(fileContent);
>  print(new String(fileContent));
>  print("$bsh.break$");
>
>  This is the file that I keep on the test machine. It gets sent to the remote
>  host and evaluated there. Note that it includes the printing of my custom
>  EOF token "$bsh.break$".
>
>  3) Lastly, I created a BeanShell sampler in the test plan that included the
>  following code. This code is just a simplified version of the
>  bsh.Remote.java class. The only enhancement is the addition of an if
>  statement that looks for the EOF token:
>
>  import java.io.BufferedReader;
>  import java.io.FileNotFoundException;
>  import java.io.FileReader;
>  import java.io.IOException;
>  import java.io.InputStream;
>  import java.io.InputStreamReader;
>  import java.io.OutputStream;
>  import java.net.Socket;
>  import java.net.UnknownHostException;
>
>  OutputStream out = null;
>  InputStream in = null;
>  String host = "${host}";
>  String port = "${port}";
>  String returnValue = "-1";
>  String body = null;
>  StringBuffer errorBuffer = new StringBuffer();
>
>  Socket s;
>  try {
>   s = new Socket(host, Integer.parseInt(port) + 1);
>   out = s.getOutputStream();
>   in = s.getInputStream();
>  } catch (UnknownHostException ex) {
>   errorBuffer.append("Not able to access remote BeanShell server.
>  ["+ex.getMessage()+"]");
>  } catch (IOException ex) {
>   errorBuffer.append("Not able to access remote BeanShell server.
>  ["+ex.getMessage()+"]");
>  }
>
>  StringBuffer sb = new StringBuffer();
>  BufferedReader bin;
>  try {
>   bin = new BufferedReader(new FileReader("${script}"));
>   String line;
>   while ((line = bin.readLine()) != null) {
>     sb.append(line).append("\n");
>   }
>   out.write(sb.toString().getBytes());
>   out.flush();
>  } catch (FileNotFoundException ex) {
>   errorBuffer.append("Not able to access local script to send to BeanShell
>  server. ["+ex.getMessage()+"]");
>  } catch (IOException ex) {
>   errorBuffer.append("Not able to access local script to send to BeanShell
>  server. ["+ex.getMessage()+"]");
>  }
>
>  BufferedReader resp = new BufferedReader(new InputStreamReader(in));
>  String respline;
>  StringBuffer bodybuffer = new StringBuffer();
>  try {
>   while ((respline = resp.readLine()) != null) {
>     bodybuffer.append(respline);
>     if (respline.indexOf("$bsh.break$") > -1) {
>       break;
>     }
>   }
>  } catch (IOException ex) {
>   errorBuffer.append("Error receiving response from remote BeanShell server.
>  ["+ex.getMessage()+"]");
>  }
>
>  // clean up the output by removing the bsh artifacts
>  String response = bodybuffer.toString();
>  String startkey = "bsh % bsh % ";
>  String endkey = "bsh % $bsh.break$";
>  int start = response.lastIndexOf(startkey)+startkey.length();
>  int end = response.lastIndexOf(endkey);
>  String trimmedResponse = response.substring(start, end);
>  SampleResult.setResponseData(trimmedResponse);
>
>  ---
>
>  That's it. The test runs and pulls this xml file back as the sampler
>  response. Then I can run xpath extractors or other assertions on the
>  response data.
>
>  This lets me reach out to a cluster of servers and do a rapid check to see
>  that things are configured the way I expect them to be.
>
>  If anyone improves on this or has other suggestions for me I'm keen to hear
>  it.

Firstly, remember that the BeanShell server has no security whatsoever
- anyone who can connect to its port can tell the server to do
anything on its host.

If the hosts are on an internal network then you are probably OK, but
the login that is used to run the server should have minimal
privileges.

A possible improvement: instead of sending the commands directly,
define a method on the server (String parameter = filename), and use
that to return the file. You can do this in the startserver.bsh file;
file.bsh is no longer needed.

You can then send the command to the server from the BSH sampler and
trigger the response. This will allow you to request multiple files.

Similarly for the BSH sampler - define the code as a method in a bsh
init file (or use the File input rather than code in the GUI) and the
sampler code will be much simpler to use.

>  Thanks,
>
>
>  Mark
>

---------------------------------------------------------------------
To unsubscribe, e-mail: jmeter-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: jmeter-user-help@jakarta.apache.org


Re: Accessing and asserting remote file system resources using BeanShell

Posted by Mark Miller <ma...@gmail.com>.
I was able to craft a simple solution to this using a BeanShell sampler.

My original problem was not being able to disconnect from the remote
BeanShell server and that hung the jmeter test.

My solution was to implement a custom EOF indicator and a custom remote
requester to detect the custom EOF.

There are three moving parts to this:

1) It expects that there is a listening BeanShell server on the remote host.
I put the bsh-2.0b4.jar on the remote host as well as a simple script to
initialize the server:

$ cat startserver.bsh
print("Starting BeanShell server...");
server(9000);

I execute that script:

java -cp bsh-2.0b4.jar bsh.Interpreter startserver.bsh
Starting BeanShell server...
Httpd started on port: 9000
Sessiond started on port: 9001

2) Then (back on the local test box) I created a simple script that could
read a file and print its contents.
# catfile.bsh
import java.io.*;
File f = new File("/opt/foo/some.xml");
FileInputStream fin = new FileInputStream(f);
fileContent = new byte[(int)f.length()];
fin.read(fileContent);
print(new String(fileContent));
print("$bsh.break$");

This is the file that I keep on the test machine. It gets sent to the remote
host and evaluated there. Note that it includes the printing of my custom
EOF token "$bsh.break$".

3) Lastly, I created a BeanShell sampler in the test plan that included the
following code. This code is just a simplified version of the
bsh.Remote.java class. The only enhancement is the addition of an if
statement that looks for the EOF token:

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

OutputStream out = null;
InputStream in = null;
String host = "${host}";
String port = "${port}";
String returnValue = "-1";
String body = null;
StringBuffer errorBuffer = new StringBuffer();

Socket s;
try {
  s = new Socket(host, Integer.parseInt(port) + 1);
  out = s.getOutputStream();
  in = s.getInputStream();
} catch (UnknownHostException ex) {
  errorBuffer.append("Not able to access remote BeanShell server.
["+ex.getMessage()+"]");
} catch (IOException ex) {
  errorBuffer.append("Not able to access remote BeanShell server.
["+ex.getMessage()+"]");
}

StringBuffer sb = new StringBuffer();
BufferedReader bin;
try {
  bin = new BufferedReader(new FileReader("${script}"));
  String line;
  while ((line = bin.readLine()) != null) {
    sb.append(line).append("\n");
  }
  out.write(sb.toString().getBytes());
  out.flush();
} catch (FileNotFoundException ex) {
  errorBuffer.append("Not able to access local script to send to BeanShell
server. ["+ex.getMessage()+"]");
} catch (IOException ex) {
  errorBuffer.append("Not able to access local script to send to BeanShell
server. ["+ex.getMessage()+"]");
}

BufferedReader resp = new BufferedReader(new InputStreamReader(in));
String respline;
StringBuffer bodybuffer = new StringBuffer();
try {
  while ((respline = resp.readLine()) != null) {
    bodybuffer.append(respline);
    if (respline.indexOf("$bsh.break$") > -1) {
      break;
    }
  }
} catch (IOException ex) {
  errorBuffer.append("Error receiving response from remote BeanShell server.
["+ex.getMessage()+"]");
}

// clean up the output by removing the bsh artifacts
String response = bodybuffer.toString();
String startkey = "bsh % bsh % ";
String endkey = "bsh % $bsh.break$";
int start = response.lastIndexOf(startkey)+startkey.length();
int end = response.lastIndexOf(endkey);
String trimmedResponse = response.substring(start, end);
SampleResult.setResponseData(trimmedResponse);

---

That's it. The test runs and pulls this xml file back as the sampler
response. Then I can run xpath extractors or other assertions on the
response data.

This lets me reach out to a cluster of servers and do a rapid check to see
that things are configured the way I expect them to be.

If anyone improves on this or has other suggestions for me I'm keen to hear
it.

Thanks,

Mark

Re: Accessing and asserting remote file system resources using BeanShell

Posted by Deepak Shetty <sh...@gmail.com>.
>I've proven with basic BeanShell that I can do this in a crude, raw fashion
outside of Jmeter.
How did you do this? If this worked why doesn't it work from within a JMeter
Beanshell Sampler.?

bsh.Remote wont work because (from the manual)
* If Remote can parse the return value of the script as an integer it will
return the value as the exit status to the command line. *
regards
deepak

On Thu, Dec 3, 2009 at 10:17 PM, Mark Miller <ma...@gmail.com>wrote:

> First off, a nod of appreciation to the contributors for this fantastic
> tool.
>
> I am using Jmeter to validate the integrity of some complex integrations.
> For these tests I use LDAP, HTTP, JDBC, and SOAP samplers extensively. It
> is
> providing great value.
>
> There is one final piece of my vision that I am struggling to achieve: I
> want to 'sample' from remotely running BeanShell servers by sending code
> that will find, read, and send back the contents of configuration files
> (for
> example) which I can then continue to evaluate in the sampler or with
> subsequent assertions. I've proven with basic BeanShell that I can do this
> in a crude, raw fashion outside of Jmeter.
>
> I have tried two approaches inside Jmeter:
>
> 1) Using a TCPSampler and sending java to the BeanShell telnet port
> (port+1).
> 2) Using a BeanShell sampler and directly invoking the bsh.Remote class.
> (see code below)
>
> import bsh.Remote;
> i = new Remote();
> ResponseMessage = (i.eval("bsh://localhost:9000","print(0);"));
>
> The main crux, it seems, is that the connection returns nothing until the
> BeanShell server itself exits. I also tried sending an exit() over to the
> server which allows it to send an exit code back - but also terminates the
> server process. So that doesn't do the trick. (Nor do I get the String data
> I am looking for, just an exit code.)
>
> I'm not quite on the right track with this. But I think the utility of the
> idea is so obvious that someone may have crossed this bridge.
>
> Anyone done anything like this and can provide some insights or point me in
> the right direction?
>
> I do appreciate your thoughts on this.
>
> --
> Mark Miller
>