Tuesday, December 1, 2015

HTTP Response Messages(HTTP CODES)

400 Bad Request
Officially: The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications. 

When / Why: The request in the script may be badly formatted. The best thing to do is check if the request has any parameters that you have edited, of so check them by debugging.

HTTP 401 Unauthorised
Officially: The request requires user authentication. The response MUST include a WWW-Authenticate header field (section 14.47) containing a challenge applicable to the requested resource. The client MAY repeat the request with a suitable Authorization header field (section 14.8). If the request already included Authorization credentials, then the 401 response indicates that authorization has been refused for those credentials. If the 401 response contains the same challenge as the prior response, and the user agent has already attempted authentication at least once, then the user SHOULD be presented the entity that was given in the response, since that entity might include relevant diagnostic information. HTTP access authentication is explained in "HTTP Authentication: Basic and Digest Access Authentication"

When / Why: Typically when load testing many users are generated from the same machine. In a Microsoft example the browser can use the current Windows logon credentials as credentials for the web site using NTLM. Therefore if the login is different as does not have the same authorisation as the original login (from the recording phase) during the execution the server may deny access with 401.
In the script you should use:
SetAuthentication(UserNameVariable,PasswordVariable,DomainVariable);

HTTP 403 Forbidden
Officially: The server understood the request, but is refusing to fulfill it. Authorization will not help and the request SHOULD NOT be repeated. If the request method was not HEAD and the server wishes to make public why the request has not been fulfilled, it SHOULD describe the reason for the refusal in the entity. If the server does not wish to make this information available to the client, the status code 404 (Not Found) can be used instead.

When / Why: If you do not see the error when manually browsing but do see it when running a script check that the script is recent. If there has been aconfiguration change on the server you may see this message: For example if if at one time a server hosted the site and now no longer does so and can't or won't provide a redirection to the new location it may send a HTTP 403 back rather than a more meaningful message.
Check that authentication is correctly set up in the script - see HTTP 401.
Also check that the browser you are simulating is allowed as a security policy can ban certain types of traffic from a server.

HTTP 404 Not Found
When / Why: You may find that when interacted with manually the web site does not appear to throw any HTTP 404 messages.
When running a load test script you then may see 404's in the response codes. This can be because the object (probably a page component) that the tool requested does not exist on the server - it may be a .gif or a .js java script or similar that is referenced by the page yet does not exist on the server. In a browser this would simply appear as an empty image place holder in the case of an image for example, or in the case of a java script you may even see nothing if the java script is redundant. As the tool specifically requests the object (as the browser does) it will of course log the 404 message if the object cannot be found.

HTTP 407 Proxy Authentication Required
Officially: This code is similar to 401 (Unauthorized), but indicates that the client must first authenticate itself with the proxy. The proxy MUST return a Proxy-Authenticate header field (section 14.33) containing a challenge applicable to the proxy for the requested resource. The client MAY repeat the request with a suitable Proxy-Authorization header field (section 14.34). HTTP access authentication is explained in "HTTP Authentication: Basic and Digest Access Authentication"

When / Why: The script was probably captured with the browser already pointing to a proxy server set (see browser network settings). See the information on HTTP 401 for reasons why this might happen.
Typically it's best to avoid running a load test through a proxy server, especially if production load will not be routed through that proxy server. Ways to avoid the proxy server are to remove the part of the script that states use of the proxy server (often internal applications are available even while bypassing the proxy server), if that doesn't work - move the injection point to a location in the network where the proxy server can be bypassed (perhaps the same VLAN as the web server).

HTTP 500 Internal Server Error
Officially: The server encountered an unexpected condition which prevented it from fulfilling the request.

When / Why: You'll often see this after an HTTP POST statement and it usually means that the post statement has not been formed correctly.
There can be a number of reasons for this including the request being badly formed by the tool - or at least not formed as expected by the server. More typically it's because the POSTed form values are incorrect due to incorrect correlation / parameterisation of form variables.
For example: In a .Net application a very large __VIEWSTATE value is passed between the browser and server with each POST, this is a way to maintain state and puts the onus on state ownership on the browser rather than the server. This can have performance issues which I won't go into here. If this value is not parameterised correctly in the script (there can be more than one __VIEWSTATE) then the server can be confused (sent erroneous requests) and respond with a 500 Internal Server Error.
A 500 error usually originates from the application server part of the infrastructure.
It's not just .Net parameters that can cause this. Items such as badly formed dates, incorrectly formatted fields and badly formatted strings (consider replaced spaces with + characters) and so on can all cause HTTP 500 errors.

HTTP 503 Service Unavailable
Officially: The server is currently unable to handle the request due to a temporary overloading or maintenance of the server. The implication is that this is a temporary condition which will be alleviated after some delay. If known, the length of the delay MAY be indicated in a Retry-After header. If no Retry-After is given, the client SHOULD handle the response as it would for a 500 response. 

When / Why: Typically this will be due to the allowed number of concurrent connections on the server and is usually down to a configuration or license setting. For example IIS running on a non server version of Windows is limited to 10 concurrent connections - after this point it will deliver a 503 message. There is a temptation in load testing to overload the application under test, so it's worth revisiting your non functional requirements - will the production server ever see this number of concurrent connections?



HTTP Response Messages

HTTP servers respond to client requests in the form of a response message. This message contains a status line, response headers, and meta-information about the resource (information about the resource itself, not about the information that is contained in the resource).
Each HTTP status line contains the HTTP version number, a status code, and a description. For example, "HTTP/1.0 200 OK" is a typical status line returned in a response message from an HTTP server.
The following table contains status codes and their meanings.

HTTP Status Codes

