Performance Testing @ the Frontline

A hidden world where small things make a big difference

Search & Replace function for LoadRunner

Posted by Kim on Friday, March 13, 2009

Sometimes it is necessary to process parameters in LoadRunner after they have been “captured” using web_reg_save() or similar methods. There is no built-in function to do this, and I’ve seen multiple horrific attempts at different kinds of Search & Replace methods over the years.

In light of this I decided to post the source for my working solution that does not eat memory, is fast and is LoadRunner parameter friendly. It can be used by anyone who has worked with LoadRunner before!
Examples:


// Store a string into "MyPar" parameter
lr_save_string("This is a string", "MyPar");

// For examples sake, convert it to URL encoded format
web_convert_param( "MyPar",
                   "SourceEncoding=PLAIN",
                   "TargetEncoding=URL", LAST); 

// Output the current result
lr_output_message("%s", lr_eval_string("{MyPar}"));

// Replace the ? characters with %20
lr_replace("MyPar", "+", "%20" );

// Output new result
lr_output_message("%s", lr_eval_string("{MyPar}"));

The following source can be copied into the VUSER_INIT action, at the end or stored as a separate file to be included in the script (your choice!)

// ----------------------------------------------------------------------------
//
// Description:
//    Search for and replace text within a string.
//
// Parameters:
//    src (in) - pointer to source string
//    from (in) - pointer to search text
//    to (in) - pointer to replacement text
//
// Returns:
//    Returns a pointer to dynamically-allocated memory containing string
//    with occurences of the text pointed to by 'from' replaced by with
//    the text pointed to by 'to'.
//
// Notes:
//    Do not use this directly in scripts unless you are a more advanced
//    user who knows C and string handling. See below for the function you
//    should use!
//
// ----------------------------------------------------------------------------
char *strReplace(const char *src, const char *from, const char *to)
{
  char *value;
  char *dst;
  char *match;
  int size;
  int fromlen;
  int tolen;

  // Find out the lengths of the source string, text to replace, and
  // the replacement text.
  size = strlen(src) + 1;
  fromlen = strlen(from);
  tolen = strlen(to);

  // Allocate the first chunk with enough for the original string.
  value = (char *)malloc(size);

  // We need to return 'value', so let's make a copy to mess around with.
  dst = value;

  // Before we begin, let's see if malloc was successful.
  if ( value != NULL )
  {
    // Loop until no matches are found.
    for ( ;; )
    {
      // Try to find the search text.
      match = (char *) strstr(src, from);
      if ( match != NULL )
      {
        // Found search text at location 'match'.
        // Find out how many characters to copy up to the 'match'.
        size_t count = match - src;

        // We are going to realloc, and for that we will need a
        // temporary pointer for safe usage.
        char *temp;

        // Calculate the total size the string will be after the
        // replacement is performed.
        size += tolen - fromlen;

        // Attempt to realloc memory for the new size.
        //
        // temp = realloc(value, size);
        temp = (char *)realloc(value, size);

        if ( temp == NULL )
        {
          // Attempt to realloc failed. Free the previously malloc'd
          // memory and return with our tail between our legs.
          free(value);
          return NULL;
        }

        // The call to realloc was successful. But we'll want to
        // return 'value' eventually, so let's point it to the memory
        // that we are now working with. And let's not forget to point
        // to the right location in the destination as well.
        dst = temp + (dst - value);
        value = temp;

        // Copy from the source to the point where we matched. Then
        // move the source pointer ahead by the amount we copied. And
        // move the destination pointer ahead by the same amount.
        memmove(dst, src, count);
        src += count;
        dst += count;

        // Now copy in the replacement text 'to' at the position of
        // the match. Adjust the source pointer by the text we replaced.
        // Adjust the destination pointer by the amount of replacement
        // text.
        memmove(dst, to, tolen);
        src += fromlen;
        dst += tolen;
      }
      else // No match found.
      {
        // Copy any remaining part of the string. This includes the null
        // termination character.
        strcpy(dst, src);
        break;
      }
    } // For Loop()
  }
  return value;
}

