Performance Testing of Tuxedo Applications with IBM Rational Robot

by John Straathof


This article describes the Zyntax Tuxedo Adapter (ZTA), a Robot API adaptor that greatly increases the usability of performance test scripts for BEA Tuxedo applications by translating raw Tuxedo buffer data into human-readable form. It supports all the major communication paradigms including synchronous, asynchronous, and conversational paradigms.


In this article I start with a description of the architecture of ZTA, one of the few existing third-party products that makes use of the IBM Rational Session Recording Extensibility framework. Next, I show an example recording of a small test application to give you an idea of the difference ZTA makes. Finally, I look at some specific issues that arise when real applications are used.

Performance Testing Tuxedo Applications

When Tuxedo applications require performance tests, a number of options are available. One common strategy is to modify the client application, but there are a number of disadvantages to using this technique. First, modifying the client application requires input from the developers, but ideally testing should be done outside of developer influence to prevent testers from making the same assumptions as the developers instead of actually testing those assumptions. Modifying the client code without developer influence, however, requires a high degree of knowledge on the part of the tester. Second, if the client application is modified, one can question if the test results really say something about the client application or only about the modified version of it (which never makes it into production). Third, generating, controlling, and executing multi-user tests and correctly interpreting the resulting test data can be very time-consuming with custom-made test solutions. Fourth, the source code for the application is not always available; this may happen when using third-party products that auto-generate code from high-level or GUI-based code, or when you are an external testing consultant who simply isn't allowed access to the code.

Standard test tools such as IBM Rational Robot do not have these disadvantages and are therefore preferred by many testing professionals.

Introducing the Zyntax Tuxedo Adaptor

When recording a test script on a Tuxedo application client at the socket level, Rational Robot intercepts calls to the Windows system libraries that write to the network. The resulting script consequently contains raw data. Data fragmentation, parallel communication threads, service-finding logic and data encryption are all verbosely reflected in the script (Figure 1). This not only makes interpretation of the script very hard, but also it may actually make the generated script unusable for multi-user tests because of session-specific information such as session "cookies" and service host resolution. When this session-specific data is not parameterized, a multi-user test either doesn't work or deviates so much from real usage the test result becomes irrelevant.

figure 1
Figure 1. Fragment of a VU script from a Tuxedo application recording without the ZTA

It is therefore desirable to perform the recording at a higher level (with less detail), preferably one in which the correspondence to the original application's intentions can be recognized. Figure 2 illustrates three recording levels for a client/server application that makes use of Tuxedo libraries.

figure 2
Figure 2. Recording levels

For the ZTA, the recording happens at the Tuxedo API level. So instead of intercepting calls to the Windows socket libraries or snooping at the network level, Robot intercepts calls from the application to the Tuxedo libraries and records them into a script. This way, most of Tuxedo's low-level functionality is hidden from the script, leaving only the data and high-level application structure.

ZTA Architecture

Robot provides an API to third-party developers that allows for interception of library calls to any Windows dynamic link library (DLL). (The documentation for this API is available to people who have Robot already installed. From the Start Menu, find the Rational Robot program group, and navigate to Rational Test/API/Session Extensibility. The authors have not been able to find the online version of this document.) Using the API requires the third party to provide three DLLs that are used by Robot:

  • Recorder
  • Filter
  • Script Generator

The Recorder DLL is invoked by Robot during the recording of a session. Before the actual recording starts, Robot queries the Recorder DLL for the target application library and a list of functions to be intercepted. During the recording, all calls from the application to the specified application library are intercepted and rerouted to the Recorder DLL. The recorder DLL knows how to interpret the data associated with the call and writes data to the session/watch file (Figure 3). It also calls the original function in the target library so the client application actually still works (not shown in the figure).

figure 3
Figure 3. Recorder architecture

Robot (RTL) intercepts the application client's calls to the application's library. Robot then writes data to the session watch file and makes calls to the Adaptor, which writes its own data to the session watch file. After the recording is finished, all entries in the session watch file (.WCH) are fed through the Filter DLL. The Filter DLL selects which entries the API adaptor is interested in (Robot itself writes entries to the session file as well).

After a selection of the session file entries has been made, the selected entries are fed to the Script Generator. The Generator can write whatever format it wants, but in the case of the ZTA, the Generator writes out statements using Robot VU syntax just like normal HTTP or socket recordings (Figure 4). Consequently, an experienced Robot user should be able to understand and make changes to the script in a straightforward manner.

