HP DECset for OpenVMS
Cookbook for an Integrated Project Development Environment


Previous Contents

6.5 Using DTM on the Display Under Test

When only a single workstation is available for both the application under test and to run DTM, output from the DTM windows can affect the tests. However, there are ways to reduce the impact on the tests. The method depends, to some extent, on which interface is used---either the command line or the DECwindows Motif interface.

DTM displays informational and other messages when tests are recorded, played, and run. With the command line interface, these messages are displayed in the DECterm window in which the DTM command was entered.

With the DECwindows Motif interface, the messages are displayed in a separate window. You can choose as to whether or not to have these windows visible while the tests are running. If the windows are visible, they will appear in screen saves and will need to be masked in order for DTM to provide successful comparisons. The messages displayed in these windows during recording and any text which is redrawn when the window is exposed after being hidden, will become synchronization text for the test. Since the messages output during play or run commands will usually not match those during recording, the test will wait for the timeout period for each synchronization point, which may slow the test down considerably.

One resolution to this problem is to update the session file to remove the synchronization text that does not occur on playback. This can be done automatically by using the PLAY/AUTOSYNC command, or by checking the Auto synchronize box on the Play window. While the test is playing, the F9/F key sequence can be used to avoid waiting for the timeout period.

As an alternative, testing can be conducted with the message windows minimized. This has the disadvantage that if errors are reported, the messages are not immediately visible. In addition, it may not be apparent when tests have completed. However, these are probably outweighed by the advantage of not needing to mask the windows.

The simplest way of minimizing the message windows is to include the click on the Minimize button in the test. On systems running DTM Version 3.9 or later, the window position is fixed and under user control, as described in the Digital Test Manager for OpenVMS Release Notes. For systems running earlier versions, the position varied according to the tiling algorithm built into DECterm, so this method would not work.

An alternative is to pause the test, minimize the windows, and resume the test. This can be done using the key sequences F9/A to pause, and F9/B to resume.

6.6 Starting the Application Under Test

There are several ways to start the application to be tested. When DTM is running on a node different from the one on which the application windows are displayed, these methods result in the application being run on either the same node as DTM or on the system being used as the display. The application can always be made to run on the display system by submitting the test collection to a queue on the system, even if the DTM command is entered on another node.

One method is to start the application via the Session Manager Applications menu. This causes the application to run on the display system. It is also possible to start the application from a DECterm window that is running on the system.

The other methods result in the application running on the same node as the collection, or DTM, in the case of RECORD and PLAY commands.

The application can also be started by a DCL command associated with the test. This can be set with the /COMMAND qualifier to the DTM CREATE TEST or DTM MODIFY TEST commands, or the corresponding DECwindows Motif interface windows, accessed from the Maintenance menu. Note that this command is not executed when the test is recorded or played using the character cell interface and must be entered again using the /COMMAND qualifier. This is also true in the DECwindows Motif interface, although if the test is selected before choosing Record or Play from the Testing menu, the Command field will be filled in with the command automatically.

Finally, the application can be started by a DCL command in the test prologue file. However, the prologue is only executed when the test is run as part of a collection, so the application must be started externally or by using the /COMMAND qualifier for the RECORD and PLAY commands.

6.7 Using the Play/Record User Interface

Use of the Play/Record User Interface, also referred to as the Record Tool Window, is not recommended. Pointer movements, button presses and output associated with these windows will almost certainly interfere with the smooth running of tests. The windows will also appear in the screen saves during record and playback and will need masking to prevent unsuccessful screen comparisons. This applies whether a single system is used or when a second display is used for DTM.


Appendix A
CMS Callable Routine Examples

The following sections contain a series of sample C programs that demonstrate how CMS callable routines can be used.

A.1 Reserving and Replacing Elements

Example A-1 uses the CMS callable routines to reserve and replace elements in a CMS library.

Example A-1 CMS Callable Routines: RESERVE and REPLACE

