Exception ACCESS_VIOLATION

November 7th, 2009

Web (HTTP/HTML) scripts in LoadRunner are implemented using C programming language. And like always with C, you should remember about some basics. One of them is that few string handling function can return NULL value instead of correct pointer which will definitely lead to exception like the one below:

  1. Action.c(7): Error: C interpreter run time error: Action.c (7):  Error — memory violation : Exception ACCESS_VIOLATION received.

Basically if you see message like this, it is not any internal LoadRunner error. It means that you made a mistake in your script and you need to fix it. But let’s start from the beginning with some example:

  1. Action()
  2. {
  3.         char * x_p;
  4.        
  5.         lr_save_string("hello_world!", "MESSAGE");
  6.         x_p = (char *)strchr(lr_eval_string("{MESSAGE}"), ‘ ‘);
  7.         lr_save_string(x_p, "MESSAGE_FROM_SP");
  8.         lr_output_message(lr_eval_string("{MESSAGE_FROM_SP}"));
  9.        
  10.         return 0;
  11. }

This small piece of code takes parameter MESSAGE with value “hello_world”, then search for the first space character and display the string starting from that place up to the end. Function strchr() is responsible for searches for the space character. If it’s found then strchr() will return a valid pointer (something like 0xb36ac56e). But if the space is not there (which is our case since there is no space in the hello message), strchr() will return NULL which refers to 0×0 memory address location.

Such memory address is a very special address. Basically any read attempt from there is threated as incorrect operation and results in memory access violation (not only in LoadRunner).

Now, howto deal with it? If you see ACCESS_VIOLATION, in most cases it means that your LR script is working on incorrect/incomplete values. You are responsible for error handling in your scripts and you should always:

  • validate parameter’s values
  • check results of C functions to handle any errors, unexpected conditions
  • remember that you can’t always expect correct values and you need to handle it as well

Here is our example with fix showing howto deal with ACCESS_VIOLATION. We are calling strchr() function and checking if value returned is not NULL.

  1. Action()
  2. {
  3.         char * x_p;
  4.        
  5.         lr_save_string("hello_world!", "MESSAGE");
  6.         x_p = (char *)strchr(lr_eval_string("{MESSAGE}"), ‘ ‘);
  7.        
  8.         if(x_p) // if the pointer is not NULL display correct message
  9.         {
  10.                 lr_save_string(x_p, "MESSAGE_FROM_SP");
  11.                 lr_output_message(lr_eval_string("{MESSAGE_FROM_SP}"));
  12.         }
  13.         else //if pointer is NULL display error message
  14.         {
  15.                 lr_error_message("Space not found in MESSAGE parameter");
  16.         }
  17.         return 0;
  18. }

More details about NULL pointer here http://en.wikipedia.org/wiki/Pointer_(computing)#The_null_pointer

LoadRunner + QTP = End-to-End performance

October 2nd, 2009

The easiest way to measure web app performance is just to record a script and run it in HP Controller. Such test is fast and simple, but it’s also incomplete and incorrect. It’s because LoadRunner is not the tool for performance measurements. It’s a tool only for generating the load on the server (Load Runner – tool for “Running” the “Load”).

So how to deal with that?

LoadRunner finishes taking measurements when web page code and all non-HTML elements (jpg,gif,js) are download into the clients memory. But starting from that point the browser need to form UI and display it to the user. And that’s the part that LR is actually skipping. Full end-to-end test should measure time between clicking “submit” button (or whatever triggers a call) and displaying full page within the browser. So how to do it in LR? The quickest answer is “not possible”. For that you need to use QuickTest Professional.

In that case of course you need at least two scripts. One prepared in LoadRunner and second prepared in QTP. Each script will have different task to accomplish. LR script will generate the load on the server simulating different amount of remote users connecting with AUT. QTP script will measure times only for one user, and that’s what we actually need. I believe every single web user care only about how fast page works in his browser. Not how fast it works across all remote users together in average. Of course one is connected with the another.