figure 4
Figure 4. Filter and generator architecture

Robot reads data from the session watch file and translates this into a script. It also feeds the entries to the Filter DLL, which selects only those data elements the Generator wants. Using the filtered elements the Generator writes its own lines to the VU script.

After the script has been generated, it can be compiled without modification and then can be replayed. To support any extra functionality added by the API adaptor, a Replay library can be associated with a script. In the case of the ZTA, a header file exists that provides definitions for the symbols and custom function calls supplied by the ZTA.

Script Example

I'll now show a simple example to illustrate how the ZTA works (Listing 1). The script was recorded with the ZTA on a very simple client-server application with a single Tuxedo service call and was modified slightly for readability. For reference, the corresponding socket script is 200 lines long, of which about 60 percent was raw data like that shown in Figure 1.

The example can be divided into five blocks separated by empty lines: 1) definition headers, 2) initialization, 3) login, 4) service call, and 5) logout.

In the definition headers you can see the standard #include <VU.h> present in any VU script, plus the #include that reads the header file for the ZTA. The initialization line init_tuxedo() initializes the replay library, does a license check, configures Tuxedo, and so on. The code for this function call resides in the ZTA replay library.

The login block consists of three lines; the first allocates a memory block to hold login information, the second fills it with credentials and passes these to Tuxedo, and the third frees the memory block. Each of these lines corresponds closely to the Tuxedo ATMI (see the BEA documentation).

After the client has logged in, the service call block follows. A Tuxedo VIEW file, called view1, defines the service call input data format. (For those not familiar with Tuxedo, a VIEW file is a data format description file that defines type and size of the fields within requests and replies.) This particular VIEW defines a block of binary data 28 bytes long, holding a 2-byte integer field called svalue, a 4-byte integer called lvalue, and a 20-byte-long ASCII string called data. If you are calculating, the missing 2 bytes were filled by alignment padding.

In the service call block, two buffers are allocated: one for input data ( _idata) and one for output data ( _odata) returned by the server. The data() lines fill in fields in the input data buffer. The tpcall() line does the actual call to the Tuxedo subsystem. The output buffer _odata is then filled and available to the scripter to utilize. The block ends by freeing the allocated data buffers.

#include <VU.h>

#include <tuxedo.h>



tpalloc(_idata, "TPINIT", "NULL", 140); 

tpinit(_idata, "user", "host", "password", "", 0, 0, TPNOFLAGS); 

tpfree(_idata);  tpalloc(_idata, "VIEW32", "view1", 28); 

tpalloc(_odata, "VIEW32", "view1", 28); 

data(_idata, _short, "svalue", "5");

data(_idata, _long, "lvalue", "10");

data(_idata, _string, "data", pad1("these",20));

tpcall("TIMER1", "VIEW1", _idata, 28, _odata, TPNOFLAGS); 






Listing 1. Simple script example

What should be interesting for testing professionals is that the binary data block that was sent by the client has been split up per field, and the values have been translated to simple string representations. These could be replaced by values from a data pool in a straightforward manner. The data returned by the server is not shown in this script, but can be accessed easily through standard ZTA functions (see below).

The script ends with the tpterm() line, which closes down the connection to the Tuxedo service(s).


Once a script has been recorded successfully, you would normally want to parameterize the script so that a replay of the script with multiple virtual users produces a realistic load on the server(s).

There are two main goals in parameterization: validity (a script can replay without errors) and differentiation (different virtual users use different data). As you saw in the example script, the latter type of parameterization can be done in a straightforward manner by simply replacing literal strings with standard Robot data pool commands.

If the server returns session-specific data during a session, simply replaying a script will result in the server returning some kind of "bad session identifier" error. One normally identifies these kinds of session identifiers by looking for identical data strings between server return data and subsequent client requests, or recording a specific client action twice with exactly the same parameters, and then comparing the two generated scripts.

ZTA eases both these strategies by optionally providing translations of server return data using data() lines identical to the ones you saw used as input data building blocks. These return data translations are also useful to identify errors that occurred during the recording.

Once the session-specific data has been identified, ZTA's get_data() function can be used to retrieve any field from an output buffer. Listing 2 shows how the field called svalue would be retrieved from the buffer called _odata. The returned string can be used directly as a replacement for any literal string later in the script.

