Coding an associated test case
The source created after running the Associated Test Case Generation Utility will contain several programs concatenated as one large source. These individual programs contain the load module entry points to the exit point process. Some, such as TEST_INIT, TEST_ENTRY, TEST_TERM, and the CICS common routines will use a single exit point to its program logic using the IDENTIFICATION DIVISION’s PROGRAM-ID. Other programs, such as the CICS or Db2 functions calls have 2 exit points within the program using the ENTRY statement as the exit points. There will be one exit point for the input (INPT) side of the call and one for the output (OUTP) side. The input side represents the call at the point where the user application program is issuing a call to the subsystem. The output side represents the response from the subsystem that is being returned to the call in the user application.
Standard exit points
Exit point names can be a maximum of 72 characters. Truncation will occur after this length.
Test case programs require that the load module be linked with the REUS=RENT option. The default linkage editor option of REUS=NONE will not allow calls to test case exit points to take place.
When a test case is to run, the replay runner will issue a call to the required TEST_ENTRY exit point to get the process going. It is the responsibility of code in this user-written exit point to issue the call to the appropriate program to be tested. Failure to issue this call in the exit point will produce a very short execution as nothing will be run. The sample XML-style template shows this required call statement.
All other exit points are optional. The TEST_INIT and TEST_TERM exit points can have alternate names by specifying the appropriate TEST configuration INIT or TERM subcommand.
The CICS_CMA, CICS_CWA, CICS_PLT, CICS_TUA and CICS_TWA exit points cannot have their exit point names altered. These exit points are generally used for access to more common, system-level logic. If different logic is to be performed based on different test cases, then these exit points can be isolated in a new program. The new program can be referenced by the TESTCASE configuration command’s MODULENAME parameter list. Alternatively, the test name being run is passed to the exit point, so the exit point logic can check and perform the required test-dependent logic there.
For subsystem call exit points there will be capability for access at both the input and output side of the call. The exit point has a specific structure to the name to allow the Associated Test Case loader to automatically identify the exit point names for the tests. This structure’s format is: XXXX_YYYY_ZZZZ_PPPPPPPP where XXXX is the name of the subsystem (CICS, Db2, MQS or IMS). YYYY represents which side of the call the processing is for. This would be specified as either INPT or OUTP. ZZZZ is the 4-character code for the subsystem function call. For CICS and Db2 it is the hex identifier (in human-readable form) of the function, for IMS and IBM MQ it is the name of the function. PPPPPPPP is optional and represents the name of a specific program, or the file’s DD name in the case of file I/O. If specified, then this exit point is only for this program or file. If not specified, then this exit point is for any program that does not already have a specific exit point defined for this function. The #hlq.SBZUSAMP member BZUCODES contains a list of the various subsystem function call values.
For program-to-program interception exit points there will be capability for access at both the input and output side of the call. The exit point has a specific structure to the name to allow the Associated Test Case loader to automatically identify the exit point names for the tests. This structure’s format is: XXXX_YYYY_PPPPPPPP_CCCCCCCC where XXXX is the program-to-program identifier (PGM). YYYY represents which side of the call the processing is for. This would be specified as either INPT or OUTP. PPPPPPPP is required and represents the name of a specific program. CCCCCCCC is optional and must be specified if the interception was to a specific control section (CSECT). It represents the CSECT name.
The test name and iteration number arguments will be passed to each of the exit points. CICS specific exit points will additionally pass the CICS EIB and COMMAREA. For all subsystem-specific calls, arguments will be passed in exactly the same order and type as the user application program originally passed when it interfaced with the subsystem. It is important to understand that these exit points have access to various arguments and the code at the exit point can make changes, but do not try to extend the length of any of the arguments as this will cause a storage violation and unpredictable results can occur.
Exit points must return a return code. Possible values are 0, 4, 8 and 16, which correspond to the error level that is to be set when an argument mismatch occurs. The default error level is 4 if an exit point is not provided, however exit points can override this error level. A return code of 0 means that any argument mismatch for this specific exit point call will be flagged as informational. A 4 means warning, 8 means error and 16 means severe. These values are checked during replay and allow a user to prematurely stop the execution. Refer to the parameter STOP on the PARM of the JCL execution for more information.
Specific exit points that will not be called
- The CICS output (OUTP) exit point for EXEC CICS RETURN will never be called during a callback. This is because the execution of the return logic happens before any output exit is invoked. This is the case in both real CICS and during replay.
- The CICS output (OUTP) exit point for EXEC CICS XCTL will never be called during a callback. This is because the execution of the return logic happens before any output exit is invoked. This is the case in both real CICS and during replay.
- The CICS output (OUTP) exit point for EXEC CICS LINK will never be called during a callback, unless executing from zUnit’s test. This is because the OUTP record may not be available due to many other records that were recorded between the time the EXEC CICS LINK starts and the other programs in that execution path end, making the INPT and OUTP records severed from each other. This would cause an abend in the logic during replay.
Copy files used by exit point routines
References to copy files will be generated in the resulting test case exit point program. These copy files are for managing the arguments for Db2 calls. The #hlq.SBZUSAMP contains the members for these copy files. Any compilation should reference this data set for copy file resolution.
Compiler requirements for exit point programs
- For COBOL, the compiler options PGMN(LM) and QUALIFY(EXTEND) must be used.
- For PL/I, the compiler option DLL and LIMITS(EXTNAME(72)) must be used. For link edit, the option DYNAM=DLL must be used.
Issuing assertions from an exit point
Exit point logic can interface with the replay runner using assertions if desired. These assertions can embed messages in the runner output. If a higher code level is needed, the assertions can set condition codes. The condition code set by the assertion can even stop the runner execution if it reaches the stop level set by the STOP parameter from the execution JCL.
To issue an assertion from the exit point logic, a call would be made to the assertion program (BZUASSRT). This program accepts 4 arguments. All arguments are by reference, meaning that the address of the argument is passed.
The first argument is a 4-byte integer that contains the condition code level to set. This condition code value will be either 0, 4, 8 or 16 representing the levels I (informational), W (warning), E (error) or S (severe). The assertion’s condition code cannot reduce the existing condition code level already set by the runner. For example, if the runner’s current condition code is at the warning level, an assertion condition code setting cannot reduce that to an informational level. Any attempt to reduce the level is ignored.
The second argument is a 4-byte integer that contains a user-defined message identification number. This number is not used internally but provided in the XML results file when test cases are used.
The third argument is a 3-byte character area that contains a user-defined message component code. This component code is not used internally but provided in the XML results file when test cases are used.
The fourth argument is an area of memory that contains the message to be inserted into the runner’s output. The format of this area is a 2-byte integer containing the length of the text that immediately follows the length field. The length can be any value from 0 to 32767 and the value excludes the length of the length itself. The length represents the true length of the actual text. If the text is greater than 120 characters, then it will be broken up into consecutive messages each of which is a maximum length of 120 characters.
Issuing trace messages from an exit point
Exit point logic can interface with the replay runner and write trace messages if desired. These trace messages are essentially assertions with a 0-condition code but have been provided their own module to call to prevent confusion about usage. This allows assertions to be used as assertions and traces as traces.
To issue a trace from the exit point logic, a call would be made to the trace program (BZUTRACE). This program accepts 1 argument. The argument is by reference, meaning that the address of the argument is passed.
The argument is an area of memory that contains the message to be inserted into the runner’s output. The format of this area is a 2-byte integer containing the length of the text that immediately follows the length field. The length can be any value from 0 to 32767 and the value excludes the length of the length itself. The length represents the true length of the actual text. If the text is greater than 120 characters, then it will be broken up into consecutive messages each of which is a maximum length of 120 characters.
| Special character | Replacement text |
|---|---|
| < | lt; |
| > | gt; |
| & | amp; |
| " | quot; |
| ' | apos; |
Managing exit point load modules
As a user starts to create more and more exit point load modules, they will notice that they are having exit point name collisions because the same name was generated by the Associated Test Case Generation Utility for the TEST_INIT, TEST_ENTRY and TEST_TERM exit points. There are several ways to manage these collisions. When a test case is run the name of the load module(s) to be loaded into the replay environment are defined using the TESTCASE configuration command’s MODULENAME parameter. This command allows you to limit the loading of test case exit points to specific load module names to be used for the test, preventing other load modules with these duplicate names from being used.
If a user wants to load many exit point load modules for the test, then a more generic list of modules names would be specified. As multiple load modules will be loaded, it will cause exit point name collisions. In this case a user can change the name of the TEST_INIT, TEST_ENTRY and TEST_TERM exit points in the exit point source and recompile. These exit point names are specified using the TEST configuration ENTRY subcommand, allowing a user to specify the unique name of the exit point to use for the test. By providing unique test case exit point names in the source and referencing these names through the configuration file, collisions can be avoided.
Creating new playback files without rerunning collection
It is possible to create a new playback file that merges the data from a current playback file along with the updates from all exit point callbacks that were executed. This will allow a user to incrementally create new playback files without having to keep exit point logic around. The modifications to the arguments from an exit point can be saved into a new playback file, even if the exit point is providing new data without an existing playback record. This new playback file can then be used to replay the application programs.
In order to create a new playback file with the merged exit point data, a new BZUNEXT DD statement needs to be added to the replay JCL. There are no execution options needed. The mere existence of the DD statement triggers the processing. The BZUNEXT DD statement must point to a new variable-blocked sequential dataset with block size of 32760 and logical record length of 32756, or a fixed-block sequential dataset with logical record length of a reasonable size balancing both the average size of the records and the amount of wasted space there will be. A reasonable recommendation is 256 bytes.
This capability can be used with or without IBM® Developer for z/OS®. Note that if it is used by IBM Developer for z/OS, then care should be taken if the test case option RESETFILE is set to TRUE. By setting the option to TRUE, it will cause the resulting BZUNEXT data set to contain a concatenation of all test case runs.