/* 
**  FACILITY: 
** 
**      CMS_EXAMPLE1.C 
** 
**  ABSTRACT: 
** 
**      Example program illustrating how CMS callable routines 
**      can be used to reserve and replace elements in a library. 
** 
**      3 routines are used:  CMS$SET_LIBRARY 
**                            CMS$REPLACE 
**                         &  CMS$FETCH      - there's no CMS$RESERVE 
** 
*/ 
#include <descrip.h>    
#include <lib$routines.h> 
#include <ssdef.h> 
#include <stdio.h> 
#include <string.h> 
#include <ctype.h> 
 
int cms$set_library (); 
int cms$fetch (); 
int cms$replace (); 
 
main() 
{ 
typedef struct dsc$descriptor_d DESCRIPTOR; 
#define DESC_BLD(name)      DESCRIPTOR name = {0,DSC$K_DTYPE_T,DSC$K_CLASS_D,0} 
#define DESC_FIL(name,str)                             \
        name.dsc$w_length = strlen(str);                \
        name.dsc$a_pointer = str 
 
/* 
** Allocating space for the library data block (LDB).  The LDB is a user- 
** allocated structure, CMS uses to maintain information about the library. 
*/ 
int    library_data_block [50]; 
int    status; 
int    reserve; 
char   action = ' '; 
char   element_list[80]; 
char   remark[80]; 
 
DESC_BLD(remark_desc); 
DESC_BLD(element_desc); 
DESC_BLD(library_desc); 
DESC_FIL(library_desc,"LIB$DIR"); 
 
    /* Set to the CMS library */ 
    status = cms$set_library (&library_data_block, &library_desc); 
    if (! (status & SS$_NORMAL)) 
        { 
        lib$signal(status); 
        return status; 
        } 
 
    do { 
      /* Reserve or Replace ? */ 
      printf("\nG. Get a File\n"); 
      printf("R. Replace a File\n"); 
      printf("Q. Quit\n\n"); 
 
      do { 
           printf("Make your selection : "); 
           gets(&action); 
           action = toupper(action); 
      } while (action != 'G' && action != 'R' && action != 'Q'); 
 
      /* Action menu */ 
      switch(action) { 
          case 'G': 
             /* Reserve */ 
             printf("Enter File name(s):"); 
             gets(element_list); 
             /* Remark */ 
             do { 
               printf("Why [80]? "); 
               gets(remark); 
             } while (strlen(remark) <= 1);   
 
             /* 
             ** CMS$FETCH ( LIBRARY_DATA_BLOCK,  by reference 
             **             ELEMENT_EXPRESSION,  by descriptor 
             **             [REMARK],            by descriptor 
             **             [GENERATION_EXRESSION], always get latest 
             **             [MERGE_GENERATION_EXRESSION], not used 
             **             [RESERVE],      1 = reserve, (by reference) 
             **                ... ) 
             */ 
             DESC_FIL(remark_desc, remark); 
             DESC_FIL(element_desc, element_list); 
             reserve = 1; 
             status = cms$fetch (&library_data_block, 
                                 &element_desc, 
                                 &remark_desc,0,0, 
                                 &reserve); 
             if (! (status & SS$_NORMAL)) 
             { 
               lib$signal(status); 
               return status; 
             } 
             break; 
 
          case 'R': 
             /* Replace */ 
             printf("Enter File name(s):"); 
             gets(element_list); 
             /* Remark */ 
             do { 
               printf("Why [80]? "); 
               gets(remark); 
             } while (strlen(remark) <= 1);   
 
             /* 
             ** CMS$REPLACE ( LIBRARY_DATA_BLOCK,  by reference 
             **               ELEMENT_EXPRESSION,  by descriptor 
             **               [REMARK],            by descriptor 
             **                  ... ) 
             */ 
             DESC_FIL(remark_desc, remark); 
             DESC_FIL(element_desc, element_list); 
             status = cms$replace (&library_data_block, 
                                   &element_desc, 
                                   &remark_desc); 
             if (! (status & SS$_NORMAL)) 
             { 
               lib$signal(status); 
               return status; 
             } 
             break; 
 
 
          default: 
             /* Quit */ 
             printf("\nGood Bye"); 
      }  
    } while (action != 'Q'); 
 
    return SS$_NORMAL; 
} 
 