Status Code
Meaning
200
OK
201
Created
202
Accepted
203
Non-Authoritative Information
204
No Content
205
Reset Content
206
Partial Content
251
Fin (i-mail capture)
252
Rec (i-mail capture)
255
Empty (i-mail capture)
300
Multiple Choices
301
Moved Permanently
302
Moved Temporarily
303
See Other
304
Not Modified
305
Use Proxy
307
Temporary Redirect
400
Bad Request
401
Unauthorized
402
Payment Required
403
Forbidden
404
Not Found
405
Method Not Allowed
406
Not Acceptable
407
Proxy Authentication Required
408
Request Timeout
409
Conflict
410
Gone
411
Length Required
412
Precondition Failed
413
Request Entity Too Large
414
Request URL Too Large
415
Unsupported Media Type
416
Requested Range Not Satisfiable
417
Expectation Failed
451
ID Error (i-mail capture)
500
Internal Server Error
501
Not Implemented
502
Bad Gateway
503
Service Unavailable
504
Gateway Timeout
505
HTTP Version Not Supported
552
POST Error (i-mail capture)
553
GET Error (i-mail capture)
554
Unordered (i-mail capture)
561
UE POST Error (i-mail capture)

How to do Manual Correlation and web_reg_save_param() in load runner

The correlation id to capture the dynamic values which are coming from a server to a parameter.

Dynamic session handling
Session ID: Session id is created by the server for security purpose.These session id's are dynamic. These values can be created by server.some of the usual dynamic values are view state,Event validation, Image Id, Dynsess,Object Id etc.
  • Process of capturing a value dynamically and replacing it in the script during replay
  • To capture the dynamic values in each run of the script execution is called correlation.
  • To parameterize the server generated values

Process of correlation:
There are two methods of correlations,They are 

1. Auto Correlation,
2. Manual Correlation

1. Auto Correlation: Automatically the L R itself handles the process to capture the dynamic value in each run of the script execution.

  1. Create the script by disabling the correlation in the recording options. 
  2. Run the script for multiple times to get the error messages like Sessions expired, Session timeout or missing object id etc.
  3. Click on find correlation it displays the required dynamic values in the co relation studio. 
  4. Select the value to be correlated and Click on correlate tab in the toolbar.
  5. The Correlation Function will be inserting in appropriate place of the script as shown in below
            
Manual Correlation:
  1. Create the 2 identical scripts and save those 2 scripts in windows temp directory. 
  2. Open any one of the script from the script go to Tools menu. 
  3. Select compare script for the comparisons, the difference between the two scripts will display in the Wdiff utility. 
  4. Identify the dynamic context charge between two scripts identically the Left & Right boundary of the dynamic values. 
  5. Search for the First occurrence of the dynamic values to replace by a given parameter name. 
  6. Select the position to insert the correlated function with all the parameters.
Try to run the script, the script should properly run without the script showing any error message for the dynamic handling. 

syntax:

Web_reg_save_param (const char “Param_Name”, "LB=","RB=","ORD=","Convert=HTML_TO_URL","Ignore Redirections=Yes","Notfound=warning","Savelength=",Saveoffset=", LAST); 
Attributes Description in the function:
LB: It is the left boundary of the dynamic value.   
RB: It is the gives the Right boundary of the dynamic value.
I will go to tree view then I will select server response from there I will select   the LB and RB as indicated.

Assign the name of the parameter which is related by the hard coded  dynamic values.
LB=Left boundary = Assigns the Left Boundary of the dynamic value.
RB = right boundary = Assigns the Right Boundary of the dynamic value.
Ord = ordinal value=Occurrence of the value.  It indicates the no of occurrences of the dynamic values.
Ex: if the occurrence is 1, ord = 1 or If the occurrence is 2 ord = 2 or If n no of occurrences then ord = all.
LAST = it come for each function at last time, it is end of the attributes. It indicates there is no any arguments which in the function.


Convert: The possible values are: 
HTML_TO_URL: convert HTML-encoded data to a URL-encoded data format

HTML_TO_TEXT: convert HTML-encoded data to plain text format this attribute is optional. 

Ignore Redirections: If "Ignore Redirections=Yes" is specified and the server response is redirection information (HTTP status code 300-303, 307), the response is not searched. Instead, after receiving a redirection response, the GET request is sent to the redirected location and the search is performed on the response from that location. 
This attribute is optional. The default is "Ignore Redirections=No".

LB: The left boundary of the parameter or the dynamic data. If you do not specify an LB value, it uses all of the characters from the beginning of the data as a boundary. Boundary parameters are case-sensitive. To further customize the search text, use one or more text flags. This attribute is required. See the Boundary Arguments section.

NOTFOUND: The handling option when a boundary is not found and an empty string is generated. 
"Not found=error", the default value, causes an error to be raised when a boundary is not found. 
"Not found=warning" ("Not found=empty" in earlier versions), does not issue an error. If the boundary is not found, it sets the parameter count to 0, and continues executing the script. The "warning" option is ideal if you want to see if the string was found, but you do not want the script to fail.
TIP: If Continue on Error is enabled for the script, then even when NOTFOUND is set to "error", the script continues when the boundary is not found, but an error message is written to the extended log file. This attribute is optional.

ORD: Indicates the ordinal position or instance of the match. The default instance is 1. If you specify "All," it saves the parameter values in an array. This attribute is optional.
TIP: The use of Instance instead of ORD is supported for backward compatibility, but deprecated.

RB: The right boundary of the parameter or the dynamic data. If you do not specify an RB value, it uses all of the characters until the end of the data as a boundary. Boundary parameters are case-sensitive. To further customize the search text, use one or more text flags. This attribute is required. See the Boundary Arguments section.

RelFrameID: The hierarchy level of the HTML page relative to the requested URL. The possible values are ALL or a number. Click RelFrameID Attribute for a detailed description. This attribute is optional.

TIP: RelFrameID is not supported in GUI level scripts.
SaveLen: The length of a sub-string of the found value, from the specified offset, to save to the parameter. This attribute is optional. The default is -1, indicating to save to the end of the string.

SaveOffset: The offset of a sub-string of the found value, to save to the parameter. The offset value must be non-negative. The default is 0. This attribute       is optional.
Search: The scope of the search-where to search for the delimited data. The possible values are Headers (Search only the headers), Body (search only body data, not headers), Noresource (search only the HTML body, excluding all headers and resources), or ALL (search body, headers, and resources). The default value is ALL. This attribute is optional.


  • Saving a single string in the request

//This Web_reg_save_param function call applies to the Web_submit_form function: . //
       
Web_reg_save_param (“FlightVal","LB=outbound Flight value=", "RB= checked >", LAST);

 Web_submit_form ("reservations.pl", "Snapshot=t4.inf", ITEMDATA,
              "Name=depart", "Value=Denver", ENDITEM,
              "Name=depart Date", "Value=10/25/2015", ENDITEM,
              "Name=arrive", "Value=London", ENDITEM,
              "Name=return Date", "Value=10/26/2015", ENDITEM,
              "Name=numPassengers", "Value=1", ENDITEM,
              "Name=roundtrip", "Value=<OFF>", ENDITEM,
              "Name=seatPref", "Value=None", ENDITEM,
              "Name=seatType", "Value=Coach", ENDITEM,
              "Name=findFlights.x", "Value=75", ENDITEM,
              "Name=findFlights.y", "Value=14", ENDITEM,
              LAST);
/*
The result of the web_reg_save_param having been called before the web_submit_form is: Action.c (14): Notify: Saving Parameter "FlightVal = 240; 355; 10/25/2015"
*/
// Now use the saved parameter value of FlightVal in to the below function

       web_submit_form ("reservations.pl_2",
              "Snapshot=t5.inf",
              ITEMDATA,
              "Name=outboundFlight", "Value= {FlightVal}", ENDITEM,
              "Name=reserveFlights.x", "Value=82", ENDITEM,
              "Name=reserveFlights.y", "Value=10", ENDITEM,
              LAST);
/*
Action.c (14): Notify: Parameter Substitution: parameter "outFlightVal" = "240; 355; 10/25/2016" */

Important points to remember:

  • Dynamic values will be encrypted sometimes, so we use manual correlation instead of automatic correlation.And it is the best way at all the times.
  • The correlation functions will be replaced Before submitting the form or data. Where we are giving input before that we are putting the function.there we the 
  • After scanning or running of the script, we will get some messages found like
1. No server found
2. No request found
3. Request link not found
4. Web link not found.

PACING Calculation in loadrunner

Pacing Calculation :

D = Duration of the test(test window/time frame)

B = Baseline time(total time taken by 1 Vu to complete 1 whole iteration)

T = Total amount of Think time in the script

I = Expected/Target iteration

R = Residual time of the test window.

R = ( D - (T + B)*I)

P = Pacing interval

Dividing the residual time by target iteration gives pacing interval

Hence:

P = R/I

D is pacing time.
(T + B)*I represents the duration of a scenario
and P is the waiting time before the next scenario

Calculating Pacing Time/Think Time to achieve 50 TPS with an average response time of 0.5 seconds with total of 100 Users
Let us start with calculating total number of transactions in an hour.
1 sec = 50 trnx
3600 sec = x
x = 3600 * 50 = 180000 trnx/hour by 100 Users

We have total number of users given as 100. Let us see how to calculate how many transactions each user will perform.
Total Number of Users = 100
Each User will perform 180000/100=1800 transactions/hour

Since, every transaction is taking on an average 0.5 seconds, let us see how much time is required to complete the each user transactions.
To complete 1800 trnx it will take 1800*0.5 = 15 minutes

So now, let us see how much think-time is required to complete the required number transactions per User in an hour.
1800 transactions will complete in 15 minutes
hence, 45 minutes of thinktime is required in between 1800 transactions (i.e. 45*60 = 2700 seconds of thinktime required in between 1800 transactions (per user))
2700 seconds = 1800 trnx
x = 1 trnx
x = 1.5 seconds think time need to include

Let us see how much time is required to complete each iteration.
Total time required to complete each Iteration = x + 0.5 seconds
= 1.5 + 0.5
= 2 seconds

Verification: Let us verify if our above calculation is correct.
Total time = 1800 * 2
= 3600 seconds
= 1 Hr

So, Each User will perform 1800 transactions where we will provide 2 seconds for each Iteration to complete.

Random Virtual User Pacing in LoadRunner:
I guess there's always a first time. I had never used LoadRunner's random virtual user (VU) pacing earlier, but am working on a project that will need to use this feature for the first time. And as I thought about it a little more, I may start using it more frequently now. Here's how it happened

This is one of the rare projects that provided me with excellent documentation - not only system documentation like the system specs, API Guides etc but also performance requirements like actual production volume reports and capacity models that estimated the projected volumes.

The capacity models estimated the maximum transaction load by hour as well as by minute (max TPM). What I needed to do was take maximum hourly load, divide it by 60 to get a per minute transactional load and use this as the average TPM. The idea was to vary the VU pacing so that over the whole duration of test, average load stays at this Average TPM but it also reaches the Max TPM randomly.

For example, if the maximum hourly transaction rate is 720 requests and maximum TPM is 20, the average TPM will be 720/60 = 12 and I will need to vary the pacing so that the load varies between 4TPM and 20TPM and averages to around 12TPM.
The Calculation:
To vary the transactional load, I knew I had to vary the VU Pacing randomly. Taking above example, I had to achieve 12TPM and I knew the transactions were taking around 1-2 seconds to complete. So I could have the pacing of around 120 seconds if I needed to generate a fixed load of 12TPM with a 5 second Ramp-up and 24 users.

ScriptTPMNumber of VUsPacing (sec)Ramp Up
Script 112241201 VU/5sec

So now to vary the TPM to x with the same 24 virtual users, I will need to have a pacing of 24*60/x. I got this from an old-fashioned logic which goes in my head this way:
24 users with a pacing of 60 seconds generate a TPM of 24
24 users with a pacing of 120 seconds generate a TPM of 24 * 60/120
24 users with a pacing of x seconds generate a TPM of 24 * 60/x

So using above formula, to vary the load from 20 to 4TPM I will need to vary the VU pacing from 72 to 360. So now we have:
ScriptTPMNumber of VUsPacing (sec)Ramp Up
Script 14 to 2024Random (72 to 360)1 VU/5sec

 

Of course, there's a caveat. The range of 72 to 360 seconds has an arithmetic mean of 216. 120 is actually the harmonic mean of the 2 numbers. So the actual variation in TPM will depend on the distribution of random numbers that LoadRunner generates within the given range. If it generates the numbers with a uniform distribution around the arithmetic mean of the range, then we have a problem.

I ran a quick test to find this out. I created an LR script and used the rand() function to generate 1000 numbers between the range with the assumption that LR uses a similar function to generate the random pacing values.

int i;
srand(time(NULL));
for (i=0;i<1000 br="" i="">lr_output_message("%d\n", rand() % 289 + 72);
}

And of course, the average came out close to the arithmetic mean of 72 and 360, which is 216.

So with the assumption that the function used by LoadRunner for generating random pacing values generates numbers that are uniformly distributed around the arithmetic mean of the range, we'll need to modify the range of pacing values so that the arithmetic mean of the range gives us the arithmetic mean of the TPM that we want...phew. What it means is that the above pacing values need to be modified from 72 to 360 (arithmetic mean = 216) to 72 to 168 (arithmetic mean = 120). However, this gives us the TPM range of 20 to 8.6 TPM with a harmonic mean of 12TPM.

But I'll live with it. I would rather have the average load stay around 12TPM. So here are the new values. Note the asterisk on TPM. I need to mention in the test plan that the actual TPM will vary from 8.6 to 20TPM with an average of 12TPM.

ScriptTPM*Number of VUsPacing (sec)Ramp Up
Script 14 to 2024Random (72 to 168)1 VU/5sec

Functions used in loadrunner tool

Functions:-
1,
In the following example, lr_error_message sends a message to the LoadRunner output window or Application Management agent log file if the login fails. lr_abort is then invoked to abort the script.
2.
The following example uses abs to convert the integers 23 and -11 to their absolute values:
       int m = 23, n = -11;
       lr_output_message ("absolute value of %d = %d", m, abs(m));
       lr_output_message ("absolute value of %d = %d", n, abs(n));
3
In the following example, the web_add_cookie function adds a cookie with the name "client_id" to the list of cookies available to the script.
web_add_cookie ("client_id=China127B; path=/; expires=Wednesday, 09–Nov–2001 23:12:40 GMT; domain=www.cnn.com");
4
 The following example gets the time as a time_t structure and converts it to a tm structure, gmt, in Coordinated Universal Time.asctime then takes gmt and converts it to a string.
5
The following example converts the initial portion of the string, s, to a float.
double atof (const char *string); /* Explicit declaration */

vuser_init() {

     float x;
     char *s = "7.2339 by these hilts or I am a villain else";

     x = atof(s);     /* The %.2f formatting string limits the output to 2 decimal places */
     lr_output_message("%.2f", x);

     return 0;
}
Output:
vuser_init.c(11): 7.23
6
The following example converts the initial portion of the string, s, to an integer.
       int i;
       char * s = "7 dollars";
       i = atoi(s);
       lr_output_message ("Price $%d", i);
Output:
vuser_init.c(7): Price $7
7
Function Name
Description
abs
Gets the absolute value of an integer.
asctime
Converts time from a structure to a string.
atof
Converts a string to a floating point value.
atoi
Converts a string to an integer value.
atol
Converts a string to a long integer value.
calloc
Allocates an array and initializes all elements to zero.
chdir
Changes the current directory to the given path.
chdrive
Switches to another drive.
cos
Computes the cosine of an angle in radians.
ctime
Converts the calendar time to local time.
fclose
Closes a file.
feof
Checks if the end of file has occurred on a stream.
ferror
Checks if any error has occurred during file I/0.
fgetc
Gets a character from a stream.
fgets
Reads a string from a file.
floor
Gets the largest integral value that is less than x.
fopen
Opens a file for buffered I/0.
fprintf
Writes formatted output to a file.
fputc
Writes a character to a stream.
fread
Reads unformatted data from a stream into a buffer.
free
Frees a block of memory.
fscanf
Reads formatted input from a stream.
fseek
Sets the current position in a file to a new location.
ftime
Prints time information to a structure.
fwrite
Write unformatted data from a buffer to a stream.
getcwd
Returns the name of the current working directory.
getdrive
Returns the name of the current drive.
getenv
Gets the definition of an environment variable.
gmtime
Converts the calendar time into Coordinated Universal Time (UTC).
isalpha
Checks if a string is a letter.
isdigit
Checks if a string is a decimal digit.
Converts an integer to a string. Windows only.
localtime
Converts the calendar time into local time.
malloc
Allocates a block of memory.
memchr
Searches for a character in a buffer.
memcmp
Compares two buffers.
memcpy
Copies n characters from one buffer into another.
memmove
Moves a number of bytes from one buffer to another.
memset
Sets n bytes of a buffer to a given character.
mkdir
Creates a directory using the given path name.
putenv
Inserts a new definition into an environment table.
rand
Gets a random integer between 0 and RAND_MAX.
realloc
Reallocates (adjusts the size of) a block of memory.
remove
Deletes the specified file.
rewind
Rewinds a file.
rmdir
Deletes the specified directory.
sin
Computes the sine of an angle in radians.
sprintf
Writes formatted output to a string.
sqrt
Computes the square root of x.
sscanf
Reads formatted input from a string.
strcat
Concatenates two strings.
strchr
Returns the pointer to the first occurrence of a character in a string.
strcmp
Compares two strings to determine the alphabetic order.
strcpy
Copies one string to another.
strdup
Duplicates a string.
stricmp
Performs a case-insensitive comparison of two strings.
strlen
Returns the length of a string.
strlwr
Converts a string to lower case.
strncat
Concatenates n characters from one string to another.
strncmp
Compares the first n characters of two strings.
strncpy
Copies the first n characters of one string to another.
strnicmp
Performs a case-insensitive comparison of n strings.
strrchr
Finds the last occurrence of a character in a string.
strset
Fills a string with a specific character.
strspn
Returns the length of the leading characters in a string that are contained in a specified string.
strstr
Returns the first occurrence of one string in another.
strtok
Returns a token from a string delimited by specified characters.
strtol
Converts a string to a long integer using a given radix.
strupr
Converts a string to upper case.
system
Executes an operating system command.
time
Returns the current calendar time.
tolower
Converts a string to lowercase.
toupper
Converts a string to uppercase.
8.
In the following example, lr_error_message sends a message to the LoadRunner output window or Application Management agent log file if login fails:
int status = web_url("Login",
          "URL=https://secure.computing.com//login.asp?user={username}&session={ssid}",
          "RecContentType=text/html", LAST);

if (status == LR_FAIL) {

     lr_error_message("Error: %s", "Unable to login to secure computing");
     return -1;
}
9
The lr_eval_string function returns the input string after evaluating any embedded parameters. If string argument contains only a parameter, the function returns the current value of the parameter.
10.
In the following example, lr.eval_int returns the value of parameter ID_num.
// Create the parameter
lr.save_int(12,"ID_num");
// Output the parameter value
lr.message(" Track Stock : " + lr.eval_int("<ID_num>") );
Example 2 - Parameterization
In the following example, lr.eval_int substitutes the parameter string STID with appropriate values for each iteration.
lr.message( "Stock Trader ID Number is " + lr.eval_int("<STID>") );
11.
C Constants
Object Oriented Constants
Behavior
LR_EXIT_VUSER
lr.EXIT_VUSER
Exit without any condition, and go directly to end action
LR_EXIT_ACTION_
AND_CONTINUE
lr.EXIT_ACTION_
AND_CONTINUE
Stop current action, and go to the next action.
LR_EXIT_MAIN_
ITERATION_
AND_CONTINUE
lr.EXIT_MAIN_
ITERATION_
AND_CONTINUE
Stop current global script run iteration, and go to the next iteration.
LR_EXIT_ITERATION_
AND_CONTINUE
lr.EXIT_ITERATION_
AND_CONTINUE
Stop current iteration, and go to the next iteration.
If called from within a block iteration, only the block iteration will be exited, and not the global iteration.
LR_EXIT_VUSER_
AFTER_ITERATION
lr.EXIT_VUSER_
AFTER_ITERATION
Run until the end of the current iteration and then exit.
LR_EXIT_VUSER_
AFTER_ACTION
lr.EXIT_VUSER_
AFTER_ACTION
Run until the end of the current action and then exit.
12.
13

Example: feof

The following example, for Windows platforms, opens a file and reads it into a buffer until feof returns true, indicating the end of the file.
To run the example, copy the file readme.txt from the installation's dat directory to the c drive, or copy another file and change the value of filename.
14.
The following example, for Windows platforms, opens a file and reads it into a buffer. ferror checks for errors on the read file stream.
15
The following example, for Windows platforms, opens a file using fopen, reads it into a buffer, and then closes it.
To run the example, copy the file readme.txt from the installation's dat directory to the c drive, or copy another file and change the value of filename.
       int count, total = 0;
       char buffer[1000];
       long file_stream;
       char * filename = "c:\\readme.txt";
       // Open the file with read access
       if ((file_stream = fopen(filename, "r")) == NULL) {
              lr_error_message ("Cannot open %s", filename);
              return -1;
       }
       // Read until end of file
       while (!feof(file_stream)) {
              // Read 1000 bytes while maintaining a running count
              count = fread(buffer, sizeof(char), 1000, file_stream);
              lr_output_message ("%3d read", count);
              // Check for file I/O errors
              if (ferror(file_stream)) {
                     lr_output_message ("Error reading file %s", filename);
              break;
              }
              total += count; // Add up actual bytes read
       }
       // Display final total
       lr_output_message ("Total number of bytes read = %d", total );
       // Close the file stream
       if (fclose(file_stream))
              lr_error_message ("Error closing file %s", filename);
Output:
Action.c(19): 1000 bytes read
Action.c(19): 1000 bytes read
...
Action.c(19): 1000 bytes read
Action.c(20): 977 read
Action.c(34): Total number of bytes read = 69977
16.
The following example opens a log file and writes the id number and group name of the Virtual User to it using fprintf.
       #ifdef unix
              char * filename = "/tmp/logfile.txt";
       #else
              char * filename = "c:\\logfile.txt";
       #endif
       long file;
       int id;
       char * groupname;
       // Create a new file
       if ((file = fopen(filename, "w+" )) == NULL) {
              lr_output_message("Unable to create %s", filename);
              return -1;
       }
       // Write the Vuser id and group to the log file
       lr_whoami(&id, &groupname, NULL);
       fprintf(file, "log file of virtual user id: %d group: %s\n", id, groupname);
       fclose(file);
Written to log file:
log file of virtual user id: -1 group: None
17.
The following example uses free to de-allocate a buffer of length 1024.
18.
The following example, for Windows platforms, opens a file and reads it into a buffer. If file errors occur during the process, goto is used to escape the enclosing loop to code which prints an error message and exits the function.
int count, total = 0;
       char buffer[1000];
       long file_stream;
       char * filename = "c:\\xyzpqi.txt";
       // Open the file with read access
       if ((file_stream = fopen(filename, "r")) == NULL)
              goto file_error;
       // Read until end of file
19.
In the following example, lr_log_message sends a message to the log file if the connection to the server fails.
char* abort="aborting...";
...
if (init() < 0) {
       lr_log_message ("login failed: %s", abort);}
       return(0);
}
20.
In the following example, lr_message sends a message if the connection to the server fails.
char* abort="aborting...";
...
if (init() < 0) {
       lr_message ("login failed: %s", abort);}
return(0);
}
21,
In the following example, ID is a parameter defined in the Parameter list. The lr_next_row function advances to the next row in theID.dat file.
lr_message( "Connect to Stock Trader ID Number %s",
       lr_eval_string("{ID}") );
