SimCon logo

SimCon - Fortran Analysis, Engineering & Migration

  FPT Reference ManualDownloadsLicensingHome

 
 
 
 
 
FPT - Fortran Regression Testing - Record and Replay of Program Execution
 
Record/ Replay

The record / replay mechanism is used in regression testing and in migration of Fortran codes.

FPT adds statements to the code to capture all of the data read in to a program and all of the data written out. The changes are made in such a way that the input data can be replayed into the program, replacing interactive interfaces and file I/O.

If you have a program is controlled by a long interactive menu, testing is tedious because the menu items must be entered by hand. The record / replay mechanism allows them to be captured once and replayed automatically.

If you have a program which interacts with a large database file, the database must be set to the same state every time testing is carried out. Record / replay can replace the database by replaying the database inputs so that the program receives the same input data every time.

Every Fortran logical unit, and every sub-progam and memory interface may be selected for replay independently. You can replay the interactive I/O, for example, without replaying some or all of the file I/O.

FPT instruments the user's code to capture and to replay:

File and terminal I/O

The arguments of interface routines

Interfaces to shared memory

For example:

Click here to see a code example before modification.

Click here to see the changes which FPT makes.

 

The changes which FPT has made

FPT has inserted an INCLUDE statement for declaration of the variables used to control record and replay.

INCLUDE 'rr_cmn.fpi'

The control variables, RR_LUN_FOR_REPLAY, RR_OUTPUT_RECORD_F etc. are in COMMON blocks. The file also contains declarations of the control functions such as REPLAY_IO(N,UNIT). This function determines whether the unit is being replayed or not.

The OPEN statement has been enclosed in a test to find whether or not the unit, in this case unit 7, is being replayed.

IF (.NOT. REPLAY_IO(1,7)) THEN OPEN (7,FILE='VISCOSITY.DAT',ACCESS='DIRECT',STATUS='OLD') ENDIF

If unit 7 is replayed from the captured data, we don't need to open the file. This means that the original files don't need to be present when the code is tested.

The read of the viscosity array has been enclosed in a test.

IF (REPLAY_IO(2,7)) THEN READ (RR_LUN_FOR_REPLAY,*)RR_IOSTAT READ (RR_LUN_FOR_REPLAY,*)VISCOSITY(I) ELSE READ (7,REC=I,IOSTAT=RR_IOSTAT)VISCOSITY(I) ENDIF

If unit 7 is being replayed, VISCOSITY(I) is read from the replay file. If not, the original READ statement is executed.

FPT inserts code to capture the values from the viscosity file.

IF (RR_INPUT_RECORD_F) THEN WRITE (RR_LUN_TO_RECORD_INPUT,*)RR_IOSTAT WRITE (RR_LUN_TO_RECORD_INPUT,*)VISCOSITY(I) ENDIF

The original READ statement had an END= destination. This has been replaced by capturing the IOSTAT value in the READ. The IOSTAT is replayed to the variable RR_IOSTAT and this is used to control jumping to the error destination by the statements:

IF (RR_IOSTAT .NE. 0) THEN GOTO 200 ENDIF

RR_IOSTAT is also replayed from the recorded file, so that the recording behaves in exactly the same way as the original code.

The WRITE statement to unit 1 is modified in a similar way. Once again, the statement is enclosed in a test, and is not executed if unit 1 is being replayed. The file does not need to exist during testing.

IF (.NOT. REPLAY_IO(3,1)) THEN WRITE (1,100) ENDIF IF (RR_OUTPUT_RECORD_F) THEN WRITE (RR_LUN_TO_RECORD_OUTPUT,100) ENDIF 100 FORMAT (/,'Viscosity table read successfully')

Note that FPT captures the outputs from the program as well as the inputs. In a migration project, the outputs may be compared on the old and new hosts as a diagnostic tool.

 

The Extent of the Changes

FPT has re-written so much of this small subroutine that it is almost unrecognisable. This is not typical. It has happened because the subroutine contains almost nothing but I/O statements. Usually, the record / replay process makes very few changes to a large program.

 

A Shared Memory Location

Many programs have interfaces which are shared memory locations. These may also be instrumented for record and replay. In the code fragment below, VISBUFR is part of a memory block shared between a simulation program and the visual scene generator.

C Only the visual system knows where the ground is RADAR_ALT=-RVISBUF(3)

To instrument this interface, we need to tell FPT that the memory is shared. This is done by annotating a declaration of VISBUFR. The annotation doesn't need to be in the main code body. It can be written in a small template file which is used only by FPT. The annotation would be, for example:

COMMON /VISBUF/ RVISBUF(20),IVISBUF(200) C% Record/replay interface:: RVISBUF

The comment beginning C% has special meaning to FPT.

FPT then modifies the original statement to read:

C Only the visual system knows where the ground is C RADAR_ALT=-RVISBUF(3) IF (REPLAY_INTERFACE(1,'RVISBUF')) THEN READ (RR_LUN_FOR_REPLAY,*)RVISBUF_TMP(3) ELSE RVISBUF_TMP(3)=RVISBUF(3) ENDIF IF (RR_INPUT_RECORD_F) THEN WRITE (RR_LUN_TO_RECORD_INPUT,*)RVISBUF_TMP(3) ENDIF RADAR_ALT=-RVISBUF_TMP(3)

The original statement is commented-out. Note how replay of the specific interface is controlled by the logical function REPLAY_INTERFACE(N,NAME).

FPT has added a new array, RVISBUF_TMP to the code. This has the same bounds and type as the original array RVISBUF and is declared wherever it is needed.

 

A Sub-Program Interface

Programs may communicate with external devices or other programs through sub-program arguments. To instrument these interfaces, FPT requires a declaration that the sub-program is an interface, and needs either the code of the sub-program, or a template which indicates the INTENT of the arguments - whether they are inputs, outputs or both. Templates may be written in small files outside the main body of the code, which are processed only by FPT. For example:

C Template for MACRO routine TO_RADALT C% Record/replay interface TO_RADALT SUBROUTINE TO_RADALT(V,IADD,IE) C% INTENT (IN) :: V C% INTENT (IN) :: IADD C% INTENT (OUT) :: IE END

A call to TO_RADALT, for example:

CALL TO_RADALT(RADAR_ALT,23,ISTAT)

is instrumented to read:

IF (REPLAY_INTERFACE(2,'TO_RADALT')) THEN READ (RR_LUN_FOR_REPLAY,*)ISTAT ELSE CALL TO_RADALT(RADAR_ALT,23,ISTAT) ENDIF IF (RR_INPUT_RECORD_F) THEN WRITE (RR_LUN_TO_RECORD_INPUT,*)ISTAT ENDIF IF (RR_OUTPUT_RECORD_F) THEN WRITE (RR_LUN_TO_RECORD_OUTPUT,*)RADAR_ALT,23 ENDIF

 

Copyright ©1995 to 2015 Software Validation Ltd. All rights reserved.