LoadRunner and QTP have one thing in common – transactions. And basically to measure end-to-end time in QTP all you need to do is to use transactions and remember to synchronize each page correctly. By synchronize I mean to finish transaction when page is fully downloaded and displayed to the user. One solutions for checking when downloading is finished is to call WaitProperty on browser’s status bar element. Example QTP code:

  1. Services.StartTransaction "SUBMIT_PAGE"
  2. Browser("IE").Page("Add_User").Image("Submit").Click 50,16
  3. Browser("IE").WinObject("Status_Bar").WaitProperty "visible", FALSE
  4. Services.EndTransaction "SUBMIT_PAGE"

If you have LR and QTP scripts already in place, now just add them in HP Controller into your scenario. To see QTP scripts in Browse window just change File Type from “Vuser Scripts” into “QuickTest scripts”. One think to remember is that you are allowed to run only single QTP instance at a time so hacks like few QTP scripts running simultaneously are not possible (unless you are using Citrix which is another story).

Only with such scenario you are able to measure full end-to-end performance.

DEFCON 17 – CTF tutorial

September 9th, 2009

If you ever wondered howto solve Capture The Flag contest exercise, here http://hackerschool.org/DefconCTF/17/B300.html is a good detailed description. Have fun…

some links that I read recently

July 30th, 2009

http://r00tsecurity.org/files/zf05.txt Joanna called “Biggest mailing list troll” heh

http://xorl.wordpress.com/

Web Services testing in LoadRunner

July 24th, 2009

Some time ago I described how to test web services in LoadRunner with HTTP/HTML script. Right now I would like to describe the correct way – testing with Web Services script.

First of all we need a web services. And there is one available exactly for training. Here is the WSDL http://soatest.parasoft.com/store-01.wsdl. I hope that folks from Parasoft don’t mind we are not using SOATest :)

In any case, we have an WSDL file. Now lets create new script.

Click File / New and select “Web Services” from list of available scripts types.

1

Now, when we have new script we should see new toolbar under the standard one. It allows to add Web Services description to the script (from WSDL file), add XML request using form and add XML request from file. So lets click on “Manage Services” button and then “Import”. Enter WSDL url http://soatest.parasoft.com/store-01.wsdl and click “Import”.

2

After WSDL file is imported, just click “Apply” and “OK”. From this point LoadRunner has description of our web services so we can use it send some requests. We will actually create two requests. One using “Add Service Call” and second using “Import SOAP” buttons from toolbar.

Click on “Add Service Call”. In “Operation” dropdown list select value “getItemById”. On left side select “id” under Input Arguments tree node. Then on right side type “1″ into Value editbox.

3

Now our script should look like this:

  1. Action()
  2. {
  3.    web_service_call( "StepName=getItemById_101",
  4.        "SOAPMethod=Cart|ICart|getItemById",
  5.        "ResponseParam=response",
  6.        "Service=Cart",
  7.        "ExpectedResponse=SoapResult",
  8.        "Snapshot=t1248415874.inf",
  9.        BEGIN_ARGUMENTS,
  10.        "id=1",
  11.        END_ARGUMENTS,
  12.        BEGIN_RESULT,
  13.        END_RESULT,
  14.        LAST);
  15.    return 0;
  16. }

Now lets add Web Service request using Import SOAP. Lets assume we have XML request saved in file on the disk. Here is an example:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  3.  <SOAP-ENV:Body>
  4.   <getItemByTitle xmlns="http://www.parasoft.com/wsdl/store-01/">
  5.    <titleKeyword>Linux</titleKeyword>
  6.   </getItemByTitle>
  7.  </SOAP-ENV:Body>
  8. </SOAP-ENV:Envelope>