lr_next_row("ID.dat");
lr_message( "Connect to Stock Trader ID Number %s",
       lr_eval_string("{ID}") );
The output window shows:
Connect to Stock Trader ID Number 2347
Connect to Stock Trader ID Number 2348
22.
In this example, an Iteration Number type parameter called "iteration" was defined in VuGen. The lr_output_message function sends a message to the Load Runner Controller or the Application Mangement Admin Center indicating the current iteration number.
lr_output_message ( "We are on iteration #%s", lr_eval_string ( "{iteration}" ) );
23.
In the following example, the lr_rendezvous function sets the Meeting rendezvous point. When all users that belong to the Meeting rendezvous arrive at the rendezvous point, they perform do_transaction simultaneously.
lr_rendezvous("Meeting");
       do_transaction(); /* application dependent transaction */
24. In the following example, lr.save_data assigns a series of values to the ID parameter. This parameter is then used in an output message.
// Example array of arbitrary bytes.
byte [] b_arr = new byte[]{(byte)0x12,(byte)0x2,(byte)0x1,(byte)0x3};
// Save the array into parameter ID
lr.save_data(b_arr,"ID");
// Save the contents of the array parameter to another array
byte [] output_arr = lr.eval_data("<ID>");
lr.output_message("This is the value of the first output byte: "
       + Byte.toString(output_arr[0]));
