Tuesday, February 11, 2014

Creating a custom .DLL file in LoadRunner

Sometimes LoadRunner does not provide all the needed features that one needs when doing performance testing. One option is to write DLL’s to handle the needed stuff and writing your own custom DLL’s is really easy once you get the hang of it!

I needed to do a few HTTP calls “under the radar” from a script so using Delphi 2009 I wrote my own HTTPClient DLL that allows me to do a HTTP GET to a specific URL without adding to the statistics (Pages and Hits/Sec stats).

Creating DLL’s in Delphi is really simple. One of the things I had to keep in mind was that D2009 uses unicode internally so I had to take care to convert any internal strings to non-unicode before returning them to LR. I opted for using the Indy 10 component TIdHTTP as the base HTTP client, adding some Cookie handling and Compression support (gzip,deflate) and making sure the DLL was thread safe (as many client threads/process would be using it). I also soon realized I needed HTTP Proxy Support so in the end I added that too.

Finally had a DLL that exported the following methods:
http_Initialize( VUserID: Integer )
http_WebProxy( VUser: Integer; Host:PAnsiChar; Port: Integer )
http_WebGet( VUserID: Integer; URL: PAnsiChar; DestBuf: PAnsiChar; BufSize: Integer )
http_Finalize( VUserID: Integer )

The VUserID is the identifier for the connection since the DLL supports keep-alive. Calling Finalize() will destroy all cookies and disconnect the client from the server.

 Sample script:

vuser_init()
{
int ret, VUserID;
char buf[10240];

// Get VUserID
VUserID = atoi(lr_eval_string("{VUserID"));

// Load the DLL
lr_load_dll("HTTPClient.dll");

// Initialize the VUser object inside the DLL
http_Initialize( VUserID );

// Set the HTTP Proxy
http_WebProxy( VUserID, "127.0.0.1", 8080);

// Clear buffer, and get the URL's response
memset(buf,0,sizeof(buf));
ret = http_WebGet( VUserID, "http://www.google.com", buf, sizeof(buf) );

// Check for error
// Returns
// 0 != Insufficient Buffer (Returned value is needed size)
if (ret != 0) lr_error_message("Error: RetCode=%d", ret)
else lr_output_message("%s", buf);

// Finalize the VUser (free the VUser object inside the DLL)
http_Finalize( VUserID );

return 0;
}


An additional good thing with this is that the DLL can be loaded under ANY protocol, so now HTTP calls can be made in any script type!