A.2 Showing and Formatting Reservation Information

Example A-2 illustrates how the CMS callable routines can be used to customize the output of a SHOW RESERVATION command.

Example A-2 CMS Callable Routines: SHOW RESERVATION

/* 
**  FACILITY: 
** 
**      CMS_EXAMPLE2.C 
** 
**  ABSTRACT: 
** 
**      Program to illustrate how the CMS callable routines can be 
**      used to create a customized version of the SHOW RESERVATIONS 
**      command. 
** 
**      2 routines are used:   CMS$SET_LIBRARY 
**                             CMS$SHOW_RESERVATIONS 
** 
**      The include file CMS$ROUTINES.H, which defines the CMS callable 
**      routine entry points and the CMS error message symbols, is created 
**      from the file SYS$SYSROOT:[SYSHLP.EXAMPLES.CMS]CMS$ROUTINES.SDL. 
**      The command to create the file is $SDL/LANG=CC CMS$ROUTINES.SDL. 
**      The SDL processor can be obtained from the OpenVMS Freeware CD. 
** 
**  IMPLICIT INPUTS: 
** 
**      This program assumes the current CMS library has been set. 
** 
*/ 
#include <ctype.h> 
#include <descrip.h> 
#include <lib$routines.h> 
 
#include <ssdef.h> 
 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include "cms$routines.h" 
 
#define LDB_SIZE        50 
 
typedef struct dsc$descriptor_s DESCRIPTOR; 
 
/* 
**  strCreateFromStringID 
** 
**  Extract a character string from a CMS string identifier. 
** 
*/ 
 
char* strCreateFromStringID( DESCRIPTOR* desc ) 
{ 
  char* string;    /* string copied from desc */ 
 
  string = malloc( desc->dsc$w_length + 1 ); 
  if (string == NULL) { 
    printf("Fatal storage allocation failure.\n"); 
  } 
  else { 
    strncpy( string, desc->dsc$a_pointer, desc->dsc$w_length ); 
    string[desc->dsc$w_length] = '\0'; 
  } 
 
  return string; 
} 
 
/* 
**  Output Routine 
** 
**  This routine is called by CMS$SHOW_RESERVATIONS once for each reservation 
**  in the CMS library.  The information about the reservation is passed to 
**  this routine in the argument list. 
** 
**  Details of the parameter passing mechanism may be found in the "DIGITAL 
**  Code Management System Callable Routines Reference Manual". 
** 
*/ 
 
static int output_routine( int* new_element, 
      int* library_data_block, 
      int* user_param, 
      DESCRIPTOR** element_id, 
      DESCRIPTOR** generation_id, 
      int* time, 
      DESCRIPTOR** user_id, 
      DESCRIPTOR** remark_id, 
      int* concurrent, 
      DESCRIPTOR** merge_generation_id, 
      int* nonotes, 
      int* nohistory, 
      int* access, 
      int* reservation_id ) 
 
{ 
 
  char* element_name;                    /* element name string */ 
  char* generation;                      /* generation string */ 
  char* username;                        /* username string */ 
  char* remark;                          /* remark string */ 
 
  /* Extract character strings from CMS string identifiers */ 
  element_name = strCreateFromStringID( *element_id ); 
  generation = strCreateFromStringID( *generation_id ); 
  username = strCreateFromStringID( *user_id ); 
  remark = strCreateFromStringID( *remark_id ); 
 
  /* 
   * Generate the output string.  The format is: 
   * 
   *  element-name  generation  reservation-id  username  remark 
  */ 
 
  printf( "%s  %s  %d  %s  \"%s\"\n", 
   element_name, 
   generation, 
   *reservation_id, 
   username, 
   remark ); 
 
  /* Free the memory allocated for character strings */ 
  free( element_name ); 
  free( generation ); 
  free( username ); 
  free( remark ); 
 
  return( CMS$_NORMAL );       /* Successful completion */ 
} 
 