Click “Import SOAP” button and select your file. Change type from “Web Service Call (Recommended)” to “SOAP Request”. Select URL from the list, and type into SOAPAction this value “getItemByTitle”. Click OK.
Now we’ve added second call that ask for book details for title “Linux”. Our script should look like this:

  1. Action()
  2. {
  3.    web_service_call( "StepName=getItemById_101",
  4.        "SOAPMethod=Cart|ICart|getItemById",
  5.        "ResponseParam=response",
  6.        "Service=Cart",
  7.        "ExpectedResponse=SoapResult",
  8.        "Snapshot=t1248415874.inf",
  9.        BEGIN_ARGUMENTS,
  10.         "id=1",
  11.         END_ARGUMENTS,
  12.         BEGIN_RESULT,
  13.         END_RESULT,
  14.         LAST);
  15.    soap_request("StepName=SOAP Request",
  16.        "URL=http://ws1.parasoft.com/glue/store-01",
  17.        "SOAPEnvelope="
  18.        "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
  19.        "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
  20.        "<SOAP-ENV:Body>"
  21.        "<getItemByTitle xmlns=\"http://www.parasoft.com/wsdl/store-01/\">"
  22.        "<titleKeyword>Linux</titleKeyword>"
  23.        "</getItemByTitle>"
  24.        "</SOAP-ENV:Body>"
  25.        "</SOAP-ENV:Envelope>",
  26.        "SOAPAction=getItemByTitle",
  27.        "ResponseParam=response",
  28.        "Snapshot=t1248416271.inf",
  29.        LAST);
  30.    return 0;
  31. }

As you can see, each request contain “ResponseParam=response”. LoadRunner will automatically save response XML into parameter with name “response”. We can easily display this parameter by addind

  1. lr_message(lr_eval_string("Response XML is \n{response}"));

after each call. So at the end out script should look like this:

  1. Action()
  2. {
  3.    web_service_call( "StepName=getItemById_101",
  4.        "SOAPMethod=Cart|ICart|getItemById",
  5.        "ResponseParam=response",
  6.        "Service=Cart",
  7.        "ExpectedResponse=SoapResult",
  8.        "Snapshot=t1248415874.inf",
  9.        BEGIN_ARGUMENTS,
  10.         "id=1",
  11.         END_ARGUMENTS,
  12.         BEGIN_RESULT,
  13.         END_RESULT,
  14.         LAST);
  15.  
  16.    lr_message(lr_eval_string("Response XML is \n{response}"));
  17.  
  18.    soap_request("StepName=SOAP Request",
  19.        "URL=http://ws1.parasoft.com/glue/store-01",
  20.        "SOAPEnvelope="
  21.        "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
  22.        "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
  23.        "<SOAP-ENV:Body>"
  24.        "<getItemByTitle xmlns=\"http://www.parasoft.com/wsdl/store-01/\">"
  25.        "<titleKeyword>Linux</titleKeyword>"
  26.        "</getItemByTitle>"
  27.        "</SOAP-ENV:Body>"
  28.        "</SOAP-ENV:Envelope>",
  29.        "SOAPAction=getItemByTitle",
  30.        "ResponseParam=response",
  31.        "Snapshot=t1248416271.inf",
  32.        LAST);
  33.  
  34.    lr_message(lr_eval_string("Response XML is \n{response}"));
  35.  
  36.    return 0;
  37. }

At the end lets run our script. Output should be something like this:

4

Validating Web Service response with XPath

May 18th, 2009

The easiest way for checking web service response in HP LoadRunner is by using XPath query language. LR API contains few functions designed especially for dealing with XML.

  1. lr_xml_get_values()  //Retrieves values of XML elements found by a query
  2. lr_xml_set_values()  //Sets the values of XML elements found by a query
  3. lr_xml_extract()  //Extracts XML string fragments from an XML string
  4. lr_xml_delete()  //Deletes fragments from an XML string
  5. lr_xml_replace()  //Replaces fragments of an XML string
  6. lr_xml_insert()  //Inserts a new XML fragment into an XML string
  7. lr_xml_find()  //Verifies that XML values are returned by a query
  8. lr_xml_transform()  //Applies Extensible Stylesheet Language (XSL) Transformation to XML data

Now, lets say we have sample web service for on-line book store and we want to ask what is the author for book id 123. Our web service can send following XML as a response:

  1. <books>
  2.   <book>
  3.       <id>123</id>
  4.       <author>John Smith</author>
  5.       <title>Working with Legacy code</title>
  6.       <publisher>Microsoft</publisher>
  7.   </book>
  8. </books>