25
In the following example, lr_load_dll is used so that a standard Windows message box can be displayed during script replay:
lr_load_dll("user32.dll");
MessageBoxA(NULL, "This is the message body", "message_caption", 0);
26.
In the following example, lr_log_message sends a message to the log file if the connection to the server fails.
char* abort="aborting...";
...
if (init() < 0) {
       lr_log_message ("login failed: %s", abort);}
       return(0);
}
In the next example, an Iteration Number type parameter called "iteration" was defined in VuGen. The lr_log_message function sends a message to the LoadRunner Controller or Application Management Admin Center indicating the current iteration number.
lr_log_message ( "We are on iteration #%s", lr_eval_string ( "{iteration}" ) );
27.
In the following example, lr_message sends a message if the connection to the server fails.
char* abort="aborting...";
...
if (init() < 0) {
       lr_message ("login failed: %s", abort);}
return(0);
}
28.
In this example, an Iteration Number type parameter called "iteration" was defined in VuGen. The lr_output_message function sends a message to the Load Runner Controller or the Application Mangement Admin Center indicating the current iteration number.
lr_output_message ( "We are on iteration #%s", lr_eval_string ( "{iteration}" ) );
29.
In the following example, lr_save_datetime is used to retrieve tomorrow's date.
lr_save_datetime("Tomorrow is %B %d %Y", DATE_NOW + ONE_DAY, "next");
lr_output_message(lr_eval_string("{next}"));
30.
In the following example, lr_save_int assigns the string representation of the value of variable num times 2 to parameter param1.
int num;
num = 5;
lr_save_int(num * 2, "param1");
The value of param1 is now "10".
31.
In this example, the lr_set_debug_message function enables the full trace option just before a call to lrd_fetch, which the user needs to debug because it has been giving unexpected results.
The second invocation of lr_set_debug_message resets the debug level to what it was formerly, by turning off (LR_SWITCH_OFF) the Extended message level.
32.
In the following segment, lr_start_timer and lr_end_timer are used to calculate the time spent on checks. This is then subtracted from the time spent on transaction "sampleTrans" with lr_wasted_time.
double time_elapsed, duration, waste;
merc_timer_handle_t timer;
       lr_start_transaction("sampleTrans");
       web_url("index.htm",
              "URL=http://localhost/index.htm",
              "TargetFrame=",
              "Resource=0",
              "RecContentType=text/html",
              "Referer=",
              "Snapshot=t1.inf",
              "Mode=HTML",
              LAST);
       timer = lr_start_timer();