int main( int argc,   /* arg count from command line */ 
   char* argv[] )  /* arg pointers */ 
{ 
 
 int   library_data_block[LDB_SIZE]; /* LDB structure */ 
 int   status;        /* completion status from CMS routines */ 
 
 $DESCRIPTOR( element_desc, "*.*" ); /* default element name for SHOW */ 
 $DESCRIPTOR( library_desc, "CMS$LIB" ); /* CMS library name */ 
 
 
 /* Check for element name(s) specified on the command line. */ 
 if (argc > 1) {   /* use supplied value, if present */ 
   element_desc.dsc$a_pointer = argv[1]; 
   element_desc.dsc$w_length = strlen(argv[1]); 
 } 
 
 /* 
  * The LDB must be initialized before using the CMS callable routines. 
  * This is done by calling CMS$SET_LIBRARY.  For the purposes of this 
  * example, we assume the library has already been set by a previous 
  * CMS SET LIBRARY command, so the logical name CMS$LIB translates to 
  * the library name. 
  * 
  */ 
 status = cms$set_library( &library_data_block, &library_desc ); 
 
 if (! (status & SS$_NORMAL)) { 
     switch( status ) 
       { 
       case CMS$_NOREF:                   /* library access error */ 
  printf("Unable to access CMS library\n"); 
  return status; 
 
       default:                           /* unexpected error */ 
  printf("Unexpected error returned from CMS$SET_LIBRARY\n"); 
  lib$signal( status ); 
  return status; 
       } 
 } 
 
 /* Get the reservation information for the library */ 
 status = cms$show_reservations( &library_data_block, 
     output_routine, 0, 
     &element_desc, 
     0,0,0,0 ); 
 
 if (! (status & SS$_NORMAL)) { 
     switch( status ) 
       { 
       case CMS$_NORES:               /* no reservations found */ 
  printf("There are no reservations in the library\n"); 
  break; 
 
       default:                       /* unexpected error */ 
  printf("Unexpected error returned from CMS$SHOW_RESERVATIONS\n"); 
  lib$signal( status ); 
  return status; 
       } 
 } 
 
 return SS$_NORMAL; 
} 
 

A.3 Showing and Filtering Element Information

Example A-3 demonstrates how to implement a version of the SHOW ELEMENT command with customized element selection criteria. It also shows how data can be passed from the user program to the CMS callback routine using the user_arg parameter.

Example A-3 CMS Callable Routines: SHOW ELEMENT

/* 
**  FACILITY: 
** 
**      CMS_EXAMPLE3.C 
** 
**  ABSTRACT: 
** 
**      Program to illustrate how the CMS callable routines can be 
**      used to create a customized version of the SHOW ELEMENT 
**      command.  The program also demonstrates how to pass information 
**      from the user program to the output callback routine using the 
**      user_param argument to the CMS callable routines. 
** 
**      This program displays information about elements in a CMS library 
**      which match user specified criteria.  The criteria available are 
**      whether the REFERENCE_COPY attribute is set or not and whether or 
**      not a notes string is specified. 
** 
**      The program must be invoked as a foreign command (i.e., via a DCL 
**      symbol) to pass parameters on the command line.  To do this, define 
**      a symbol such as the following: 
** 
**              $ SHOWELE == "$dev:[dir]CMS_EXAMPLE3" 
** 
**      The program would then be invoked as follows: 
** 
**              $ SHOWELE [element-expression [attribute [attribute]]] 
** 
**  INPUTS: 
** 
**      (1) element expression - specifies the elements or groups to 
**          include in the search.  The default is *.*. 
** 
**      (2)-(n) element slection criteria - keywords representing the element 
**              characteristics which must be present for an element to be 
**              listed.  Valid values are REFERENCE (CMS reference copy 
**              attribute is set), NOREFERENCE (reference copy attribute is 
**              not set), NOTES (a notes string is defined), and NONOTES. 
** 
**              All specified attributes must be set for an element to 
**              be displayed.  If no attributes are specified, all elements 
**              matching the element expression will be displayed. 
** 
**              The selection attributes may not be abbreviated.  An attribute 
**              and its negated form (e.g., NOTES and NONOTES) may not be 
**              specified together. 
** 
**  IMPLICIT INPUTS: 
** 
**      Logical name CMS$LIB translates to the location of the CMS library. 
** 
** 
**      The include file CMS$ROUTINES.H, which defines the CMS callable 
**      routine entry points and the CMS error message symbols, is created 
**      from the file SYS$SYSROOT:[SYSHLP.EXAMPLES.CMS]CMS$ROUTINES.SDL. 
**      The command to create the file is $SDL/LANG=CC CMS$ROUTINES.SDL. 
**      The SDL processor can be obtained from the OpenVMS Freeware CD. 
** 
** 
*/ 
#include <ctype.h> 
#include <descrip.h> 
#include <lib$routines.h> 
#include <ssdef.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include "cms$routines.h" 
 
