VuGen: Find A Shorter String Within A Longer One

We had a web application which was easy to script, but had an unusual situation dealing with the business rules that we had to work around. This was an application where users update their personal information, emergency contacts, and other forms.

The problem was the Emergency Contacts. Since this was a brand new application to the company, most users would not have anything listed and would need to input this information. The first time the user accesses the page, they would get a message that they are required to have at least one emergency contact and the application’s business rules would force them to enter a single PREFERRED contact. They had the option of adding up to five, but at least one was required. All additional contacts would be considered SECONDARY.

The weird thing was not adding the first contact, but there were only a limited number of test users to work with. What happens the second time you access the form? You could edit the existing, but we needed to put a transaction time around adding a NEW contact. We want to leave the database as clean as we found it,  so we wanted to delete any contact we added. You can’t do that if the only emergency contact is the initial PREFERRED one. We added a secondary contact and then tried to delete it. In theory this should be a very simple thing. However, sometimes when you added the second contact it would be the first one listed, and other times it would be the second one listed. Because we are bypassing the GUI with out Vugen script and making GETS and POSTS that could bypass some of the business rules we were actually deleting the PRIMARY some of the time, which meant the next time a user went to that page, there would be an error page waiting on them. This would throw errors in the Controller. About 50% of those transactions for adding a contact were failing. This illustrates the importance of verification of business rules at both the application layer AND at the database layer.

To make matters even worse,  the list of contacts were displayed in such a way that capturing text within the table listing was difficult. Here is the table where the Name(” Load Runner” and Role (“Primary”) is actually in the HTML source:

<tr>
 <td align="center" valign="middle">
 <a href="../edit/select.do?emerContId=94422" >
 <img src="/oneforce/images/icon_edit.gif" border="0">
 </a>
 </td>
 <td align="center" valign="middle">
&nbsp;
</td>
 <td valign="top">
 Load
 
Runner
 </td>
 <td valign="top">
 
Primary
 
</td>
<td valign="top">
Brother
</td>
<td valign="top">
999-999-9999
</td>
<td valign="top">
</td>
</tr>

I know that still LOOKS simple, but what you don’t see is all of the \t\t\t\t\t \r\r\r\r \n characters that are in there as well. If you tried to capture just the word “Primary”, ther left and right boundaries in a web_reg_save_param would look like this:

td class=\"datacell2\" valign=\"top\">\t\t \t\n \t\t\t\t\t\t\\t\t\t \n \t\t\t\t\t\t\t\t\t\t\t\t\t

This was not working. There wasn’t an easy left and right boundary for capturing a useful string. We had tp get as much of a unique left and right boundary, and the right ORDINAL  to get it as specific as possible for our correlation. If we grabbed a cell that had the word “Primary” in it, we did not want to delete that one. We set up a web_reg_save_param to capture ALL tabs, new lines, etc like this:

web_reg_save_param("pSecondaryContact",
 "LB=td class=\"datacell1\" valign=\"top\">",
 "RB=</td>",
 "Ord=2",
 "NotFound=EMPTY",
 LAST);

This pulled up about 128 characters within the table, but right in the middle of all the \t and \n’s characters was the word “Primary”. If we ran the web_reg_save_param and this word was in the long string, we knew we should delete id number 2 on the list. If it was not there, we wanted to delete id number 1, because that meant the secondary contact was the first on the list. Are you still with me?

After that step in the script, instead of checking to see what the value of {pSecondaryContact} was, we decided to use strstr to search through those characters hunting for the word “Primary”.  At the top of the Action, where you initialize your variables, we set up two character pointers:

char *strPrimary = "Primary";
char *strCapturedString;

Then, after the step that captures pSecondaryContact, run the following code:

strCapturedString = lr_eval_string("{pSecondaryContact}");
 
rc = strstr(strCapturedString, strPrimary);
 
if ( rc == 1 )
 {
/*
 * Delete_Secondary_Contact code follows on...
 */
 …
 …
 }

This takes that long string with all the escape characters and stores its value in a pointer called strCapturedString.Using the rc integer variable, it checks if the strstr function actually finds the string “Primary” (as set at the top of script) in the captured string. Strstr returns a status code of 1 if it finds something, and 0 if it does not. The “if” statement means that if the string “Primary” is found, then run the step that deletes the appropriate record on the web page. We added an ELSE statement with the exact same deletion step, but that deletes the first record instead. This worked!

When it’s not easy to capture a string because there is no easy left and right boundary, grab a larger amount of text and search for the specific string needed within it. This could even be used when you need to find the exact location within the string (the offset) and strip it out of the larger string. There are all kinds of uses. There is probably an easier way to accomplish this. If you know of one, please let me know in the comment section below.

What's Next?

Did you enjoy this article? Help spread the word by sharing:

Join the Northway Navigator Club today and get access to restricted content including our best tips and tricks. Membership is free! You will also receive free email updates by registering.

Engage in the conversation and leave a comment:

Scott Moore

About Scott Moore (153 articles)

With over 20 years of IT experience with various platforms and technologies, Scott has tested some of the largest applications and infrastructures in the world. He is a Certified Instructor and Certified Product Consultant in HP’s LoadRunner and Performance Center products. He currently holds HP certifications for ASE, ASC, and CI. A thought leader in the APM space, he speaks regularly at IT conferences and events