For the testing of servers

If the only tool you have for testing your server is a GUI, you are going to be embarrassed occasionally.

For feature testing, for load testing and much more, you need a mock client.

Enter mock_client.pl.

Usage:

  mock_client.pl [-l] [-q|-v] [a=b ...] [-m min_delay] [-x max_delay] [-f line_num] [-t line_num] config.csv

or

  mock_client.pl -h

eg:

mock_client.pl host=127.0.0.1 Username=user Password=pass -f 5 -t 10 mock_client.csv

Options

-l = loop forever – once csv file has been sent, resend it, forever. Incompatible with -f and -t

-q = quiet – show only a few characters for each request sent – incompatible with -v
-v = verbose – show each message sent/received – incompatible with -q

a=b = constants to be populated into templates

-m min_delay = minimum time in seconds between requests – sits idle, if necessary – compatible with -x
-x max_delay = maximum time in seconds between requests – sends in parallel, if necessary – compatible with -m

-f line_number = start sending from this line number – incompatible with -l
-t line_number = send up to this line number – incompatible with -l

config.csv = config file containing the messages to be sent.

The config file

The config file must be in comma separated format.

For example:

 FILES,NAME,STREET,POSTCODE
 "message_1.xml","John Smith","Wall St","54321"
 "message_2.xml;message_3.xml","Peter Pan","Never-never St","12345"

Row 1 of mock_client_config.csv must contain headings for every column in the file.

One of the columns must have “FILES” as its heading.  This column contains names of files to be sent.

All other columns represent values to be injected into the messages being sent.

For example, message_1.xml might contain:

 ...<PostCode>${POSTCODE}</PostCode>...

When message_1.xml is sent, this will be sent as:

 ...<PostCode>54321</PostCode>...

Every row after the header row represents a session. Each session consists of one or more messages to be sent to the server, as well as parameter values to be injected.  Where a single session contains more than one message, the file names must be seperated by “;”.

Individual fields may optionally be wrapped with double quotes. This is standard behaviour for some spreadsheet programs, and allows cells to contain embedded commas or leading or trailing whitespace.  Embedded newlines are not supported.

As well as the config csv file, parameter values may also be provided on the command line, using the A=B format.  Such parameters apply to all sessions.

For XML interfaces, parameterised values may also be taken from the response to an earlier message sent in the same session.  This allows testing of some scenarios where information isn’t known in advance but is instead provided by responses as the test progresses.

For example, it might be desirable to create an object on the server, then retrieve the newly created object using its ID, as returned in the original request, update it, then delete it.

If so, the .csv file might contain:

 FILES,...
 "create.xml;retrieve.xml;update.xml;retrieve.xml;delete.xml",...

And response to the create.xml request might contain a string such as:

 <allocated_object>123</allocated_object>

If so, then this response can be used in the next request, for example:

<target_object>${allocated_object}</target_object>

And this would be expanded to:

 <target_object>123</target_object>

There are limitations on this feature. The node must not re-appear in a different place, and only simple elements are supported, not complex elements, nor values containing embedded newlines.

For example, suppose the response contains:

 <allocated_object><x>123</x><y>456</y></allocated_object>

It would not then be possible to then use:

 <target_object>${allocated_object}</target_object>

This will simply fail, complaining that ${allocated_object} is not defined.

If the format of the field doesn’t change, it might be possible to get the desired result with:

 <target_object><x>${x}</x><y>${y}</y></target_object>

The script reports if the value of a node as returned by the server changes from one respose to the next.  When different nodes have the same name, the comparison is skipped. This avoids some false warnings but might miss some real changes.  You may wish to comment out this behaviour.

A string of the format ${PARAM_NAME|Default Value} can be used to indicate a parameter with a default value which will be used when the parameter is not provided by any of the other mechanisms described above.

Lines in the CSV file, except for the inital header line, may be commented out with a leading ‘#’. A ‘#’ is also treated as a comment if it follows a single ‘”‘, which is what will many spreadsheet programs will write into a .csv file if the first cell in a row begins with a ‘#’.

Normally, sessions are numbered 0001, 0002, 0003, etc. If a column has the heading SESSION, its values will be used to name each session.

${ATTACHMENT} is magic. Instead of the usual behaviour of injecting the value of ${ATTACHMENT} into the message, mock_client.pl runs encode.bat with the value of ${ATTACHMENT} as the only parameter and the output from encode.bat is injected into the message to be sent.

Normally, sessions are numbered 0001, 0002, 0003, etc. If a column has the heading SESSION, its values will be used to name each session.

${ATTACHMENT} is magic. Instead of the usual behaviour of injecting the value of ${ATTACHMENT} into the message, mock_client.pl runs encode.bat with the value of ${ATTACHMENT} as the only parameter and the output from encode.bat is injected into the message to be sent.

Remote destination

When sending .xml files to a soap server, they must include a HTTP header, including Network address details
Eg:

 POST /gateway HTTP/1.1
 Accept-Encoding: gzip,deflate
 Content-Type: text/xml;charset=UTF-8
 SOAPAction: "http://localhost:8888/gateway"
 User-Agent: Jakarta Commons-HttpClient/3.1
 Host: localhost:8888
 Content-Length: 1

Note that Content-Length is ‘magic’, the script will automatically fill in the right value if the string is provided.  It will not add it in if it is missing.

The header can also be parameterised, either from the cmd line or the .csv file, eg:

SOAPAction: "http://${host}:8888/gateway"

If your message contains a SOAPAction line, eg: “http://host.company.com:1234&#8221;, then this will be used to determine the remote host and port.

Alternately, the config parameters ${host} and ${port} will be used.

There are no defaults for these values. If they are not provided on the command line or in the config file, an error will result.

Timings

The default delay behaviour is to send each request as soon as a response to the previous request is received.

-m and -x can be used to set a minimum and/or maximum delay between requests, so as to ensure requests are sent no faster/slower than a certain speed

-m min_time – wait at least this many seconds between requests. If the response arrives within min_time seconds, the script waitsuntil min_time has passed.  If the response takes longer than min_time, the next request is sent as soon as the response arrives, or as specified by -x.  This can be used to cap the sending speed.

-x max_time – wait at most this many seconds between requests. If the response does not arrive within max_time seconds the next request is sent  in parallel with the previous request.  This can be used to force a certain rate of requests – even if the server cannot keep up. This can cause problems where one request depends on the previous response having been returned already.

-m and -x may both be used, so long as the minimum value does not exceed the maximum value.

Eg to send requests no faster than 1 every 5 seconds, and no slower than one every 10 seconds:
mock_client.pl -m 5 -x 10 mock_client.csv

Eg to send requests exactly once a minute
mock_client.pl -m 60 -x 60 mock_client.csv

-m and -x are applied per request, if there is a mix of slow and fast responses the script does not try to ‘catch up’. Exercise for the reader, if you need this behaviour.

Fractions of a second are supported for -x, not for -m. Exercise for the reader if you have a need for this behaviour.

Logging

Mock_client.pl outputs a summary to stdout and writes details to a log file, the core name of which is the same as the .csv file, plus a time stamp, plus a trailing number for uniqueness, if required.

For eg, if the config is mock.csv, the log filename will have the format mock.2012.10.29_18:20.log, and if it is run twice or more in the same minute, mock.2012.10.29_18:20-2.log, etc.

What is/is not written to stdout is configurable using the -v and -q parameters.

The default is to print errors and informationals to screen. Log files always contain everything.

-v    print errors and informationals and debug messages to screen.
-q    print major errors and major informationals to screen, prints just a few characters for other things.

if -q is set, then when the following events occur, the following characters are printed:
start of a session        _
a message is sent        /
a response is received        \
a failure occurs        !
a null response is returned    0
successful end of session     +
repeating all tests (i.e. -l)    |

For eg, two sessions, containing 1 message and 2 messages respectively, might look like this if there are no errors:

 _/\+_/\/\+

Or like this, if there are

_!_!

Note that the errors were sort of fatal. (In this case, failed to connect.)Where the session has more than one message,  a fatal error causes the remaining messages not to be sent. Instead, the script continues with the next session, if any.

Advertisements