/* Do some checks the duration of which
is not to be included in the transaction. */
       web_image_check("ImgCheck1",
              "src=index_files/image002.jpg",
              LAST);
       web_image_check("ImgCheck2",
              "src=index_files/planets.gif",
              LAST);
// How long did the tests take in seconds.
       time_elapsed = lr_end_timer(timer);
// Convert to millisecond.s
       waste = time_elapsed * 1000;
/* Remove the time the checks took from
       the transaction. */
       lr_wasted_time(waste);
        lr_end_transaction("sampleTrans", LR_AUTO);


In the following segment, lr_think_time instructs the script to pause for 10 seconds after accessing a link and submitting a form.
In the following example, a user data point is defined that checks the CPU every second and records the result.
for (i=0;i<100;i++) {
       measure_cpu ( );
       cpu_val=cpu_check();
       lr_user_data_point("cpu", cpu_val);
       sleep(1);
}
30
The following segment demonstrates the use of timers to collect wasted time, and the use of lr_wasted_time to remove that wasted time from the transactions. The output log segments below show that the effects are not reported in the Vuser log, but are reported in the Analysis session.
31.
In the following example, lr_whoami retrieves information about a Vuser and places it into a message string. The message string contains Vuser login information that is used to connect with a server.
Note that memory for vuser_group is allocated automatically. Do not alter the string.
           
        vuser_group, id, scid);