string id;

tpcall("TIMER1", "VIEW1", _idata, 28, _odata, TPNOFLAGS);

id = get_data( _odata, "svalue", 0 );

Listing 2. Example of parameterization

Tuxedo Environment

Most Tuxedo applications depend heavily on environment variables that describe the application configuration, such as the connection string, the location of the VIEW definition files, and the location of the Tuxedo software itself. These environment settings are used both by Tuxedo and the ZTA; Tuxedo needs the VIEW definitions files to construct requests, and ZTA uses these same files to interpret these requests and their responses.

The ZTA records the configuration environment at several stages during a Tuxedo session's lifetime and optionally writes lines to your script so that during replay the environment can be identical to that of the original client application.

Handling of Other Communication Paradigms

Our example above used the simplest of communication paradigms that is supported by Tuxedo: the synchronous client-server paradigm. In this paradigm, clients work in a serialized way, making one request to the server(s), waiting for a response, and then making further requests.

However, for some applications the client needs several pieces of data from different servers and does not care about the order in which these results come. In these cases, the asynchronous paradigm is preferable. In this paradigm, the client farms out requests to the servers without waiting for an answer until all the requests have been sent out. To keep track of which response corresponds to which request, Tuxedo clients are assigned unique identifiers for each request; these identifiers subsequently are returned along with the server response. The ZTA supports this paradigm in a straightforward manner, as the following simple script shows. Tuxedo developers may recognize the very close correspondence with the underlying ATMI function calls. Refer to the ATMI reference (see above) for an explanation of the tpacall and tpgetrply functions. The necessary variables to store the unique identifiers and buffer lengths are automatically inserted into the script.

int length1;

int rply1;

tpalloc(_idata, "FML32", "NULL", 0);

tpalloc(_odata, "FML32", "NULL", 0);

tpalloc(_buf3, "FML32", "NULL", 0);

tpalloc(_buf4, "FML32", "NULL", 0);

data(_idata, _string, "FIRST_NAME",    pad1("Betsy",6));

call1 = tpacall("FML32", _idata, 40, TPNOFLAGS);

data(_buf3,  _string, "FIRST_NAME",    pad1("Camilla",21));

call2 = tpacall("FML32", _buf3, 56, TPNOFLAGS);

data(_buf4,  _string, "FIRST_NAME",    pad1("Daniel",7));

call3 = tpacall("FML32", _buf4, 40, TPNOFLAGS);

tpgetrply(&call3, _odata, &length1, TPNOCHANGE); 

tpgetrply(&rply1, _odata, &length1, TPGETANY|TPNOCHANGE); 

tpgetrply(&rply1, _odata, &length1, TPGETANY|TPNOCHANGE);

tpfree(_idata); tpfree(_odata);

tpfree(_buf3); tpfree(_buf4);

Listing 3. Asynchronous script example

In both asynchronous and synchronous paradigms discussed above, each action is started by a client request and ended by a server response. Tuxedo also supports a communication paradigm where both client and server may start an action: the conversational paradigm. This paradigm is used by popular services such as telnet and SSH. The ZTA provides support for the Tuxedo conversational functions tpconnect, tpsend, tprecv, and tpdiscon in the same way as it supports the tpcall and tpacall/ tpgetrply functions.

You should realize that if the communication between participants in a conversational session is truly bidirectional, replaying a recorded script does not make much sense since the serial nature of the resulting script forces the session's conversation direction to be exactly the same as it is during the recording. However, in those cases where the conversation is "half-duplex" (each side talking in turns, yielding control of the channel to the other side at regular intervals), replaying the script may work well.

The ZTA currently does not support Tuxedo transactions (blocks of requests that will all be rolled back if one or more of the requests fail).


This article describes the Zyntax Tuxedo Adaptor, an IBM Rational Robot extension that allows testing of BEA Tuxedo versions 7 and higher. It also explains how an adaptor can be written to work alongside IBM Rational Robot. I've shown how ZTA is integrated with Robot through the Session Extensibility framework, and I provided and explained a simple example script to give an idea how ZTA works. I've also described how parameterization can be done. Finally, I've taken a look at the different communication paradigms and how ZTA supports them.


John Straathof has worked as a Performance Analyst or Product Manager in the testing field since 1989 for Performix, Pure Software, Pure Atria, and Rational Software. In 1999, John formed Zyntax Consulting.