Back to Blog

Using C Macros in LoadRunner Vugen

Introduction to C Macros

C macros aren’t  discussed a lot by HP LoadRunner users, yet they are at the core of the C programming language used in VUGen. They can provide flexibility and power that reduces script development and maintenance times. A good example would be where a function cannot be used to encapsulate reusable code blocks because something in the code block must be known at compile time instead of at run time. In this case, there would be a global variable accessed within the code block, but the name of the variable must be different every place the code block is used in the script.

When using Macros, UPPERCASE is a convention only.  Everything in the macro must be on one line,  hence the “\” characters at the end of each line. This concatenates all of the source code to one line. “##” is used to concatenate a macro value, so if ICOUNT is a macro variable, the macro iCount##ICOUNT  becomes-> iCount1. To concatenate in a string, use just “#”.  Admittedly, this can be a bit confusing.

The macro (“{dRWB” #NUMBER”}”) becomes-> (“{dRWB” “2” “}”) and the compiler concatenates two consecutive strings, so it becomes -> (“{dRWB2”}).

Source Code

Typically a macro is put either in globals.h, or at the beginning of vuser_init.c

#define HANDLE_RWB(ICOUNT,NUMBER)\
if(iCount##ICOUNT==0) \
{\
  lr_save_string( lr_eval_string("{dRWB" #NUMBER"}"),"RWB" #NUMBER);\
  c=strlen(lr_eval_string("{dRWB" #NUMBER"}"));\
  (iCount##ICOUNT)++;\
  if(c<=15)\
  {\
    lr_error_message("Invalid RWB value has been captured");\
    lr_exit(LR_EXIT_MAIN_ITERATION_AND_CONTINUE, LR_FAIL);\
  }\
}

// because the macro uses a variable iCount1, it is declared “globally”

int iCount1;
int c;

vuser_init()
{

  lr_save_string("fsdfsdfsdfdfsdfsd", "dRWB2"); // code to create input data
  HANDLE_RWB(1,2);
  lr_message("size:%d",c);
  lr_message(lr_eval_string("{RWB2}"));
  return 0;
}

Output (if advanced->parameter substitution is enabled)

vuser_init.c(22): Notify: Saving Parameter "dRWB2 = fsdfsdfsdfdfsdfsd ".
vuser_init.c(23): Notify: Parameter Substitution: parameter "dRWB2" =  " fsdfsdfsdfdfsdfsd "
vuser_init.c(23): Notify: Saving Parameter "RWB2 = fsdfsdfsdfdfsdfsd ".
vuser_init.c(23): Notify: Parameter Substitution: parameter "dRWB2" =  " fsdfsdfsdfdfsdfsd "
size:17
vuser_init.c(25): Notify: Parameter Substitution: parameter "RWB2" =  " fsdfsdfsdfdfsdfsd "
Ending action vuser_init.

Note that on line numbers – the output displays all vuser_init.c(23), This is the way macros work. All of the expanded macro is a single execution line.

Macro Expansion

To see the detail of the macro expansion, after compiling, open the file pre_cci.c  in the script directory. In this case, the interesting contents are:

if(iCount1==0) {       lr_save_string( lr_eval_string("{dRWB" "2""}"),"RWB" "2");c=strlen(lr_eval_string("{dRWB" "2""}"));    (iCount1)++;    if(c<=150)    {lr_error_message("Invalid RWB value has been captured");        lr_exit(5, 1);    }};

This is one big line, where word wrap makes it difficult to read. After manually adding some appropriate new lines:

if(iCount1==0) {
  lr_save_string( lr_eval_string("{dRWB" "2""}"),"RWB" "2");
  c=strlen(lr_eval_string("{dRWB" "2""}"));
  (iCount1)++;
  if(c<=150)    {
    lr_error_message("Invalid RWB value has been captured");
    lr_exit(5, 1);
  }
}

Note how:

lr_exit(LR_EXIT_MAIN_ITERATION_AND_CONTINUE, LR_FAIL);\

becomes:

lr_exit(5, 1);

When you see blue text in a Vugen script, these are usually macro values that the preprocessor converts to integer values.

Now go out and have some fun with macros today.

Special Thanks to Ron Sercely for this guest blog entry.

Back to Blog