#define LDB_SIZE        50 
 
/* element selection attributes */ 
struct element_select { 
  unsigned REF     : 1; 
  unsigned NOREF   : 1; 
  unsigned NOTES   : 1; 
  unsigned NONOTES : 1; 
  unsigned fill    : 28; 
}; 
typedef struct element_select ELEMENT_SELECT; 
#define ELEMENT_SELECT_INIT {0,0,0,0,0} 
 
typedef struct dsc$descriptor_s DESCRIPTOR; 
 
/* 
**  strCreateFromStringID 
** 
**  Extract a character string from a CMS string identifier. 
** 
*/ 
 
char* strCreateFromStringID( DESCRIPTOR* desc ) 
{ 
  char* string;    /* string copied from desc */ 
 
  string = malloc( desc->dsc$w_length + 1 ); 
  if (string == NULL) { 
    printf("Fatal storage allocation failure.\n"); 
  } 
  else { 
    strncpy( string, desc->dsc$a_pointer, desc->dsc$w_length ); 
    string[desc->dsc$w_length] = '\0'; 
  } 
 
  return string; 
} 
 
/* 
**  Output Routine 
** 
**  This routine is called by CMS$SHOW_ELEMENT once for each requested 
**  element in the CMS library.  The information about the element is 
**  passed to this routine in the argument list. 
** 
**  The user selection options are passed via the user_param parameter.  All 
**  attributes must be present for an element to be listed. 
** 
**  Details of the parameter passing mechanism may be found in the "DIGITAL 
**  Code Management System Callable Routines Reference Manual". 
** 
*/ 
 