32.RTE functions
TE_connect
Connects the terminal emulator to the specified host.
TE_find_text
Searches for text in a designated area of the screen.
TE_get_line_attribute
Returns information about text formatting.
TE_get_text_line
Reads text from a designated line on the screen.
TE_get_cursor_pos
Returns the current location of the cursor.
TE_set_cursor_pos
Sets the position of the cursor on the terminal screen.
TE_getvar
Returns the value of an RTE system variable.
TE_setvar
Sets the value of an RTE system variable.
TE_perror
Prints an error code to the LoadRunner output window or Business Process Monitor agent log.
TE_sperror
Translates an error code into a string.
TE_send_text
Sends a null-terminated string to a VT terminal emulator.
TE_type
Sends a formatted string to the client application.
TE_typing_style
Determines the way text is typed into the terminal emulator.
TE_unlock_keyboard
Unlocks the keyboard of a mainframe terminal
TE_wait_cursor
Waits for the cursor to appear at a specified location in the terminal window.
TE_wait_silent
Waits for the client application to be silent for a specified number of seconds.
TE_wait_sync
Waits for the system to return from X-SYSTEM or Input Inhibited mode.
TE_wait_sync_transaction
Records the time that the system remained in the most recent X SYSTEM mode.
TE_wait_text
Waits for a string to appear in a designated location.
In these examples, web_save_param_length creates three new parameters, Param7_Length, Param10_Length,and Param16_Length, and stores the length of each respective source parameter as a hexidecimal number.
       // Create a parameter 7 characters long
       lr_save_string("ABCDEFG", "Param7");
       web_save_param_length("Param7", "Base=Hexadecimal", LAST);
       // Output: Action.c(9): Notify: Saving Parameter "Param7_Length = 7"
       // Create a parameter 10 characters long
       lr_save_string("ABCDEFGHIJ", "Param10");
       web_save_param_length("Param10", "Base=Hexadecimal", LAST);
       //Output is in hexadecimal:
       //Action.c(14): Notify: Saving Parameter "Param10_Length = A"
       // Create a parameter 16 characters long
       lr_save_string("ABCDEFGHIJKLMNOP", "Param16");
       web_save_param_length("Param16", "Base=Hexadecimal", LAST);
       //Output is in hexadecimal:
       //Action.c(18): Notify: Saving Parameter "Param16_Length = 10"
The following examples are presented for web_reg_save_param.
  • Example 1: Saving simple text strings
    • Case of saving a single string
    • Case requiring handling arrays
  • Example 2: Saving a text by using binary boundaries
  • Example 3: Saving a text specified with an offset and length
  • Example 4: Boundaries containing special characters
Example 1: Saving simple text strings

In this example, web_reg_save_param is used to save a value from the response to a web_submit_form call. The value saved is used in a subsequent web_submit_form call.
In the Mercury Tours sample program, the server response to the web_submit_form call below contains the following radio button options:
<tr bgcolor=#66cccc><th>Flight<th>Departure time<th>Cost
<tr bgcolor=#66CCff><td align=center><input type = radio name=outboundFlight value=230;378;11/20/2003 checked >Blue Sky Air 230<td align=center>8am<td align=center>$ 378
<tr bgcolor=#eeeeee><td align=center><input type = radio name=outboundFlight value=231;337;11/20/2003>Blue Sky Air 231<td align=center>1pm<td align=center>$ 337
and so on.
To submit a reservation, the outboundFlight value is required. web_reg_save_param is used to save the outboundFlightvalue.
  • Case of saving a single string
  • Case requiring handling arrays
Case of saving a single string
To reserve the default flight, save the "checked" value, and pass it to web_submit_form. The html segment for the default value is:
name=outboundFlight value=230;378;11/20/2003 checked >
/*This web_reg_save_param call applies to the following action function: web_submit_form. */
       web_reg_save_param("outFlightVal",
       "LB=outboundFlight value=", "RB= checked >", LAST);
       web_submit_form("reservations.pl",
              "Snapshot=t4.inf",
              ITEMDATA,
              "Name=depart", "Value=London", ENDITEM,
              "Name=departDate", "Value=11/20/2003", ENDITEM,
              "Name=arrive", "Value=New York", ENDITEM,
              "Name=returnDate", "Value=11/21/2003", ENDITEM,
              "Name=numPassengers", "Value=1", ENDITEM,
              "Name=roundtrip", "Value=<OFF>", ENDITEM,
              "Name=seatPref", "Value=None", ENDITEM,
              "Name=seatType", "Value=Coach", ENDITEM,
              "Name=findFlights.x", "Value=83", ENDITEM,
              "Name=findFlights.y", "Value=16", ENDITEM,
              LAST);
/*
The result of the web_reg_save_param having been called before the web_submit_form is:
Action.c(15): Notify: Saving Parameter "outFlightVal = 230;378;11/20/2003"
*/
// Now use the saved outFlightVal
       web_submit_form("reservations.pl_2",
              "Snapshot=t5.inf",
              ITEMDATA,
              "Name=outboundFlight", "Value={outFlightVal}", ENDITEM,
              "Name=reserveFlights.x", "Value=92", ENDITEM,
              "Name=reserveFlights.y", "Value=10", ENDITEM,
              LAST);
/*
Action.c(34): Notify: Parameter Substitution: parameter "outFlightVal" = "230;378;11/20/2003" */

 
Case requiring handling arrays
If you want to test the last option returned by the web_submit_form call, save all the matches and then handle the array.
This example shows the use of web_reg_save_param with "ORD=ALL" to get an array of parameters. The last item in the array is then used to correlate a web_submit_form call.
char outFlightParam[50]; // The name of the parameter for correlation
char outFlightParamVal[50]; // The formatted value of outFlightParam
/*
This web_reg_save_param call applies to the following action function, web_submit_form. Because of the "ORD=ALL" argument, it saves all the values that have the given left and right boundaries to an array of parameters.
The SaveLen argument is used to restrict the length to 18 characters because the default value is "230;378;11/20/2003 checked >". We restrict the length so as not to capture the " checked ".
*/
       web_reg_save_param("outFlightVal",
              "LB=outboundFlight value=", "RB=>",
              "ORD=ALL",
              "SaveLen=18",
              LAST);
       web_submit_form("reservations.pl",
              "Snapshot=t4.inf",
              ITEMDATA,
              "Name=depart", "Value=London", ENDITEM,
              "Name=departDate", "Value=11/20/2003", ENDITEM,
              "Name=arrive", "Value=New York", ENDITEM,
              "Name=returnDate", "Value=11/21/2003", ENDITEM,
              "Name=numPassengers", "Value=1", ENDITEM,
              "Name=roundtrip", "Value=<OFF>", ENDITEM,
              "Name=seatPref", "Value=None", ENDITEM,
              "Name=seatType", "Value=Coach", ENDITEM,
              "Name=findFlights.x", "Value=83", ENDITEM,
              "Name=findFlights.y", "Value=16", ENDITEM,
              LAST);