For checking if the “author” element within XML response contains “John Smith” value we will use lr_xml_get_values() function. Here is the code that calls web service and checks if the value is as expected:

  1. Action()
  2. {
  3.      web_add_header("SOAPAction", "\"CallMe\"");
  4.      lr_start_transaction("AUTHOR");
  5.      soap_request("StepName=Sample Soap Request",
  6.        "ExpectedResponse=ANY",
  7.        "URL=http://foo.com/api",
  8.        "SOAPEnvelope= "
  9.        "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
  10.        "<soap:Envelope "
  11.        "xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" >"
  12.        "<soap:Body soap:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
  13.        "<GetBookDetails>"
  14.        "<idValue>123</idValue>"
  15.        "</GetBookDetails>"
  16.        "</soap:Body>"
  17.        "</soap:Envelope>",
  18.        "Snapshot=t765765765.inf",
  19.        "ResponseParam=Response_Xml",LAST);
  20.  
  21.  
  22.      lr_xml_get_values("XML={Response_Xml}",
  23.           "ValueParam=Author_Name",
  24.           "Query=/books/book/author",
  25.           LAST);
  26.  
  27.      lr_output_message(lr_eval_string("Author is = {Author_Name}"));
  28.  
  29.      if(strcmp(lr_eval_string("{Author_Name}"),"John Smith") == 0)
  30.      {
  31.         lr_end_transaction("AUTHOR", LR_PASS);
  32.      }
  33.      else
  34.      {
  35.         lr_end_transaction("AUTHOR", LR_FAIL);
  36.      }
  37.      return 0;
  38. }

First argument in lr_xml_get_values() call is parameter name that holds response XML. Second argument in name of new parameter that will hold author value extracted from response XML. Third argument is XPath query that extracts author element value.

IP Spoofing with LoadRunner

April 23rd, 2009

As described here ip spoofing is a technique for hiding real identity of the attacker on the net. It is mainly used for hacking but it can be helpful for performance tests as well.

Let’s say we have some fancy network infrastructure that cache some of our requests in the performance test. Because of that our results may be incorrect. To omit this issue we can change the IP address of each (e.g. HTTP) request that reaches the server and simulate load from multiple users not only on the application level but on the network level as well. In that case cache won’t affect performance tests. Fortunately folks from Mercury/HP implemented special function for IP spoofing in LoadRunner API.

  1. lr_enable_ip_spoofing();
  2. lr_disable_ip_spoofing();

To use it, first put your code between these to functions calls.
Second (before connecting to load generator!!!) enable IP Spoofer option in LR Controller (Scenario > Enable IP Spoofer).

Let the hacking begin :)

Tip:
There is an option in Controller (in Expert mode) to choose between multiple IP addresses per process or per thread (Tools > Options).

Don’t waste your time

April 19th, 2009

Waste time in Load Runner is a time spend on tasks that normal browser user wouldn’t perform like storing test results, performance monitoring, calculations, etc. Wasted time is measured by LR automatically but sometimes it is necessary to use it explicitly through lr_wasted_time() function .

lr_wasted_times() removes time from all open transaction. If you want to make some calculation and don’t count them into overall transaction time then you should use this function.

Small example

  1. Action()
  2. {
  3.         merc_timer_handle_t timer;
  4.         long i;
  5.         double wastedTime;
  6.  
  7.         lr_start_transaction("My_Transaction");
  8.         timer = lr_start_timer();
  9.         for(i = 0; i < 1000; i++)
  10.                 lr_message("%d\n", i);
  11.         wastedTime = lr_end_timer(timer);
  12.         wastedTime*=1000;
  13.  
  14.         lr_wasted_time(wastedTime);
  15.  
  16.         lr_end_transaction("My_Transaction", LR_AUTO);
  17.         lr_message("Wasted %lf milliseconds", wastedTime);
  18.         return 0;
  19. }

On line 7 I’m starting one transaction. On line 8 I’m starting timer and stoping it at line 11. For loop between is used to generate my wasted time. After stopping the time, we need to subtract wasted time from open transaction by calling lr_wasted_time() on line 14. But before that on line 12 we need to change time units. lr_end_timer() returns time in seconds but lr_wasted_time() takes time in milliseconds. Thats why we need to multiply it by 1000. There is one more think. lr_wasted_time() is defined as

  1. void lr_wasted_time (long wasteTime);

If you use long type variable to measure wasted time you will always get rounded results (e.g. 1000, 2000, 3000). Instead it is better to use double type variable so at the end the results are more precise.