static int output_routine( int* first_call, 
      int* library_data_block, 
      ELEMENT_SELECT* user_param, 
      DESCRIPTOR** element_id, 
      DESCRIPTOR** remark_id, 
      DESCRIPTOR** history_string_id, 
      DESCRIPTOR** notes_string_id, 
      int* position, 
      int* concurrent, 
      int* reference_copy, 
      DESCRIPTOR* group_list_id, 
      int* review ) 
{ 
  int   notes_len;   /* length of notes string */ 
  char  reference_string[18];           /* string to output for reference 
        state */ 
  char* element_name;                   /* element name string */ 
  char* notes;                          /* notes string */ 
  char* remark;                         /* remark string */ 
 
  /* 
   * Check the attributes of this element which correspond to the 
   * selection options.  Logically, it's simpler to check whether 
   * the element should not be displayed. 
   */ 
  notes_len = (**notes_string_id).dsc$w_length; 
 
  if (! (((*user_param).REF && (*reference_copy == 0)) || 
  ((*user_param).NOREF && (*reference_copy == 1)) || 
  ((*user_param).NOTES && (notes_len == 0)) || 
  ((*user_param).NONOTES && (notes_len != 0)))) 
    { 
      /* There are no conflicting criteria, so display the element */ 
      if (*reference_copy == 1) 
 strcpy( reference_string, "/REFERENCE_COPY" ); 
      else 
 strcpy( reference_string, "/NOREFERENCE_COPY" ); 
 
      /* Extract character strings from CMS string identifiers */ 
      element_name = strCreateFromStringID( *element_id ); 
      notes = strCreateFromStringID( *notes_string_id ); 
      remark = strCreateFromStringID( *remark_id ); 
 
      /* 
       * Generate the output string.  The format is: 
       * 
       *  element-name  reference_string  notes-string  remark 
       */ 
      printf( "%s  %s  \"%s\"  \"%s\"\n", 
       element_name, 
       reference_string, 
       notes, 
       remark ); 
 
      /* Free the memory allocated for character strings */ 
      free( element_name ); 
      free( notes ); 
      free( remark ); 
    } 
 
  return( CMS$_NORMAL );       /* Successful completion */ 
} 
 
 
/* 
**  MAIN() - main program entry point. 
** 
*/ 
int main( int argc,   /* arg count from command line */ 
   char* argv[] )  /* arg pointers */ 
{ 
 
 int   library_data_block[LDB_SIZE]; /* LDB structure */ 
 int   status;        /* completion status from CMS routines */ 
 ELEMENT_SELECT options = ELEMENT_SELECT_INIT; 
                                           /* element selection characteristics */ 
 int   arg_index; 
 
 $DESCRIPTOR( element_desc, "*.*" ); /* default element name for SHOW */ 
 $DESCRIPTOR( library_desc, "CMS$LIB" ); /* CMS library name */ 
 
 
 /* Check for arguments specified on the command line. */ 
 switch (argc) { 
 case 1:    /* no command line args */ 
   /* Nothing to be done in this case.  The default element expression is set 
      in the string descriptor initialization. */ 
   break; 
 
 default:    /* command line args are present */ 
   /* get the specified element expression */ 
   element_desc.dsc$a_pointer = argv[1]; 
   element_desc.dsc$w_length = strlen(argv[1]); 
 
   /* 
    * Any remaining command line arguments are expected to be element selection 
    * criteria.  Scan the remaining args and record the criteria present. 
    * 
    * The character strings presented to the program in argv[] have been 
    * converted to lowercase unless they were quoted on the command line. 
    * Because it is unlikely a user would quote these strings we check 
    * only for the lowercase form of the strings. 
    * 
    * N.B.  strcmp() returns 0 if strings match. 
    */ 
   for (arg_index = 2; arg_index < argc; ++arg_index) { 
     if (! strcmp( argv[arg_index], "reference" )) 
       options.REF = TRUE; 
     else if (! strcmp( argv[arg_index], "noreference" )) 
       options.NOREF = TRUE; 
     else if (! strcmp( argv[arg_index], "notes" )) 
       options.NOTES = TRUE; 
     else if (! strcmp( argv[arg_index], "nonotes" )) 
       options.NONOTES = TRUE; 
     else 
       printf("Invalid option \'%s\' ignored.\n", argv[arg_index]); 
   } 
 } 
 
 /* Check for conflicting options */ 
 if ((options.REF && options.NOREF) || (options.NOTES && options.NONOTES)) { 
   printf("Conflicting options!\n"); 
   return SS$_NORMAL; 
 } 
 
 /* 
  * Command line processing is complete. 
  * 
  * The LDB must be initialized before using the CMS callable routines. 
  * This is done by calling CMS$SET_LIBRARY.  The location of the CMS 
  * library is assumed to be pointed to by the logical name CMS$LIB. 
  * This logical name is defined when the CMS SET LIBRARY command is 
  * issued. 
  * 
  * It is not necessary to report any error status from the CMS callable 
  * routines as these routine cause the appropriate error messages to be 
  * printed before returning here. 
  * 
  */ 
 status = cms$set_library( &library_data_block, &library_desc ); 
 
 if (! (status & SS$_NORMAL)) { 
     switch( status ) 
       { 
       case CMS$_NOREF:                   /* library access error */ 
  printf("Unable to access CMS library\n"); 
  return SS$_NORMAL; 
 
       default:                           /* unexpected error */ 
  printf("Unexpected error returned from CMS$SET_LIBRARY\n"); 
  return SS$_NORMAL; 
       } 
 } 
 
 /* Get the reservation information for the library */ 
 status = cms$show_element( &library_data_block, 
       output_routine, 
       &options, 
       &element_desc, 
       0,0 ); 
 
 if (! (status & SS$_NORMAL)) { 
   printf("Unexpected error returned from CMS$SHOW_RESERVATIONS\n"); 
   return SS$_NORMAL; 
 } 
 
 return SS$_NORMAL; 
} 
 


Previous Next Contents