/*
The result of the web_reg_save_param having been called before the web_submit_form is:
Notify: Saving Parameter "outFlightVal_1 = 230;378;11/20/2003"
Notify: Saving Parameter "outFlightVal_2 = 231;337;11/20/2003"
Notify: Saving Parameter "outFlightVal_3 = 232;357;11/20/2003"
Notify: Saving Parameter "outFlightVal_4 = 233;309;11/20/2003"
Notify: Saving Parameter "outFlightVal_count = 4"
The next problem is to get the highest array element, identified with the parameter outFlightVal_count. This parameter is automatically created by the script recorder. You do not have to enter anything in the script.
*/
/* Get the name of the parameter, in this case "outFlightVal_4".
Put it in brackets so it can be an input to an lr_eval_string call.
Note that the brackets in the second argument to sprintf are not indicating a script parameter to sprintf. They are string literals that will be part of outFlightParam after the call.
In the second call to sprintf, those brackets indicate a parameter to lr_eval_string.
*/
       sprintf(outFlightParam, "{outFlightVal_%s}",
              lr_eval_string("{outFlightVal_count}"));
/* outFlightParam is now "{outFlightVal_4}" */
       /* Now get the "Value" argument for web_submit_form, in the
              format "Value=xxxx")
       */
       sprintf(outFlightParamVal, "Value=%s",
              lr_eval_string(outFlightParam));
       lr_message("The value argument is : %s", outFlightParamVal);
       // The value argument is : Value=233;309;11/20/2003
       /* Now the string outFlightParamVal can be passed
              to web_submit_form */
       web_submit_form("reservations.pl_2",
              "Snapshot=t5.inf",
              ITEMDATA,
              "Name=outboundFlight",outFlightParamVal, ENDITEM,
              "Name=reserveFlights.x", "Value=92", ENDITEM,
              "Name=reserveFlights.y", "Value=10", ENDITEM,
              LAST);
 

 
Example 2: Saving a text by using binary boundaries

The following example uses BIN type boundaries. The left boundary is composed of 3F and DD. The right boundary is composed of CCand b.
web_reg_save_param("p", "LB/BIN=\\x3F\\xDD", "RB/BIN=\\xCCb", LAST);
 
Example 3: Saving a text specified with an offset and length

The following example specifies an offset and length. The boundaries for the HTML string "Astra on TESTSERVER", are "Astra " (note the space which follows the word) and "TestServer"This should return "on" but since the offset is 1 (i.e. start at the second character) and the length of data to save is 1, then the string saved to TestParam is "n".
web_reg_save_param("Param1", "LB=Astra ", "RB= TESTSERVER",
       "SaveOffset=1", "SaveLen=1", LAST);
 
Example 4: Boundaries containing special characters

The following example shows the use of escaping in the C language when the boundaries contain special characters.
The following HTML segment contains new line characters (paragraph markers) after each "<strong>" and quote marks around each class name. We want to save "Georgiana Darcy" to parameter "UserName". The segment containing the new line and quotes has to be included in the left boundary because "Name:", which precedes the segment, is required for the occurrence to be unique. The ORD attribute cannot be used in this case because the length of the list preceding the relevant element varies.
<span class="surveyQuestionReview"><strong> UserID:</strong></span><strong>
    </strong> <span class="surveyAnswerReview">Revere18041775</span> <br>
<span class="surveyQuestionReview"><strong> Name:</strong></span><strong>
    </strong> <span class="surveyAnswerReview">Georgiana Darcy</span> <br>
<span class="surveyQuestionReview"><strong> Company:</strong></span><strong>
    </strong> <span class="surveyAnswerReview">Pride and Prejudice</span> <br>
The function is:
web_reg_save_param("UserName",
"LB=Name:</strong></span><strong> \n    </strong> <span class=\"surveyAnswerReview\">",
              "RB=</span> <br>",
              LAST);
Note the \n for the new line character, and that the quote characters need to be escaped: \".
In the following example, web_reg_find searches for the text string "Welcome". If the string is not found, it fails and the script execution stops.
       // Run the Web Tours sample
       web_url("MercuryWebTours",
              "URL=http://localhost/MercuryWebTours/",
              "Resource=0",
              "RecContentType=text/html",
              "Referer=",
              "Snapshot=t1.inf",
              "Mode=HTML",
              LAST);
// Set up check for successful login by looking for "Welcome"
       web_reg_find("Text=Welcome",
              LAST);
// Now log in
       web_submit_form("login.pl",
              "Snapshot=t2.inf",
              ITEMDATA,
              "Name=username", "Value=jojo", ENDITEM,
              "Name=password", "Value=bean", ENDITEM,
              "Name=login.x", "Value=35", ENDITEM,
              "Name=login.y", "Value=14", ENDITEM,
              LAST);
-------
In the following example, the web_find function searches for the name "John" in the employees.html page.
web_url("index.html",
        "URL=http://server1/people/employees.html",
        "TargetFrame=",
        LAST);
web_find("Employee Check",
        "expect=notfound",
        "matchcase=yes",
        "onfailure=abort",
        "report=failure",
        "repeat=no",
        "what=John",
        LAST);
Example 2
In the following example, the web_find function searches for the text "Home" which is between "Go to" and "Page".
web_url("index.html",
        "URL=http://server1/",
        "TargetFrame=",
       LAST);
web_find("Text Check",
        "RightOf=Go to",
        "LeftOf=page",
        "What=Home",
       LAST);

web_submit_data

Return Values
Parameterization
Performs an "unconditional" or "contextless" form submission