Wednesday, August 26, 2009

Each VUser Must Use Unique Login ID

This is a problem: the web app that I am testing is using the login id as session id. Since I am furnished with data, that has multiple non-unique logins, I have to make sure that all of virtual users are using unique login id.

Several solutions come to mind, but I decided to give LoadRunner VTS a whirl.

Perusing VTS2.doc I quickly hone in lrvtc_send_if_unique function:
VTCERR lrvtc_send_if_unique(char *columnName, char *message)
But this function is pretty much useless since the VTCERR equals 1 no matter if the insertion is successful or not. Trying its cousin instead:
VTCERR vtc_send_if_unique(PVCI pvci, char *columnName, char *message, unsigned short *outRc)
This function returns successful insertion status in outRc parameter (1 = Pass, 0 = Fail).
lr_start_transaction("GetUniqueUserName");
status = 0;
while (status == 0) {
lr_save_string(lr_eval_string("{pDATAFILEUserName}"), "pUserName");

pvci = lrvtc_connect(lr_eval_string("{pVTSServer}"), 8888, 0);
rc = vtc_send_if_unique(pvci, "pUserName1", lr_eval_string("{pUserName}"), &status);
lr_output_message("Insert if unique, rc = %d, status: = %d", rc, status);
lrvtc_disconnect();

if (status == 0) //try another login in the data file if fail
lr_advance_param("pDATAFILEUserName ");
else
user_removed = 0; // just another flag
}
lr_end_transaction("GetUniqueUserName", LR_AUTO);
The login removal process is a trickier than the insert process, since VTS doesn’t have a function to look up a value in a column, a value has to be looked up (one by one):
int removePreviousUserName() { // to eliviate the nasty side effect of exit when error
int rc = 0;
unsigned short status;
int EOT = 0;
int i;
int user_removed = 0;

lr_start_transaction("RemovePreviousUserName");
i=lastrowID;

while (!EOT) {
i++;
pvci = lrvtc_connect(lr_eval_string("{pVTSServer}"), 8888, 0);

rc = lrvtc_query_column("pUserName1", i);
lr_output_message("query row %d, rc = %d", i, rc);

if (rc!=0)
EOT = 1;
else {
if (stricmp(lr_eval_string("{pUserName}"), lr_eval_string("{pUserName1}")) == 0) {
lr_output_message("Del msg (%s) at row %d", lr_eval_string("{pUserName1}"), i);
rc = vtc_clear_message(pvci, "pUserName1", i, &status);
lr_output_message("Del msg, rc = %d, Status = %d", rc, status);
lastrowID = i;
EOT = 1; // exit anyway
user_removed = 1;
}
}
lrvtc_disconnect();
}
lr_end_transaction("RemovePreviousUserName", LR_AUTO);
return user_removed;
}
A little explanation about lastrowID, when a data is deleted from VTS, a value can never be re-inserted into that row again via vtc_send_if_unique function. So, there are lots of empty rows at the lower index after the value is deleted. Thus there is no point for the script to start the search for a login to delete from row 1; instead it should start the search from the last deletion point.

Functionally the script works, but VTS system is not capable of handling multiple virtual users. At 10 virtual users, each running 20 seconds transactions, VTS is throwing numerous -10003 errors, that causes slow GetUniqueUserName transaction:
  • 75% of population: 2.201 +/- 2.912
  • 90 Percentile: 6.506
2.2 seconds on the average to insert unique value? I don’t think so. I need a better solution.

No comments: