Sunday, June 9, 2013

LoadRunner VuGen scripting - How to automatically download file from server and save it to local disk?

LoadRunner records file transferring from server and does not record file saving.

What to do, if you have to save transferred file to local disk?
Continue reading, and you will get the solution :)

You can download file from a server with the web_url function.
See an example:

Image downloading:
web_url("logo.gif",
"URL=http://www.google.com/intl/en_ALL/images/logo.gif",
"Resource=1",
"RecContentType=image/gif",
"Snapshot=t1.inf",
LAST);

This code downloads Google's logo image:

To save this image as file to local disk, we have to perform these steps:
Capture image from server's response
Save captured data to local disk

How to capture image from server's response?

Use web_reg_save_param function with the following boundaries - "LB=\r\n\r\n", "RB=". These boundaries allows to capture the whole data from a body of server's response. Function will look like:
web_reg_save_param("prmLogoImage", "LB=\r\n\r\n", "RB=", LAST);

This function should be placed before web_url function. After execution, prmLogoImage parameter will contain GIF-file.

I will clarify briefly the meaning of boundaries - "LB=\r\n\r\n" and "RB=".
Please, read the basic concepts of HTTP protocol, read Request message section:

HTTP response consists of the following:
Headers, such as HTTP/1.1 200 OK or Content-Length: 3473
An empty line
A message body, containg text of requested page or file

So, Header and Message body should be separated by empty line.
First CRLF (that is, a carriage return (CR = "\r") followed by a line feed (LF = "\n")) ends last header, and second CRLF ( = "\r\n") creates empty line. All data, followed by second CRLF, are treated as message body.
To summarize - "LB=\r\n\r\n" says "start capturing from the beginning of message body", empty right boundary "RB=" says "capture data till the end of message".

Open LoadRunner and enable logging of data, returned by server:


Then execute script containing initial web_url function, and open Replay log:


As you see, Replay log contains "\r\n\r\n" at the end of server's response.
Also, pay attention, that server returns the length of file to be downloaded (Content-Length: 8558).

Save captured data to local disk
Saving captured binary data (in our case, GIF file) requires additional step - we have to determine the length (= size) of captured data.

Tips: The simplest way - strlen function - is not correct. Imagine, that that captured data contains embedded NULL characters ('\0'):
"123\0qwe"
The real size of captured data = 7 bytes ('1', '2', '3', '\0', 'q', 'w', 'e').
But strlen function will return value 3, because it counts bytes before the first NULL character ('\0').

To calculate size of captured data use lr_eval_string_ext function:
lr_eval_string_ext ("{prmLogoImage}", strlen("{prmLogoImage}") /* = 14*/, &szBuf, &nLength, 0, 0,-1);

lr_eval_string_ext function copies captured data into szBuf array and places a size of captured data into nLength variable. That's easy, I hope :) If not, Help will help :)

Tips: There is another way to get known the size of file to be downloaded. Remember, that server returned the length of file (Content-Length: 8558). So, you can extract this value using Correlation.

And the last action is to save binary data from szBuf array into a local file. I used standard fwrite function from C programming language:
fwrite(szBuf, len, 1, hFile);

Well, please see the whole source code:

Click the block to expand the source code:
int WriteDataToFile(char *szFileName, const char *szBuf, int len)
{
int hFile;

hFile = fopen(szFileName,"wb");
.....

Execute the source code, and you will see, that new file will be created and saved automatically - "C:\LogoImage.gif". And this is what we needed - Google's logo image.

How to record a file saving, performed by user from browser page?

The problem:
This is a frequently asked question - why file downloading from a browser page (right mouse click, then "Save Target As...") was not recorded in LoadRunner VuGen script?

The difference between functional and load testing:Actually, LoadRunner records a file transferring only, not downloading!
This is the principal difference between functional and load testing! I will describe it.
Functional testing is done from a user's viewpoint.

What does a user see? It sees windows, dialogs, UI cotrols.
For example, user can see downloaded html-page in a browser, or as plain text in a telnet session.
In this case, data transferring is the same (HTTP protocol), while data representation varies (browser or telnet session).
LoadRunner performs Load testing, i.e. it records and emulates data transferring between client and server. Data transferring only, not data displaying for user!
For the above example, html-page can be downloaded directly from web-server. Another variant - page can be downloaded from FTP-server (even using Secured FTP protocol - FTPS), and then data will be passed to browser. User will see the same page.
In this case, data representation is the same (browser page), while data transferring varies (HTTP or FTPS protocols).

So, remember the simple rule:

LoadRunner does not record client side activities!

Tips: That's why LoadRunner does not show browser windows during load testing.
Note: Please, do not tell me, that VuGen shows Run-Time Viewer during replay :)
The run-time viewer was developed specifically for script debugging. There is no dependency between data representations in Run-Time Viewer and in a real browser (for detailed info read Mercury Support Knowledge Base (http://kb-web.mercury.com, requires login), topic 14094 "What are the limitations of the Run-Time Viewer").