The “is it done yet” loop

Occasionally you will find that you must write some code in VuGen to continuously check that the system has completed something, before you continue.

Two examples that I have found recently were:

  • A web application that generates reports. Click a button to generate a report. The report gets generated in the background on the report server. When the report is ready to be viewed, the web page will be updated with the report name appearing as a hyperlink. The virtual user should keep refreshing the page until the report is available, then they should view the report. Typically report generation takes 10 minutes.
  • A message-based system. An order message is placed on a queue, where it is picked up and processed by the system. Processing typically takes 30-90 seconds, and is complete when the status of the order is flagged as "complete" in the database. To determine the processing time for the order, the virtual user must repeadedly query the database using the order number. Once the order status is "complete", a transaction can be created with the correct duration (using lr_set_transaction).

If you have a basic understanding of your chosen VuGen user type, and know how to write the code for a loop, you might think that writing code to do this is easy.

// Code taken from HP whitepaper on LoadRunner by 
// Opral Wisham from Waste Management, Inc.

// This example was used in a script that required clicking
// the "refresh" button until the run status changed to
// "success". This code provides an automatic refresh
// until the batch job has been completed. The next step
// requires the completion of the batch job.

int x; // flag will be 0 or 9
char *temp, *temp2; // values to hold strings

  temp2="Success"; //compare string 2
  //lr_message("temp2 = %s", temp2);
  // set x to 0. x is the success flag

  do {

      "Name=ICType", "Value=Panel", ENDITEM,
      "Name=ICElementNum", "Value=0", ENDITEM,
      "Name=ICStateNum", "Value={ICStateNum6}", ENDITEM,
      "Name=ICAction", "Value=REFRESH_BTN", ENDITEM,
      "Name=ICXPos", "Value=0", ENDITEM,
      "Name=ICYPos", "Value=0", ENDITEM,
      "Name=ICFocus", "Value=", ENDITEM,
      "Name=ICChanged", "Value=-1", ENDITEM,
      "Name=ICFind", "Value=", ENDITEM,
      "Name=PMN_FILTER_PRCSTYPE", "Value=", ENDITEM,
      "Name=PMN_FILTER_PRCSNAME", "Value=", ENDITEM,
      "Name=PMN_DERIVED_PRCSINSTANCE", "Value={Process_Instance}", ENDITEM,
      "Name=PMN_DERIVED_TO_PRCSINSTANCE", "Value={Process_Instance}", ENDITEM,
      "Name=PMN_FILTER_RUNSTATUS", "Value=", ENDITEM, 

    // Compare correlation value with character string
    temp = lr_eval_string(lr_eval_string("{RunStatus}"));
    // correlation value to variable
    //lr_message("temp = %s", temp);
    //compare string 1
      // string compare success with correlation value
      x=9; // set flag to indicate success
  } while (x == 0); // do while flag not set

  return 0;

The example code above has two major problems:

  • the polling loop will run forever if it never finds the string "success" on the page it is checking
  • the VuGen script will refresh the page it is checking as fast as possible. This means that your virtual user is not behaving like a real user at all. This behaviour may create hundreds or thousands of additional requests on the system. Potentially it may keep an entire CPU core busy on the system being monitored or tested (and it will also put unnecessary load on your load generators).

So, whether your script is for performance testing with LoadRunner or for application monitoring with BAC, it is important that your polling loop has some think-time inside it so that it does not hit the server too hard, and that it will exit after a reasonable period of time if the event being polled for has not happened.

Here is a better implementation of a polling loop.

  int POLLING_TIMEOUT = 600; // 10 minutes
  long start_time;

  // Will keep refreshing the report page until it finds "Success" or reaches POLLING_TIMEOUT.
  do {



    web_submit_data("Display Report",
      "Name=report_id", "Value={ReportID}", ENDITEM,
      "Name=report_filter", "Value=", ENDITEM, 

	// Abort script if POLLING_TIMEOUT is exceeded.
    if ( (time(NULL) - start_time) > POLLING_TIMEOUT) {
		lr_error_message("Timed out while waiting for report to generate.");

  } while (atoi(lr_eval_string("{SuccessCount}")) == 0);

Tech tips from JDS