// ----------------------------------------------------------------------------
//
// Description:
//    Find and replace text within a LoadRunner string.
//
// Parameters:
//    lrparam (in)    - pointer to LoadRunner Parameter Name
//    findstr (in)    - pointer to text top search for
//    replacestr (in) - pointer to text to use as replacement
//
// Returns:
//    Returns an integer. 0=Error, 1=Success.
//
// Example:
//    lr_save_string( "This is a small test of the search and replace function", "LRParam");
//    lr_replace( "LRParam", "a", "-x-" );
//    lr_output_message( "%s", lr_eval_string("{LRParam}") );
//
// ----------------------------------------------------------------------------
int lr_replace( const char *lrparam, char *findstr, char *replacestr )
{
  int res = 0;
  char *result_str;
  char lrp[1024];

  // Finalize the LR Param Name
  sprintf( lrp, "{%s}", lrparam);

  // Do the Search and Replace
  result_str = strReplace( lr_eval_string(lrp), findstr, replacestr );

  // Process results
  if (result_str != NULL )
  {
    lr_save_string( result_str, lrparam );
    free( result_str );
    res = 1;
  }
  return res;
} // EOF
About these ads

33 Responses to “Search & Replace function for LoadRunner”

  1. Lior said

    10x works like a charm …

  2. Cristian said

    Thank you.

    I was looking for exactly this.

    PS: a smaaaaaalllll world…

  3. Poornima said

    Hi……

    replace(const char *string, char *pattern, char *replace, char *match)
    {

    int length;
    int status;
    int eflag;
    char buf[1024] = “”;
    char out[1024] = “”;

    regex_t re;
    regmatch_t pmatch[128];
    lr_load_dll(“pcre3.dll”);

    if((status = regcomp(&re, pattern, REG_EXTENDED)) != 0){
    regerror(status, &re, buf, 120);
    lr_output_message(“Match PCRE Exit 2″);
    return 2;
    }

    while(status = regexec( &re, string, 1, pmatch, eflag)== 0){
    strncat(out, string, pmatch[0].rm_so);
    strcat(out, replace);
    string += pmatch[0].rm_eo;
    eflag = REG_NOTBOL;
    }
    strcat(out, string);
    lr_save_string(out, match);
    }

    You can get commands regrading software testing in MACROTESTING

  4. Hari said

    Dear Fiends,
    I have to copy GQV352233 value and past it into some other search text box it should do automatically.

    name=\”h_srmid\”></d

    Help me out of this
    Thanks
    HK

  5. Ben said

    Hi everyone. I was wondering whether someone has a way to convert xml script in to Base64 encode and after that it again decode for result.

    Thanks in advanced.

    Matt

  6. Sharath said

    Hi,

    I am trying to use your code for string search and replace, but i am getting several compilation errors

    Action.c (43): illegal statement termination
    Action.c (43): skipping `char’
    Action.c (43): illegal expression
    Action.c (43): syntax error; found `char’ expecting `)’
    Action.c (43): type error: pointer expected
    Action.c (43): syntax error; found `char’ expecting `;’
    Action.c (43): illegal statement termination
    Action.c (43): skipping `char’
    Action.c (43): undeclared identifier `src’
    Action.c (43): type error: pointer expected
    Action.c (43): illegal expression
    Action.c (43): syntax error; found `char’ expecting `;’
    Action.c (43): illegal statement termination
    Action.c (43): skipping `char’
    Action.c (43): undeclared identifier `from’
    Action.c (43): type error: pointer expected
    Action.c (43): illegal expression
    Action.c (43): syntax error; found `char’ expecting `;’
    Action.c (43): illegal statement termination
    Action.c (43): skipping `char’
    Action.c (43): too many errors

    I am new to LoadRunner, would you please provide pre-requisite steps before copying this code to existing Loadrunner script, do i need to add any ‘include’ libraries to support this code, or need to declare any global variables.

    Please Advise!
    Sharath.

  7. Sharath said

    Please disregard the above comment, it’s working fine now

  8. Anonymous said

    I am getting the error that Sharath mentioned above. Can someone please let me know how to resolve that. Appreciate it.
    Thanks

    • Kim said

      Copy the source code into VuGen using the “View Source” option.
      1) Click “View Source” in the upper right corner when hovering mouse over the code
      2) In the popup window, Select All text and Copy it into the clipboard
      3) Paste into VuGen, at the end of the Vuser_Init() action.

      Note: To use the code in the Vuser_Init() action, you must paste the code BEFORE the vuser_init() { .. } function.

  9. Prasad said

    Hi,
    how to convert string “XYZ”,”MPQ”,” RSD”

    to string XYZ&PQ&RSD&

    I am unable to convert input string ” ,” to & .

    Please let me know the way

    • Kim said

      lr_save_string( “\”XYZ\”,\”MPQ\”,\”RSD\””, “lrvar” );

      lr_replace(“lrvar”, “\”,\””, “&” );

      lr_output_message(“Notify: %s”, lr_eval_string(“{lrvar}”) );

  10. Syed said

    Hi Kim,

    using
    lr_save_string(lr_eval_string(“{pRecVersBIN}”),”LRParam”);
    lr_replace( “LRParam”, “\\”, “\\\\” );
    lr_output_message( “%s”, lr_eval_string(“{LRParam}”) );
    I am getting
    Action.c(1045): Notify: Parameter Substitution: parameter “pRecVersBIN” = “\x8dŽ\x16\x07\x00″
    Action.c(1045): Notify: Saving Parameter “LRParam = \x8dŽ\x16\x07″.
    vuser_init.c(194): Notify: Parameter Substitution: parameter “LRParam” = “\x8dŽ\x16\x07″
    vuser_init.c(199): Notify: Saving Parameter “LRParam = \x8dŽ\x16\x07″.
    Action.c(1047): Notify: Parameter Substitution: parameter “LRParam” = “\x8dŽ\x16\x07″
    Action.c(1047): Ž
    Not changing “\” to “\\”.

    Can you please help?
    Thanks

    • Kim said

      You are trying to replace inside a BINARY string, 5 bytes in length. The data is $8D $8E $16 $07 $00 (numbers in HEX).

      The ‘\x8d’ means that the character decimal number 142 (or $8D in HEX) is in that place. The \x is just the way C shows that there is a binary character there (see http://en.wikipedia.org/wiki/Hexadecimal for details).

      You can not replace the \ in the string since it does not exist in the string. You can have a look at http://www.ascii-code.com/ for details on what the characters really are.

      Why would you want to replace the \ characters anyway? The output you seek with the replace statement shown would be ‘\\x8dŽ\\x16\\x07′ which still is gibberish and absolutely not at all in line with what the original data was. Also note that the last \x00 is completely removed as C terminates strings with a $00 (ASCII NULL) character, you lose the last character when you handle it as a string.

  11. Syed said

    Hi Kim,

    In the web_custom_request(“SubmitChanges”, I have this value that needs to be correlated and I capture this in binary but in the “Submit Changes” it comes with “\\” instead of “\” what I get from correlation,
    \rRecordVersion\\x8D\\xC0\\x15\\x07\\x00`\r”(This is in script). I don’t know how to handle this. Can you help pls?

    Thanks,

    Syed

    • Kim said

      From offline discussion I’m posting here the solution to the question:

      When LR captures data as binary with web_reg_save_param() it is shown in the log window as \x?? format, where the ?? are the ASCII table hex number of a character. Example: \x30 (Dec 48) is the same as character zero. See here for more info on ASCII character numbers: http://www.ascii-code.com/.

      There is a a special case for NULL or ASCII Character 0. This can be represented with a double \\ in a string. Example:

      web_reg_save_param(“pRecVersBIN”,
      “LB/IC=\rRecordVersion”,
      “RB/BIN=\\x00″, // Note the DOUBLE \\ to represent ASCII Character 0 (also known as NULL character)
      LAST);

      In addition the double \\ notation can be used in custom POST requests when the body parameter is BodyBinary. Example:

      web_custom_request(“x”,
      “URL=http://127.0.0.1/bin/post.php”,
      “Method=POST”,
      “Mode=HTTP”,
      “Body=a=”,
      “BodyBinary=\\x40\\x40″, // We also mix several body types. Here we insert two @@
      “Body={pRecVersBIN}”, // that are concatenated together. Insert saved binary data.
      “BodyBinary=\\x40\\x40″, // to produce one big body. Here we insert two @@
      LAST );

      This will produce the following POST data, given that the pRecVersBIN param contains the following binary data: “\x8D\x8E\x16\x07″ (raw hex dump):

      00000000h: 40 40 8D 8E 16 07 40 40 ; @@Ž..@@

      So even if LR in all instances shows \\x?? or \x?? notation of the binary stuff, the actual data sent in the POST is still the raw bytes.

  12. Syed said

    Thanks Kim. Greatly appreciate your help.

    ~Syed

  13. Rob said

    I am using your solution as part of my load test and it works GREAT! I really appreciate you posting this on here, thank you!

  14. Mach said

    I was struggling for a couple of days getting past some character replacement until I saw this. I tried it and it was working in minutes. Many thanks for sharing this. Keep up the good work. Im now so relieved I can move on with the scripting.

  15. paramesh said

    Works like a charm .. Kim add a like button to your pages and I would keep clicking them.. ur base 64 encoding also was very useful…

  16. Anonymous said

    SUUUUUPPPPERRRRRRRR!!!!!!!!!

    Thanks a lot for this!

  17. Nag said

    Hi, I like to know the solution for below query.

    wrsp captured the session value in the format…d9add5a1\x2D0\x3A0..and it is in the script like d9add5a1-0:0
    Can you help me out how I can convert ASCII code into binary format. Thanks alot

    • Kim said

      You can search for and replace binary characters by using the \x prefix.

      Example: lr_replace(“MyString”, “\x20″, “\x32″);

      This will replace all SPACE characters with the 0 (zero) character in the MyString parameter.

  18. Anonymous said

    Works perfectly but it’s a bit slow. Thank you.

  19. Swagata said

    Hi!

    I am new to LR.
    I am facing a similar problem. A variable contains space which when converted to URL by web_convert_param, replaces spaces(” “) by “+” but in the actual url contains “%20″ in place of spaces. Hnece I want to replace “+” by “%20″ . When I copied the above program in Vuser_init below error comes on compiling:

    vuser_init.c (25): syntax error; found `{‘ expecting `;’
    vuser_init.c (25): skipping `{‘
    vuser_init.c (35): undeclared identifier `src’
    vuser_init.c (36): undeclared identifier `from’
    vuser_init.c (37): undeclared identifier `to’
    vuser_init.c (57): operands of = have illegal types `int’ and `pointer to char’
    vuser_init.c (111): illegal return type; found `pointer to char’ expected `int’
    vuser_init.c (143): operands of = have illegal types `pointer to char’ and `int’
    vuser_init.c (154): unrecognized declaration
    vuser_init.c (154): unrecognized declaration
    vuser_init.c (154): warning: empty declaration
    vuser_init.c (155): unrecognized declaration
    c:\\users\\eswabas\\appdata\\local\\temp\\noname8\\\\combined_noname8.c (5): 11 errors, not writing pre_cci.ci

    Can you please help me out with this?

  20. vineet said

    Works like breeze..really nice

  21. Hi there to all, for the reason that I am in fact
    eager of reading this web site’s post to be updated regularly.
    It contains good stuff.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
Follow

Get every new post delivered to your Inbox.

%d bloggers like this: