IBM Business Analytics Proven Practices: Scripting Basic IBM Cognos 10 Report Execution Using LoadRunner

Product(s): IBM Cognos 10 BI v10.1.1, v10.2 and v10.2.1; Area of Interest: Performance

This document is intended for individuals using LoadRunner to drive performance and stability tests against IBM Cognos 10. The main focus of this document is the action of executing simple reports in IBM Cognos Viewer.

Share:

Eric Racine, Performance and Stability, IBM

Eric has been part of IBM Cognos since 1991 and has worked on the Performance and Stability team for the past 7 years. Eric is well versed in using automation tools such as LoadRunner to simulate multiple concurrent users in order to analyze software performance and determine hardware sizing requirements.



06 December 2013

Introduction

Purpose of Document

This document is intended for individuals using LoadRunner to drive performance, scalability and stability tests for IBM Cognos 10. The topic covered will be the action of executing simple reports in IBM Cognos Viewer.

Applicability

In general, the concepts should be applicable to all IBM Cognos 10 production versions. The code examples will be specific to IBM Cognos 10 BI versions 10.1.1, 10.2 and 10.2.1. All script examples were recorded using LoadRunner v9.5. Minimal testing was successfully done with LoadRunner v11.5.

Exclusions and Exceptions

The code shown in this document will not necessarily work in every environment for every test case. Cases where there are authored drillthroughs, portlets or dashboards will require specific coding even though they share many of the same concepts described in this document.

As IBM Cognos 10 BI is continuously under development, the code examples and concepts outlined in this document may not apply to versions other than IBM Cognos 10 BI versions 10.1.1, 10.2 and 10.2.1.

Assumptions

It is assumed the consumer of this document has a programming background and is already familiar with developing scripts in LoadRunner.


Description Of The Test Case

For the purposes of this document, the following simple test case has been created and needs to be tested in IBM Cognos 10 BI.

  1. Connect to IBM Cognos 10 BI via a web browser.
  2. Login using simple LDAP authentication.
  3. Navigate to a report in a folder in IBM Cognos Connection.
  4. Click on the desired report which is a simple list. This action will execute the report in IBM Cognos Viewer.
  5. Click on the Return link to exit IBM Cognos Viewer and return to IBM Cognos Connection.
  6. Logoff.

Asynchronous Communication In IBM Cognos Viewer

This section offers a simplified explanation of asynchronous (or async) communication in IBM Cognos Viewer. For the purpose of this document asynchronous communication is between the client (ie: a web browser) and the IBM Cognos 10 BI server. It is basically a back and forth between the client and the IBM Cognos 10 server in which the IBM Cognos 10 server updates the browser to the current status of the running report at specified intervals. Table 1 and Table 2 describe a simple asynchronous conversation between a web browser client requesting the execution of a report and the IBM Cognos 10 BI server.

Table 1: Communication for a report that executes in less than 3 seconds
Web Browser ClientIBM Cognos 10 BI Server
Report “Run” request is issued->
<-Status=”Complete” less than 3s later
Report is pushed to browser and rendered in IBM Cognos Viewer.
Table 2: Asynchronous communication for a report that has an execution time of 40 seconds
Web Browser ClientIBM Cognos 10 BI Server
Report “Run” request is issued.->
<-Status=”Working” after 3s have elapsed
“Wait” response->
<-Status=”stillWorking” after 30s have elapsed. “stillWorking” will be sent every 30s until the report is complete.
“Wait” response->
<-Status=”Complete” after 7s.
Report is pushed to browser and rendered in IBM Cognos Viewer.

Both of these cases must be accounted for in the LoadRunner script because a report that runs in less than 3 seconds when there is only 1 user is on the system may take 40 seconds or more when 500 users are on the system. Conversely, a report that runs in 6 seconds on a low-end IBM Cognos 10 BI development environment may run in less than 3 seconds on a production level test environment. The script must be able to handle both cases and there will be more on this later in the document.


Forcing Asynchronous Communication In IBM Cognos 10

IBM Cognos 10 BI comes with the option for the IBM Cognos 10 BI Administrator to force a report execution request to enter asynchronous mode. This is the desired mode for recording any test case via LoadRunner. This ensures that any request will go into asynchronous communications mode and at least one cycle of the asynchronous communication will be recorded by LoadRunner.

Steps to enable forced asynchronous communication:

  1. For each IBM Cognos 10 Dispatcher instance, locate the file named rsvpproperties.xml.sample in the <c10install>/configuration directory.
  2. Rename the file to rsvpproperties.xml.
  3. Open rsvpproperties.xml using a text editor such as Notepad or vi, locate the AsynchWaitOverride property and uncomment the property by removing the <!-- and --> that surround it and setting the value to -3. The uncommented property should be as follows,
    <property>AsynchWaitOverride</property>
    <value type="long">-3</value>
  4. Restart each IBM Cognos 10 Dispatcher.

What a negative value in the AsynchWaitOverride property does is force the run request to “sleep” for one second longer than the absolute value of the AsynchWaitOverride property, thus forcing the asynchronous conversation for at least one cycle. This is a setting that should only be used for script development purposes and should never be used when performing any actual tests.

To disable forced asynchronous communication, reverse the steps used to enable it:

  1. For each IBM Cognos 10 Dispatcher instance, locate the file named rsvpproperties.xml in the <c10install>/configuration directory.
  2. Rename the file to rsvpproperties.xml.sample.
  3. Open rsvpproperties.xml.sample using a text editor such as Notepad or vi, locate the AsynchWaitOverride property and comment out the property by adding <!-- and --> around it. Set the value to 3. The commented out property should be as follows,
    <!-- <property>AsynchWaitOverride</property>
    <value type="long">3</value> -->
  4. Restart each IBM Cognos 10 Dispatcher.

Recording The Test Case In LoadRunner

It is recommended that the LoadRunner recording of the test case be done in HTTP/HTML mode and the General: Recording option set to HTML-based script. The HTML Advanced options that are tied to this setting should use the default settings.

When recording ensure comments are inserted into the script at record time so it is easier to know what steps were being executed at the time the code was recorded.

Some may be tempted to use LoadRunner’s Click and Script technology. While Click and Script is not recommended, it may work so, if time permits, trying it out may be worthwhile. Investigation into using the Click and Script recording option for IBM Cognos 10 BI test cases yielded mixed results, more negative than positive. We found that anything beyond the most basic test cases won’t work in this mode.


Understanding The Raw Recording Pertaining To Report Execution

Even with comments inserted into the code, it can be difficult to understand exactly what is going on when a report is executed. IBM Cognos 10 BI describes many user gestures as actions.

Table 3 should assist a scripter in reading the generated raw recording. Looking for the following keywords in the raw recording will help explain what has just been recorded.

Table 3: Definitions of some IBM Cognos 10 BI actions
KeywordsExplanation
ui.action=runExecute a report. Likely unseen in this code example.
ui.action=waitRespond to an IBM Cognos 10 BI status message of “Working” or “stillWorking”.
ui.action=releaseSignal to IBM Cognos 10 BI that the user is finished with a report.

IBM Cognos 10 BI makes use of numerous session related values that change dynamically during script execution. As a result, a simple record and playback scenario is not a viable option.


Creating LoadRunner Code From The Raw Recording

This section is an example on turning raw LoadRunner code into code that can be used for testing purposes. We will draw from the raw LoadRunner recording to create a workable script.

The code will ignore step validation but validation should be done on each step of a LoadRunner script so that the success/failure of the step can be tracked. LoadRunner functions such as web_reg_find should be used.

In general, any EXTRARES resources should be stripped from the code. Leaving them in could, in certain circumstances, cause undue load on the IBM Cognos 10 BI system and in almost every circumstance (with a few notable exceptions such as charts and PDF output), the resources are downloaded automatically by LoadRunner.

Code for “1. Connect to Cognos 10 via a web browser”

This step is straightforward. To connect to IBM Cognos 10 BI, a valid URL must be entered using LoadRunner’s web_url function. This can be pulled almost “as is” from the raw recording if the web server and the virtual directory for the IBM Cognos 10 Gateway will not be changing. It is very common to parameterize the web server and virtual directory for portability to other test environments.

// connect to web server
web_url("ConnectToCognosPortal",
	"URL=http://{WebServer}{WebVDir}",
	"Resource=0",
	"RecContentType=text/html",
	"Referer=",
	"Snapshot=t1.inf",
	"Mode=HTML",
	LAST);

Code for “2. Login using simple LDAP authentication”

Again, this step is straightforward as the recorded function is typically a web_submit_form function that takes two values, username and password. As above, these are usually parameterized. In a typical environment, successfully authenticating will cause the user’s Welcome page to load.

// enter in username and password
web_submit_form("EnterUserCredentials",
	"Snapshot=t2.inf",
	ITEMDATA,
	"Name=CAMUsername", "Value={UserID}", ENDITEM,
	"Name=CAMPassword", "Value={Password}", ENDITEM,
   	LAST);

// load IBM Cognos 10 Welcome page
web_url("Welcome Page",
"URL=http://{WebServer}{Gateway}?b_action=xts.run&m=portal/welcome/welcome.xts",
“Resource=0",
"RecContentType=text/html",
"Referer=",
"Snapshot=t260.inf",
"Mode=HTML",
LAST);

Code for “3. Navigate to a report in a folder in IBM Cognos Connection”

The next step is to navigate to a folder in IBM Cognos Connection that contains a report. Using LoadRunner’s web_link functions are typically the best and easiest approach since no maintenance or changes are required when moving to new IBM Cognos 10 BI environments. Parameterize the folder name, if necessary. If there is more than one Folder to navigate, string a group a web_link functions together to complete the folder navigation steps.

// click link defined by the Folder name
web_link("NavCC_link",
    	"Text={folderName}",
    	"Snapshot=t7.inf",
    	LAST);

Code for “4. Click on the desired report which is a simple list. This action will execute the report in Cognos Viewer in HTML output.”

Step 4 contains most of the complexity within this test case. To make it easier to understand it has been broken down into two subcomponents.

  1. Issuing the run request for the report.
  2. Handling the async conversation programmatically.

Code for “Issuing the run request for the report”

In the run_report() function listed below, the code that follows the web_link named ClickReportNameLink contains the ui.action=run command (see Table 3) to tell IBM Cognos 10 to execute the selected report. There is client-server communication information that starts when the ui.action=run command is initiated. This is captured in the getAsyncInfo() procedure. See Appendix A for the code to the getAsyncInfo() procedure. This information is crucial to properly track the request and to avoid negative performance hits and unnecessary errors. If the report is not ready in less than 3 seconds, the async communication loop is started.

If the report output is ready in less than 3 seconds, HTML and PDF output will be sent directly to the browser.

If the report contains a chart, the PNG file containing the chart must be retrieved from the IBM Cognos BI server once the report execution has completed. This is handled in a function call to getChartOutput() whose code can be found in Appendix A.

PDF output is a special case. If the PDF is not ready within 3 seconds the output is not pushed to the client, the client must retrieve it. However, the location of the PDF is a URL that is found in the server's status update when it responds with status = "complete" when running a report with PDF output. We use the getPDFReportOutput() (see Appendix A) function to retrieve the PDF report output.

If we are running a CSV report, we need to obtain all required dynamic parameters. The left and right boundaries of these are different than those obtained when running a report containing charts or running a PDF report. Similar to PDF and charts, CSV output must be retrieved using the URL in the server response. The getCSVReportOutput() function (see Appendix A) is used to retrieve the resulting output.

Run Report request for Cognos 10.1

void run_Report(char *reportName, char *contentCheck)
	lr_save_string(lr_eval_string(reportName), "reportName");
	 // turn reportName into LoadRunner parameter
	lr_save_string(lr_eval_string(contentCheck), "contentCheck");
	 // turn contentCheck into LoadRunner parameter

	getAsyncInfo(); // gather dynamic server-client communication info
{
// gather dynamic server-client communication info
getAsyncInfo(); 

// check for a successful PDF or HTML report
web_reg_find("Text={contentCheck}", "SaveCount=successfulReport", "Search=All", LAST);

/* 
If we've obtained one or many 'f' parameters, we've obtained one or more
charts. When we obtain a chart, we also obtain a 'k', 's', and 'did'
parameter to accompany the 'f' parameter. To simplify this situation, we've
selected the 'f' parameter to validate that we've received the correct
number of charts back in a given report. The number of 'f' parameters
we find should be equal to the number of 'k', 's', and 'did' parameters.
Please note that the boundaries of the 'f' parameter for a chart are
entirely different than those for a CSV report.
*/	
web_reg_save_param("var_f_param_chart", "LB=&amp;f=",
 "RB=&amp;k=","notfound=warning", "ord=all", LAST);

/*
If we are running a CSV report, obtain all required dynamic parameters. The
left and right boundaries of these are different than those obtained when
running a report containing charts or running a PDF report.
*/
if (strcmp(lr_eval_string("{DataCheck}"),"application/vnd.ms-excel") == 0) {
	web_reg_save_param("var_b_action_csv", "LB=b_action=",
	 "RB=&f=","notfound=warning", LAST);
	web_reg_save_param("var_f_param_csv", "LB=&f=",
	 "RB=&k=","notfound=warning", LAST);
	web_reg_save_param("var_k_param_csv", "LB=&k=",
	 "RB=&s=","notfound=warning", LAST);
	web_reg_save_param("var_s_param_csv", "LB=&s=",
	 "RB=&did=","notfound=warning", LAST);
	web_reg_save_param("var_did_param_csv", "LB=&did=",
"RB=&viewer","notfound=warning", LAST);
}

web_reg_save_param("var_ui.objectClass", "LB=ui.objectClass\": \"", "RB=\"", LAST);
lr_save_string("", "var_chart_Src_param");
	
/*
Store the searchPathSingleObject and modelID parameters which are used for
the Authored Drill Through Test Cases. Also capture the Dispatcher URI which
is used in the async conversations
*/
web_reg_save_param("var_searchPathSingleObject", "LB=bus:searchPathSingleObject\\\">
storeID(&quot;", "RB=&quot;)<\\/item>", "NotFound=Warning", LAST);

web_reg_save_param("var_modelID", "LB=xsi:type=\\\"bus:searchPathSingleObject\\\">
storeID(&quot;", "RB=&quot;)/model[last()]", "NotFound=Warning", LAST);

web_reg_save_param("var_dispatcherURI", "LB=dispatcherURI\": \"", "RB=\", \"enc",
 "notfound=warning", LAST);

// Capture the ui.object parameter which is now used in our Async conversation.
web_reg_save_param("var_ui_object", "LB=<input type=\"hidden\" name=\"ui.object\"
 value=\"", "RB=\"/>\n", LAST);
	
// Execute report by clicking on the link defined by reportName
web_link("ClickReportNameLink",
	"Text={reportName}",
	"Snapshot=t6.inf",
	LAST);

/*
Since we've changed getAsyncInfo() such that we don't force an error if we
are unable to obtain an m_tracking, ui.conversation, etc.. (due to our
discovery with CSV reports), we should now validate that the user has
received these parameters if they aren't running a CSV report.  If they
haven't, force a failure.
*/
if((strcmp(lr_eval_string("{DataCheck}"), "application/vnd.ms-excel") != 0) &&
 (strcmp(lr_eval_string("{var_m_tracking}"), "") == 0) &&
 (strcmp(lr_eval_string("{var_ui.conversation}"), "") == 0)){
		lr_message("ERROR: m_tracking or var_ui.conversation not found.
		  Their values are:  m_tracking: %s, ui_conversation: %s", 
	lr_eval_string("{var_m_tracking}"), 	lr_eval_string("{var_ui.conversation}"));
	lr_exit(LR_EXIT_ITERATION_AND_CONTINUE, LR_FAIL);
}

/*
This is a verification point to see if we've received the correct number of
charts.	If we've received less charts than we should have, we now force a
failure and continue on to the next action.
*/
if (atoi(lr_eval_string("{var_f_param_chart_count}"))
 < atoi(lr_eval_string("{successfulReport}"))) {
	if(atoi(lr_eval_string("{var_f_param_chart_count}")) > 0) {
	lr_message("Error: Did not return expected number of charts var_f_param_chart_count
	%s does not equal successfulReport %s try using image/png as a datacheck",
	lr_eval_string("{var_f_param_chart_count}"),lr_eval_string("{successfulReport}"));
		lr_exit(LR_EXIT_ITERATION_AND_CONTINUE, LR_FAIL);
	}
}

/*
PDF and HTML output will be sent directly to the browser if it is ready in less than 3
 seconds. CSV output won't be sent directly. Instead a URL to the location of the CSV
 output is sent. In the event that a CSV is completed in less than 3 secs we have to
 issue the URL request to get the CSV and NOT go into async. An error page should not
 lead to async since the web_reg_save_params should throw exceptions.  If we are running
 a CSV report, no ui.coversation or m_tracking will be returned if the report has
 completed in less than 3 seconds.  If this is the case, call getCSVReportOutput(),
 otherwise enter Async()
*/
if ((strcmp(lr_eval_string("{var_ui.conversation}"), "") == 0) &&
 (strcmp(lr_eval_string("{var_m_tracking}"), "") == 0) &&
 (stricmp(lr_eval_string("{DataCheck}"), "application/vnd.ms-excel")==0))	{
	// Substitute the ‘f’, ‘k’, ‘s’ and ‘did’ parameters obtained such that we
	// can invoke getCSVReportOutput();
	lr_save_string(lr_eval_string("{var_b_action_csv}"), "var_b_action");
	lr_save_string(lr_eval_string("{var_f_param_csv}"), "var_f_param");
	lr_save_string(lr_eval_string("{var_k_param_csv}"), "var_k_param");
	lr_save_string(lr_eval_string("{var_s_param_csv}"), "var_s_param");
	lr_save_string(lr_eval_string("{var_did_param_csv}"), "var_did_param");
	if (atoi(lr_eval_string("{successfulReport}"))==0) {
   	if (atoi(lr_eval_string("{FileSize}"))>0){
			getExcelReportOutput();
		}
		else {		
			getCSVReportOutput();  // get CSV output
		}
	}
}
else if ((atoi(lr_eval_string("{successfulReport}"))==0)) {
	reportWait(lr_eval_string("{contentCheck}"));  // start async
}

return;
}

Run Report for Cognos BI 10.2 and 10.2.1

The internal process of retrieving charts, CSV and PDF in Cognos BI 10.2 and 10.2.1 are all handled by the getResourceURIs() function to get the required URL to retrieve the output as opposed to individual functions for each. Once the getResourceURIs() are found, they are retrieved using the getResource() function to retrieve the output. The async process logic and content check are still applicable to wait for report to complete. The code for the getResourceURIs() and getResource() functions can be found in Appendix C.

void run_Report(char *reportName, char *contentCheck)
{
	lr_save_string(lr_eval_string(reportName), "reportName");
	 // turn reportName into LoadRunner parameter
	lr_save_string(lr_eval_string(contentCheck), "contentCheck");
	 // turn contentCheck into LoadRunner parameter

	getAsyncInfo(); // gather dynamic server-client communication info

	// check for a successful PDF or HTML report
	web_reg_find("Text={contentCheck}", "SaveCount=successfulReport", "Search=All", LAST);


	// If we obtain a PDF, CSV, or Report Containing a chart,
    // grab the URL to the resource.
	getResourceURIs();

	web_reg_save_param("var_ui.objectClass", "LB=ui.objectClass\": \"", "RB=\"", LAST);


	// Store the searchPathSingleObject and modelID parameters which are used for the
	// Authored Drill Through Test Cases.
	// Also capture the Dispatcher URI which is used in the RSVP async conversation
	web_reg_save_param("var_searchPathSingleObject", "LB=bus:searchPathSingleObject\\\"
	 >storeID(&quot;", "RB=&quot;)<\\/item>", "NotFound=Warning", LAST);
	web_reg_save_param("var_modelID", "LB=xsi:type=\\\"bus:searchPathSingleObject\\\"
	 >storeID(&quot;", "RB=&quot;)/model[last()]", "NotFound=Warning", LAST);
	web_reg_save_param("var_dispatcherURI", "LB=dispatcherURI\": \"", "RB=\", \"enc",
	 "notfound=warning", LAST);

	// Capture the ui.object parameter which is used in our Async conversation 
	web_reg_save_param("var_ui_object", "LB=<input type=\"hidden\" name=\"ui.object\"
	 value=\"", "RB=\"/>\n", LAST);
	


	/* execute report by clicking on the link defined by reportName
	   NOTE: This web_link generates two more web_URL requests. Because those two
	   requests are redundant, they are not included in the header, but are captured when 
	   verifying scripts through Fiddler  and Loadrunner.
	*/
	web_link("ClickReportNameLink",
		"Text={reportName}",
		"Snapshot=t6.inf",
		LAST);

	/* Since we've changed getAsyncInfo() such that we don't force an error if we are 
	   unable to obtain an m_tracking, ui.conversation, etc.., we should now validate 
	   that the user has received these parameters if they aren't running a CSV report.  
	   If they haven't, force a failure.
	*/

	if((strcmp(lr_eval_string("{DataCheck}"), "application/vnd.ms-excel") != 0) &&
	 (strcmp(lr_eval_string("{var_m_tracking}"), "") == 0) &&
	 (strcmp(lr_eval_string("{var_ui.conversation}"), "") == 0)){
		lr_message("ERROR: m_tracking or var_ui.conversation not found.  Their values are:
		 m_tracking: %s, ui_conversation: %s", lr_eval_string("{var_m_tracking}"),
		 lr_eval_string("{var_ui.conversation}"));
		lr_exit(LR_EXIT_ITERATION_AND_CONTINUE, LR_FAIL);
	}


	// If a CSV report is being run...
   if ((strcmp(lr_eval_string("{var_ui.conversation}"), "") == 0) &&
    (strcmp(lr_eval_string("{var_m_tracking}"), "") == 0) &&
    (stricmp(lr_eval_string("{DataCheck}"), "application/vnd.ms-excel")==0))
   {
	   if (atoi(lr_eval_string("{var_resource_URI_param_count}")) <
	    atoi(lr_eval_string("{successfulReport}"))){
			lr_message("Error: Did not return expected report.  Ensure your content check
			 is correct");
		   	lr_exit(LR_EXIT_ITERATION_AND_CONTINUE, LR_FAIL);
	   }else{
		   getResource();
	   }
	} 

	if ((atoi(lr_eval_string("{successfulReport}"))==0) &&
	 (strcmp(lr_eval_string("{var_asyncStatus}"), "complete") == 0))
	{
		lr_message("Error: Did not return the expected report.  Ensure your content check
		 is correct");
		lr_exit(LR_EXIT_ITERATION_AND_CONTINUE, LR_FAIL);
		
	}

   	if (atoi(lr_eval_string("{successfulReport}"))==0){
		reportWait(lr_eval_string("{contentCheck}"));  // start async
	}

	return;
}

The parameter contentCheck is a piece of information that is found on Page 1 of the desired report and should be data that is extremely unlikely to be found anywhere else but as data in the desired report.

Code for “Handling the async conversation programmatically”

The code that follows is an example of how one could programmatically tell LoadRunner how to handle an async conversation in IBM Cognos 10. It tells LoadRunner to issue an ui.action=wait response to IBM Cognos 10’s status of stillWorking (assuming that the report execution is still in progress). As soon as the status is anything other than stillWorking the loop can be exited.

The following code shows the reportWait() procedure for IBM Cognos 10.1 using individual procedures to retrieve PDF, charts and CSV report,

/*
void reportWait(char *contentCheck) {

	int chart_iterator = 1;
	//Used to iterate through the number of charts which are found.
	char tmp[10];			  
	//This is used to index the array of var_chart_Src parameters.
	char buffer[500];		  
	//Temporary buffer used to store the current var_chart_Src value.
	char chart_status = 0;    
	// Set to '0' if we encounter an error condition where we do not receive a number of
	// 'f', 'k', 's', and 'did' parameters equal to the number of charts we need to 
	// obtain. Initialize the status to '0' to indicate a failure.

	//Initialize buffers for use in determining the link to the Image/PNG in CM.
	strcpy(buffer, "");
	strcpy(tmp, "");

	messageEnable();

	if(LRMessage_enabled)
			lr_message("async reportWait protocol has started");

	lr_save_string(lr_eval_string(contentCheck), "DataCheck"); 
	// turn contentCheck into LoadRunner parameter
/* Since the report isn't ready tell the IBM Cognos 10 server that we are "waiting". Keep
 responding to each server status update as long as the server keep responding with the
 status "stillWorking". The loop is exited when a) the status is "complete" or b) an
 error page is displayed.
*/
do	{
		sendAsyncWaitResponse();
}
while(atoi(lr_eval_string("{statusWaiting}"))==1);

/*
PDFs are a special case.  The PDF output is not pushed to the client.  The client must 
get it.  However, the location of the PDF is a URL that is found in the server's status 
update when it responds with status = "complete" when running a report with PDF output. 
This is a similar case with Chart reports, we must retrieve the PNG file upon completion 
from the Server.
*/

/*
The following condition evaluates to true if:
A) The report has not been successfully found yet.  This means we've obtained an 'f', 
'k', 's', and 'did' parameter required to obtain a PDF, or we've received an error. 
HTML report output will be found since it's pushed to the client and will result in this 
condition evaluating to False.
B) We haven't obtained the charts yet for the executing report.
*/
if (atoi(lr_eval_string("{successfulReport}"))==0) {
	// If we are obtaining a PDF report, we must call getPDFReportOutput().
	if ((stricmp("application/pdf", lr_eval_string("{DataCheck}")) == 0)) {
			/*		
		Since our 'f', 'k', 's', and 'did' parameters are captured as ordinals
		(an array of parameters), we must correctly substitute the first
		occurrence of each back into one parameter since we are dealing with
		one and only one PDF in this case.
		*/
		lr_save_string(lr_eval_string("{var_f_param_1}"), "var_f_param");
		lr_save_string(lr_eval_string("{var_k_param_1}"), "var_k_param");
		lr_save_string(lr_eval_string("{var_s_param_1}"), "var_s_param");
		lr_save_string(lr_eval_string("{var_did_param_1}"), "var_did_param");
		getPDFReportOutput();
	}
	// If we've executed a report containing charts.....
	else if(stricmp(lr_eval_string("{DataCheck}") , "image/png") == 0) {
		/*
		This step is used to handle an erroneous condition in which we may
		not have obtained any f, k, s, or did parameters, yet the report we
		are executing does contain several charts. If this is the case, set
		chart_status to zero to force an error.
		*/
		If (atoi(lr_eval_string("{var_f_param_count}")) == 0)
			chart_status = 0;
		if (atoi(lr_eval_string("{var_k_param_count}")) == 0)
			chart_status = 0;
		if (atoi(lr_eval_string("{var_s_param_count}")) == 0)
			chart_status = 0;
		if (atoi(lr_eval_string("{var_did_param_count}")) == 0)
			chart_status = 0;

	/*
	Verify that we have obtained the correct number of f, k, s, and did
	parameters equal to the number of charts we need to obtain. For
	example, if we are running a report which has 6 charts, we expect to
	obtain four unique parameters (f, k, s, and did) per chart.
		*/
if (atoi(lr_eval_string("{var_f_param_count}")) ==
 atoi(lr_eval_string("{var_k_param_count}"))) {
if (atoi(lr_eval_string("{var_f_param_count}")) ==
 atoi(lr_eval_string("{var_s_param_count}")))
if (atoi(lr_eval_string("{var_f_param_count}")) ==
 atoi(lr_eval_string("{var_did_param_count}")))
				      chart_status = 1;
		}

		/*
		If we've obtained the correct number of charts, continue on to obtain
		All of the charts by calling getChartOutput(). Since we don't need to
		pass a buffer containing the URL into getChartInput, simply pass an
		empty string in as an argument.
		*/
		if (chart_status == 1) {
			// This loop will iterate through the number of charts that it finds
			// and call getChartOutput() for each.
			while (chart_iterator<=atoi(lr_eval_string("{var_f_param_count}"))){
				itoa(chart_iterator, tmp, 10);
				sprintf(buffer, "{var_f_param_%d}", chart_iterator);
				lr_save_string(lr_eval_string(buffer), "var_f_param");
				sprintf(buffer, "{var_k_param_%d}", chart_iterator);
				lr_save_string(lr_eval_string(buffer), "var_k_param");
				sprintf(buffer, "{var_s_param_%d}", chart_iterator);
				lr_save_string(lr_eval_string(buffer), "var_s_param");
				sprintf(buffer, "{var_did_param_%d}", chart_iterator);
				lr_save_string(lr_eval_string(buffer), "var_did_param");
				getChartOutput("");
				chart_iterator++;
			}
		}
		else {
			lr_message("Didn't obtain required number of 'f', 'k', 's',
			 and 'did' parameters, ABORTING...");
			lr_exit(LR_EXIT_MAIN_ITERATION_AND_CONTINUE, LR_AUTO);
		}
	}
	else if ((stricmp(lr_eval_string("{DataCheck}"),"application/vnd.ms-excel") == 0)
	 && ( strlen(lr_eval_string("{runOption}")) == 0 )) {
		// Substitute the f, k, s, and did parameters obtained such that we can
		// invoke getCSVReportOutput();
		if (strlen(lr_eval_string("{FileSize}"))>0) {			
			getExcelReportOutput();
		}
	   else {
			getCSVReportOutput();
		}
	}
	// Handle CSV/Excel report output
	else if (strcmp(lr_eval_string("{runOption}"), "CSV") == 0) {
		// We are running CSV report output so call getCSVReportOutput to fetch
		// the resource from Content Manager
		getCSVReportOutput(); // then
	}
else if ((strcmp(lr_eval_string("{runOption}"), "spreadsheetML") == 0) 
 || (strcmp(lr_eval_string("{runOption}"), "XLWA") == 0 )
 || (strlen(lr_eval_string("{FileSize}"))>0)) {   
		// We are running Excel report output so call getExcelReportOutput to
		// fetch the resource from Content Manager
		getExcelReportOutput();
	}

	/*
	The following else condition evaluates to true if a) the report was not
	found due to an error page and/or b) the PDF "gd" value was not found
	and/or the HTML report's DataCheck is incorrect.
	*/
	else {
		lr_fail_trans_with_error("REPORT OUTPUT ERROR. If this is an HTML Report please
		 validate your DataCheck.");
		lr_error_message("REPORT OUTPUT ERROR. If this is an HTML Report please validate
		 your DataCheck.");
		lr_exit(LR_EXIT_ITERATION_AND_CONTINUE , LR_FAIL);
	}
}
return;

The following code shows the reportWait() procedure for IBM Cognos BI 10.2 and 10.2.1 using the getResource() procedure to retrieve PDF, charts and CSV report.

/*
Name: reportWait

Arguments: This function accepts one arguments.
	contentCheck = some piece of data that positively identifies a successful report
	 navigation.
Parameters:  No parameter files are used in this procedure.

Description: This procedure will click a nav link in Cognos Connection to start report
 execution.  If the report is lengthy (>3 secs server time to complete) start the
 async wait protocol.
*/
void reportWait(char *contentCheck) {

	messageEnable();

	if(LRMessage_enabled)
			lr_message("async reportWait protocol has started");

	lr_save_string(lr_eval_string(contentCheck), "DataCheck");
	 // turn contentCheck into LoadRunner parameter

	// since the report isn't ready tell the Cognos10 server that we are "waiting".
	// keep responding to each server status update as long as the server keep responding
	// with the status "stillWorking"
	do
	{
		sendAsyncWaitResponse();
	}
	// loop is exited when a) the status is "complete" or b) an error page is displayed.
	while(atoi(lr_eval_string("{statusWaiting}"))==1);


	// If we're obtaining charts, a PDF, or an Excel content type
	if (atoi(lr_eval_string("{successfulReport}"))==0)
	{

		// This step is used to handle an erroneous condition in which we don't hav
		// the report we are executing does contain several charts.  If this is the case,
		// set chart_status to zero to force an error.
		if (atoi(lr_eval_string("{var_resource_URI_param_count}")) > 0){
			// If we've obtained the correct number of charts, continue on to obtain all
			// of the charts by calling
			// getResource. 
			getResource();
		}
		else{
		
			lr_message("Error: Did not return the Expected Report, please validate
			 Content Check");
			lr_exit(LR_EXIT_ITERATION_AND_CONTINUE, LR_FAIL);
		}
	}
		
	return;
}

The code for the sendAsyncWaitResponse() procedure can be found in Appendix A.

Code for “5. Click on the Return link to exit Cognos Viewer and return to Cognos Connection”

Within IBM Cognos Viewer, when the user is finished viewing the report they click the Return link to exit IBM Cognos Viewer and return to the IBM Cognos Connection portal. Clicking the link is a two step procedure.

  1. Load the IBM Cognos Connection folder the user executed the report from.
  2. Signal to the IBM Cognos 10 Report Service that the user is done with the report. This step will allow the Report Service to clean up resources it had dedicated to this report.
// Return to the IBM Cognos Connection folder
web_url("ReturnToCognosConnection",
	"URL=http://{WebServer}{Gateway}?b_action=xts.run&m=portal/cc.xts&
		m_folder={returnFolder_guid}",
	"Resource=0",
	"RecContentType=text/html",
	"Referer=",
	"Snapshot=t14.inf",
	"Mode=HTML",
	LAST);

// Signal IBM Cognos 10 that the user is finished with the report
web_submit_data("Release", 
	"Action=http://{WebServer}{Gateway}", 
	"Method=POST", 
	"RecContentType=application/xml", 
	"Referer=", 
	"Snapshot=t9.inf", 
	"Mode=HTML", 
	ITEMDATA, 
	"Name=b_action", "Value=cognosViewer", ENDITEM, 
	"Name=cv.responseFormat", "Value=successfulRequest", ENDITEM, 
	"Name=ui.primaryAction", "Value=run", ENDITEM, 
	"Name=ui.objectClass", "Value=report", ENDITEM, 
	"Name=ui.action", "Value=release", ENDITEM, 
	"Name=m_tracking", "Value={var_m_tracking}", ENDITEM, 
			LAST);

Code for “6. Logoff”

The last step is to log off IBM Cognos 10. This code emulates the user clicking the Log off link in IBM Cognos Connection.

// Log the user off the IBM Cognos 10 system
web_url("LogOff",
	"URL=http://{WebServer}{Gateway}?b_action=xts.run&m=portal/logoff.xts&
		h_CAM_action=logoff",
	"Resource=0",
	"RecContentType=text/html",
	"Referer=",
	"Snapshot=t14.inf",
	"Mode=HTML",
	LAST);

Appendix A - The getAsyncInfo() function

This Appendix contains the code for the getAsyncInfo() procedure which will capture the initial async information returned from IBM Cognos 10 BI with respect to the current running report execution. There are some small differences in getAsyncInfo() between IBM Cognos BI versions 10.1 and 10.2.x. Both are listed here.

getAsyncInfo() for IBM Cognos BI 10.1

/*
Name: getAsyncInfo
Description: procedure that looks for the necessary dispatcher tracking,
conversation and async info for interactive reporting.  Works for completely
rendered HTML pages.  Since these parameters are not returned when running a
CSV report that completes in less than 3 seconds (does not enter async()),
we must set notfound=warning and check to see if we have found them later
on.
*/
void getAsyncInfo()
{
web_reg_save_param("var_actionState", "LB=action_state\": \"",
 "RB=\"","notfound=warning", LAST);
web_reg_save_param("var_executionParameters", "LB=parameters\": \"",
 "RB=\"", "notfound=warning", LAST);
web_reg_save_param("var_ui.conversation", "LB=conversation\": \"",
 "RB=\"","notfound=warning", LAST);
web_reg_save_param("var_m_tracking", "LB=tracking\": \"",
 "RB=\"","notfound=warning", LAST);

	// This breaks runReportWithOptions, since you only need to grab the CAF
	// context id once, at logon.
	if (stricmp(lr_eval_string("{runOption}"),"{runOption}") == 0) {
		web_reg_save_param("var_ui.cafcontextid", "LB=caf\": \"",
		"RB=\"","notfound=warning", LAST);
	}

web_reg_save_param("var_asyncStatus", "LB=\"status\": \"",
 "RB=\"","notfound=warning", LAST);
	return;
}

getAsyncInfo() for IBM Cognos BI 10.2 and 10.2.1

/*
Name: getAsyncInfo
Description: procedure that looks for the necessary dispatcher tracking,
conversation and async info for interactive reporting.  Works for completely
rendered HTML pages.  Since these parameters are not returned when running a
CSV report that completes in less than 3 seconds (does not enter async()),
we must set notfound=warning and check to see if we have found them later
on.
void getAsyncInfo()
{
	web_reg_save_param("var_actionState", "LB=ActionState\": \"",
	 "RB=\"","notfound=warning", LAST);
	web_reg_save_param("var_executionParameters", "LB=Parameters\": \"",
	 "RB=\"", "notfound=warning", LAST);
	web_reg_save_param("var_ui.conversation", "LB=Conversation\": \"",
	 "RB=\"","notfound=warning", LAST);
	web_reg_save_param("var_m_tracking", "LB=Tracking\": \"",
	 "RB=\"","notfound=warning", LAST);
	web_reg_save_param("var_objectPermissions", "LB=objectPermissions\": \"",
	 "RB=\",","notfound=warning", LAST);


	// This breaks runReportWithOptions, since you only need to grab the caf context id
	// once, at logon.
	if (stricmp(lr_eval_string("{runOption}"),"{runOption}") == 0) {
		web_reg_save_param("var_ui.cafcontextid", "LB=CAFContext\": \"",
		 "RB=\"","notfound=warning", LAST);
	}

	web_reg_save_param("var_asyncStatus", "LB=Status\": \"", "RB=\"","notfound=warning",
	 LAST);

	return;
}

The following is the code for getAsyncInfo_HTMLFragment() which is used capture any subsequent async information returned from the IBM Cognos 10 server with respect to the currently running report execution for a report that has entered async. The reason that the we use the getAsyncInfo_HTMLFragment() procedure instead of the getAsyncInfo() procedure is because when the report enters async, the left and right boundaries used in the web_reg_save_param function need to be updated.

/*
Name: getAsyncInfo_HTMLFragment
Description: Procedure that looks for the necessary dispatcher tracking,
conversation and async info for interactive reporting.  Works for grabbing
async info from server status messages sent as an HTML Fragment. Since these
parameters are not returned when running a CSV report that completes in less
than 3 seconds (does not enter async()), we must set notfound=warning and
check to see if we have found them later on.
*/
void getAsyncInfo_HTMLFragment()
{
web_reg_save_param("var_actionState", "LB=action_state": "",
 "RB="","notfound=warning", LAST);
web_reg_save_param("var_executionParameters", "LB=parameters": "",
 "RB="","notfound=warning", LAST);
web_reg_save_param("var_ui.conversation", "LB=conversation": "",
 "RB="","notfound=warning", LAST);
web_reg_save_param("var_m_tracking", "LB=tracking": "",
 "RB="","notfound=warning", LAST);
web_reg_save_param("var_ui.cafcontextid", "LB=caf": "",
 "RB="","notfound=warning", LAST);
web_reg_save_param("var_asyncStatus", "LB="status": "",
 "RB="","notfound=warning", LAST);
return;
}

Appendix B – The sendAsyncWaitReponse() function

The procedure sendAsyncWaitResponse() sends a wait response to IBM Cognos 10 when it receives a status of stillWorking for a longer running report that has entered async. Since textual report data is pushed to IBM Cognos Viewer when the status reaches complete, the report validation must be included in this section of code.

The sendAsyncWaitResponse() for IBM Cognos 10.1 uses individual procedures to retrieve PDF, chart or CSV report output.

/*
Name: sendAsyncWaitResponse
Arguments: This function accepts no arguments.
Parameters:  No parameter files are used in this procedure.
Description: This procedure responds to the server's "stillWorking" status
with a "wait" response.  It also handles the situations where IBM Cognos
Viewer debug logging is enabled.
*/
void sendAsyncWaitResponse()
{
	// track dynamic communication info between the client and server
	getAsyncInfo_HTMLFragment();

	// validates successful async communication
web_reg_find("Text=&quot;status&quot;: &quot;stillWorking",
 "SaveCount=statusWaiting", "Search=All", LAST);

	web_reg_find("Text=<xml><state>{ &quot;status&quot;: &quot;",
 LAST);

	if(LRMessage_enabled)		// debug message
		lr_message("INFO: m_tracking: %s", lr_eval_string("{var_m_tracking}"));

	// Capture all required dynamic parameters in order to obtain a PDF report
	// or chart
if((strcmp(lr_eval_string("{DataCheck}"), "application/pdf") == 0) ||
 (strcmp(lr_eval_string("{DataCheck}"), "image/png") == 0)) {
web_reg_save_param("var_b_action", "LB=b_action=", "RB=&amp;f=","notfound=warning",
 LAST);
web_reg_save_param("var_f_param", "LB=&amp;f=", "RB=&amp;k=","notfound=warning",
 "ord=all", LAST);
web_reg_save_param("var_k_param", "LB=amp;k=", "RB=&amp;s=","notfound=warning",
 "ord=all", LAST);
web_reg_save_param("var_s_param", "LB=&amp;s=", "RB=&amp;did=","notfound=warning",
"ord=all", LAST);
	}

	/*
	Capture all required dynamic parameters in order to obtain a CSV/Excel
report.  The left and right bounadaries of these are different when
compared to running a report containing charts or running a PDF report.
*/
	// Handle various Microsoft report output options. This code
	// is only for runReportWithOptions
	if ((strcmp(lr_eval_string("{runOption}"), "CSV")  == 0) ||
		 (strcmp(lr_eval_string("{runOption}"), "spreadsheetML")  == 0) ||
		 (strcmp(lr_eval_string("{runOption}"), "XLWA") == 0) ||
		 (strcmp(lr_eval_string("{DataCheck}"),"application/vnd.ms-excel")==0))
	{
		// If 1 of 3 Microsoft report output types, grab parameters
		// for CSV/Excel report
		if(LRMessage_enabled)		// debug message
lr_message("INFO: fetching dynamic params for excel/CSV report output: %s",
 lr_eval_string("{runOption}"));
		
web_reg_save_param("var_b_action", "LB=b_action=", "RB=&f=","notfound=warning", LAST);
web_reg_save_param("var_f_param", "LB=&f=", "RB=&k=","notfound=warning", LAST);
web_reg_save_param("var_k_param", "LB=&k=", "RB=&s=","notfound=warning", LAST);
web_reg_save_param("var_s_param", "LB=&s=", "RB=&did=","notfound=warning", LAST);
web_reg_save_param("var_did_param", "LB=&did=", "RB=&viewer","notfound=warning",
 LAST);
	}

	/*
	The "did" parameter has slightly different boundaries between PDFs and
	Charts.  If we are looking for a chart, then we must change the left and
	right boundaries.
	*/
	if(stricmp(lr_eval_string("{DataCheck}"), "image/png") == 0)
web_reg_save_param("var_did_param", "LB=&amp;did=", "RB=\" width=",
 "notfound=warning","ord=all", LAST);
	else
web_reg_save_param("var_did_param", "LB=&amp;did=", "RB=&amp;viewer",
 "notfound=warning","ord=all", LAST);

	// Store the searchPathSingleObject and modelID parameters which are used
	// for the Authored Drill Through Test Cases
web_reg_save_param("var_searchPathSingleObject",
 "LB=bus:searchPathSingleObject\\\">storeID(&quot;",
 "RB=&quot;)<\\/item>", "NotFound=Warning", LAST);

web_reg_save_param("var_modelID",
 "LB=xsi:type=\\\"bus:searchPathSingleObject\\\">storeID(&quot;",
 "RB=&quot;)/model[last()]", "NotFound=Warning", LAST);
		
	// Check for the presence of a completed HTML report.
web_reg_find("Text={contentCheck}", "SaveCount=successfulReport", "Search=All", LAST);

	/*
	This is the client's "waiting" response to the server's "stillWorking"
	status update If IBM Cognos Viewer debugging is enabled then run the
	WaitResponse with cv.debugDirectory
	*/
	if (atoi(lr_eval_string("{cvDebugEnabled}")) > 0) {
		web_custom_request("WaitResponse", 
			"URL=http://{WebServer}{Gateway}", 
			"Method=POST", 
			"Resource=0", 
			"RecContentType=text/plain", 			
			"Snapshot=t75.inf", 
			"Mode=HTML", 
			"Body=cv.ignoreState=true"
			"&b_action=cognosViewer"
			"&cv.id=_NS_"
			"&ui.action=wait"
			"&ui.object={var_ui_object}"
			"&cv.actionState={var_actionState}"
			"&ui.primaryAction=run"
			"&errURL={var_errURL}"
			"&ui.objectClass={var_ui.objectClass}"
			"&executionParameters={var_executionParameters}"
			"&ui.conversation={var_ui.conversation}"
			"&m_tracking={var_m_tracking}"
			"&ui.cafcontextid={var_ui.cafcontextid}"
			"&cv.catchLogOnFault=true"
			"&cv.responseFormat=data"			
			"&cv.debugDirectory={UserID}_{IterationNumber}_{ReportName}",
			LAST);
	}
	else {
		web_custom_request("WaitResponse", 
			"URL=http://{WebServer}{Gateway}", 
			"Method=POST", 
			"Resource=0", 
			"RecContentType=text/plain", 
			"referer="
			"Snapshot=t75.inf", 
			"Mode=HTML", 
			"Body=cv.ignoreState=true"
			"&b_action=cognosViewer"
			"&cv.id=_NS_"
			"&ui.action=wait"
			"&ui.object={var_ui_object}"
			"&cv.actionState={var_actionState}"
			"&ui.primaryAction=run"
			"&errURL={var_errURL}"
			"&ui.objectClass={var_ui.objectClass}"
			"&executionParameters={var_executionParameters}"
			"&ui.conversation={var_ui.conversation}"
			"&m_tracking={var_m_tracking}"
			"&ui.cafcontextid={var_ui.cafcontextid}"
			"&cv.catchLogOnFault=true"
			"&cv.responseFormat=data", 
			LAST);
	}
	return;
}

The sendAsyncWaitResponse() for IBM Cognos 10.2 and 10.2.1 uses the getResourceURIs() procedure to retrieve PDF, Chart and CSV.

/*
Name: sendAsyncWaitResponse
Arguments: This function accepts no arguments.
Parameters:  No parameter files are used in this procedure.
Description: This procedure responds to the server's "stillWorking" status with a "wait"
 response.  
*/
void sendAsyncWaitResponse()
{
	messageEnable();

	if(LRMessage_enabled)
			lr_message("AsyncWaitResponse from client");


	// track dynamic communication info between the client and server
	getAsyncInfo_HTMLFragment();

	// validates successful async communication
	web_reg_find("Text=m_sStatus&quot;: &quot;stillWorking",
	 "SaveCount=statusWaiting", "Search=All", LAST);
     
	// Capture all required dynamic parameters in order to obtain a PDF report or chart
	getResourceURIs();

	// Capture all required dynamic parameters in order to obtain a CSV/Excel report.  
	// The left and right boundaries
	// This code is only for runReportWithOptions


	// Store the searchPathSingleObject and modelID parameters which are used for the
	// Authored Drill Through Test Cases
	web_reg_save_param("var_searchPathSingleObject",
	 "LB=bus:searchPathSingleObject\\\">storeID(&quot;",
	 "RB=&quot;)<\\/item>", "NotFound=Warning", LAST);
	web_reg_save_param("var_modelID",
	 "LB=xsi:type=\\\"bus:searchPathSingleObject\\\">storeID(&quot;",
	 "RB=&quot;)/model[last()]", "NotFound=Warning", LAST);
		
	// checks for the presence of a completed HTML report.
	web_reg_find("Text={contentCheck}", "SaveCount=successfulReport", "Search=All", LAST);

	// this is the client's "waiting" response to the server's "stillWorking"
	// status update
	if(firstAsync == 0) {
	
		firstAsync = 1;
		
		web_custom_request("WaitResponse", 
			"URL=http://{WebServer}{Gateway}", 
			"Method=POST", 
			"Resource=0", 
			"RecContentType=text/plain", 
			"referer="
			"Snapshot=t75.inf", 
			"Mode=HTML",
			"Body=b_action=cognosViewer"
			"&cv.actionState={var_actionState}"
			"&cv.catchLogOnFault=true"
			"&cv.id=_NS_"
			"&cv.objectPermissions={var_objectPermissions}"
			"&cv.responseFormat=data"
			"&cv.showFaultPage=true"
			"&errURL={var_errURL_encoded}"
			"&executionParameters={var_executionParameters}"
			"&m_tracking={var_m_tracking}"
			"&ui.action=wait"
			"&ui.backURL={Gateway}%3Fb_action%3Dxts.run%26m%3Dportal/cc.xts%26m_folder
				%3D{returnFolder_guid}"
			"&ui.cafcontextid={var_ui.cafcontextid}" 
			"&ui.conversation={var_ui.conversation}"
			"&ui.object={var_ui_object}"
			"&ui.objectClass={var_ui.objectClass}"
			"&ui.primaryAction=run",
		LAST);
	}
	
	else {
	
		web_custom_request("WaitResponse", 
			"URL=http://{WebServer}{Gateway}", 
			"Method=POST", 
			"Resource=0", 
			"RecContentType=text/plain", 
			"referer="
			"Snapshot=t75.inf", 
			"Mode=HTML",
			"Body=b_action=cognosViewer"
			"&cv.actionState={var_actionState}"
			"&cv.catchLogOnFault=true"
			"&cv.responseFormat=data"
			"&cv.showFaultPage=true"
			"&errURL={var_errURL_encoded}"
			"&m_tracking={var_m_tracking}"
			"&ui.action=wait"
			"&ui.backURL={Gateway}%3Fb_action%3Dxts.run%26m%3Dportal/cc.xts%26m_folder
				%3D{returnFolder_guid}"
			"&ui.primaryAction=run",
		LAST);
		
	}
	
	return;
}

Appendix C: The getOutput() functions

This appendix lists the code to retrieve the output formats that are not automatically returned when a report is finished executing. With IBM Cognos BI 10.1, individual functions were used to get the different output format. With versions 10.2 and 10.2.1 these are covered by the getResource() functions. The functions that will be covered here are,

  • getPDFReportOutput()
  • getChartOutput()
  • getCSVReportOutput()
  • getExcelReportOutput()
  • getResourceURIs()
  • getResource()

getPDFReportOutput ()

As mentioned earlier in this document, PDF output is not pushed to the client if the output is not ready within 3 seconds - the client must retrieve it. When the server responds with a status of complete when running a report with PDF output, the response will be a URL that can be used to retrieve the PDF output. The getPDFReportOutput() function is used to retrieve the PDF using the URL from the server response.

/*
Name: 		 getPDFReportOutput()
Arguments:	 This function accepts no arguments.
Parameters:  No parameter files are used in this procedure.
Description: This procedure sends the URL to IBM Cognos 10 to get the completed PDF
 report output.
*/
void getPDFReportOutput()
{
	web_reg_find("Text={DataCheck}","Search=All", LAST);

// URL to get completed PDF output from Cognos10
	web_url("GetPDFOutput",	"URL=http://{WebServer}{Gateway}?b_action={var_b_action}&
		f={var_f_param}&k={var_k_param}&s={var_s_param}&did={var_did_param}&viewer=true",
		"TargetFrame=",
		"Resource=1",
		"RecContentType=application/pdf",
		"Referer=",
		LAST);
	return;
}

getChartOutput ()

When running a report containing charts, the charts are not pushed to the client. They must be retrieved from the server upon completion using the getChartOutput() function. This function uses the URL that is provided when the server responds with a status of complete.

/*
Name: getChartOutput
Arguments: buffer - a string containing the URL to the resource in CM.  This is used only
 for HTML Views.
Parameters:  No parameter files are used in this procedure.
Description: This procedure sends the URL to IBM Cognos 10 to get the completed Chart
 report.
*/
void getChartOutput(char* buffer)
{
	char* encStr;		// temp variable for manipulating string
	char* position; // variable for designating what position in original
							// string the "search" string is found
	int numCharts = 0; 

	// If we are obtaining charts from a view
	if (strcmp(lr_eval_string("{var_chart_Src_param}"), "") != 0) { 
		// URL from IBM Cognos 10 must be encoded correctly.  Must decode
		// before sending URL
		  encStr = lr_eval_string(buffer);

		// Replace "&amp" with "&", ";" with "", and "&apos" with ""
		// Loop until "&amp", ";", and "&apos" are not found in the string
		// defined by var_chart_Src
		do	{
			lr_log_message("%s", encStr);
			encStr = replace_str(encStr,"&amp","&");
			encStr = replace_str(encStr,";","");
			encStr = replace_str(encStr,"&apos","");
		}
while((position = (char*)strstr(encStr, "&amp")) ||
 (position = (char*)strstr(encStr, ";")) ||
 (position = (char*)strstr(encStr, "&apos")));

		// convert properly formatted string to a LoadRunner parameter
		lr_save_string(encStr, "var_chart_Src_param");	

		// data check to validate successful return of a Chart report
		web_reg_find("Text=image/png", "SaveCount=SuccessfulChart", "Fail=NotFound",
		 "Search=All", LAST);
				
	// URL to get completed Chart output from Cognos10
		web_url("GetChartOutput",
	"URL=http://{WebServer}{Gateway}?SM=query&search={var_chart_Src_param}",
			"TargetFrame=",
			"Resource=1",
			"RecContentType=image/png",
			"Referer=",
			LAST);
	}
	else { 	// If we are obtaining charts from an interactive report.
		web_reg_find("Text=image/png","SaveCount=SuccessfulChart",
		"Fail=NotFound", "Search=All", LAST);
		// URL to get completed Chart output from IBM Cognos 10
		web_url("GetChartOutput", "URL=http://{WebServer}{Gateway}?b_action={var_b_action}&
				f={var_f_param}&k={var_k_param}&s={var_s_param}&did={var_did_param}",
				"TargetFrame=",
				"Resource=1",
				"RecContentType=image/png",
				"Referer=",
				LAST);
	}
	return;
}

getCSVReportOutput ()

When running a report in CSV, the output of the report must be retrieved from the server upon completion using the getCSVOutput() function. This function uses the URL in the server response.

/*
Name: getCSVReportOutput
Arguments: This function accepts no arguments.
Parameters:  No parameter files are used in this procedure.
Description: This procedure sends the URL to IBM Cognos 10 to get the completed CSV
 report output.
*/
void getCSVReportOutput()
{

web_reg_find("Text={contentCheck}", "SaveCount=successfulReport", "Search=All", LAST);

// URL to get completed CSV output from IBM Cognos 10
web_url("GetCSVOutput", "URL=http://{WebServer}{Gateway}?b_action={var_b_action}&
f={var_f_param}&k={var_k_param}&s={var_s_param}&did={var_did_param}&
viewer=true",
		"TargetFrame=",
		"Resource=1",
		"RecContentType=application/vnd.ms-excel"
		"Referer=",
		LAST);

// Validate that the correct data check was found
if((atoi(lr_eval_string("{successfulReport}"))== 0)){ // If not fail out
lr_error_message("Data Validation failed!  %s was not found.",
 lr_eval_string("{contentCheck}"));
	lr_exit(LR_EXIT_ITERATION_AND_CONTINUE, LR_FAIL);
}

return;
}

getExcelReportOutput ()

When running a report for Excel, the output of the report must be retrieved from the server upon completion using the getExcelReportOutput() function.

/*
	Name: getExcelReportOutput
	Arguments: This function accepts no arguments.
	Parameters:  No parameter files are used in this procedure.
	Description: This procedure sends the URL to Cognos10 to get the completed Excel
	 report output.
*/
void getExcelReportOutput()
{
	int var_fileSize, var_fileSizeCheck, temp;

	// Check for a valid data check, keep track of the count
	// We need this count later to indicate that we got the report
	
	web_reg_find("Text={contentCheck}", "SaveCount=successfulRunReportCount",
	 "Fail=NotFound", "Search=All", LAST);

	//save the file size in bytes (the saved parameter will be a string)
	web_reg_save_param("var_fileSizeChar", "LB=content-length: ", "RB=\r\n", LAST);

	// URL to get completed Excel output from Cognos10
	web_url("GetExcelOutput",
		"URL=http://{WebServer}{Gateway}?b_action={var_b_action}&f={var_f_param}&
k={var_k_param}&s={var_s_param}&did={var_did_param}&viewer=true",
		"TargetFrame=",
		"Resource=1",
		"RecContentType=application/excel",
		"Referer=",
		LAST);

	//for testing purposes, display the file size returned.
    lr_message("Array index 1 = %s", lr_eval_string("{var_fileSizeChar}"));

	//convert the file size to an integer
	var_fileSize = atoi(lr_eval_string("{var_fileSizeChar}"));
	lr_message("Value of var_fileSize is: %d", var_fileSize);

	//convert the file size check (from the ReportInfo.dat file) to an integer
	//var_fileSizeCheck = atoi(lr_eval_string("{FileSize}"));
	var_fileSizeCheck = atoi(lr_eval_string("{FileSize}"));
	lr_message("Value of var_fileSizeCheck is: %d", var_fileSizeCheck);

    lr_start_transaction("File Size Check");

	if (var_fileSize < (var_fileSizeCheck - (var_fileSizeCheck * .1)) ||
	 (var_fileSize > var_fileSizeCheck + (var_fileSizeCheck * .1))) {
			lr_message("The file size is outside the tolerance range of +/- 10%.");
			lr_message("Please check your dat file to ensure you have specified the
			 correct file size.");
			lr_message("You can get the content size from fiddler OR enable LR extended
			 logging.");
            lr_end_transaction("File Size Check", LR_FAIL);
			lr_exit(LR_EXIT_VUSER, LR_FAIL);
		
	}
	else {
		lr_message("The file size is within the tolerance range of +/- 10% ! :) ");
		lr_end_transaction("File Size Check", LR_PASS);
	}
 
	return;
}

With Cognos 10.2 and 10.2.1 scripts, we are now using 2 functions to retrieve output for pdf, chart and Excel. GetResourceURIs, to retrieve the URL to the resource and getResource to retrieve it using the URL found.

getResourceURIs ()

In IBM Cognos BI 10.2 and 10.2.1, use the getResourceURIs() function to get the URL used by the getResource() function to retrieve charts, PDF report output and Excel report output.

/*
Name: getResourceURIs()
Description: Used to grab the URLs of resources such as Charts, PDFs and Excel output
 types that need to be obtained.
*/
void getResourceURIs(){

	// If we obtain a PDF, CSV, or Report Containing a chart, grab the URL to the
 	// resource.
	if((stricmp(lr_eval_string("{DataCheck}"), "image/png") == 0) ||
	 (stricmp(lr_eval_string("{DataCheck}"), "application/pdf") == 0)){
		web_reg_save_param("var_resource_URI_param", "LB=rsid=",
		 "RB=\"","notfound=warning", "ord=all", "Convert=HTML_TO_TEXT", LAST);
	}
	else{
		web_reg_save_param("var_resource_URI_param", "LB=rsid=",
		 "RB=\'","notfound=warning", "ord=all", LAST);
	}
}

getResource()

In IBM Cognos BI 10.2 and 10.2.1, use the getResource() function retrieve charts, PDF report output and Excel report output.

/*
Name: getResource
Arguments: buffer - a string containing the URL to the resource in CM.  
Parameters:  No parameter files are used in this procedure.
Description: This procedure sends the URL to Cognos10 to get the completed Chart report.
*/
void getResource()
{
	int position = 1;
	int numResources = 0; 

	// If we are obtaining charts from a Report or a PDF.
	if(atoi(lr_eval_string("{var_resource_URI_param_count}")) != 0){ 

		numResources = atoi(lr_eval_string("{var_resource_URI_param_count}"));
		
		web_set_sockets_option("MAX_CONNECTIONS_PER_HOST","6");
		web_concurrent_start(NULL); 
		do{
		
			web_reg_find("Text={DataCheck}", "SaveCount=successfulReport",
			 "Fail=NotFound", "Search=All", LAST);	
			// data check to validate successful return of a Chart report

			lr_param_sprintf("var_resource_URI_param_tmp",
			 lr_eval_string("{var_resource_URI_param_%d}"), position);
			lr_save_string(lr_eval_string(lr_eval_string("{var_resource_URI_param_tmp}")),
			 "var_resource_URI");

			//web_convert_param("var_resource_URI", "SourceEncoding=HTML",
			// "TargetEncoding=PLAIN",LAST);

			// URL to get completed Chart output from Cognos10
			web_url("GetResource",
				"URL=http://{WebServer}{Gateway}?b_action=rc&rsid={var_resource_URI}",
				"TargetFrame=",
				"Resource=1",
				"RecContentType={DataCheck}",
				"Referer=",
				LAST);

			position++;

		}while(position <= numResources);
		
		web_concurrent_end(NULL); 
	}
	// Else we are obtaining charts from a View.
	else{

	    web_reg_find("Text=image/png", "Fail=NotFound", "Search=All", LAST);

		web_url("GetChartOutput",
			"URL=http://{WebServer}{var_chart_Src_param}",
			"TargetFrame=",
			"Resource=1",
			"RecContentType=image/png",
			"Referer=",
			LAST);

	}

	return;
}

Appendix D: Example LoadRunner Script

The following is how a LoadRunner script running the test case in this document may look. Since the same procedures are frequently used in different scripts, adding these procedures to a header file (for example BI.h) and be included at the beginning of your scripts would allow to reuse the same code while keeping your scripts shorter and easier to read. The header file should be placed in LoadRunner's includes folder in your LoadRunner install location.

Scripts are usually broken down in 3 sections - vuser_init, action (one or more) and vuser_end. vuser_init normally contains the calls or procedures to launch, logon and navigate to your report location in Cognos 10. This should also contain the inclusion of your header file. action should contain the code to execute the report and the expected datacheck. This section could be ran for one of more iteration to run same report multiple times or run different reports in same location. vuser_end normally contains the logoff and product shut down code.

Here is an example of the 3 actions blocks with calls to procedures that are in a header file which is included in the vuser_init. These are example only and some calls to procedures not referenced in this document.

vuser_init

#include "BI.h"
vuser_init()
{
	// Define path to the folder containing the reports.  Always end the array with "END".
	char navSequence[][50] = {"Folder1","Folder2","Folder3", "END"};

   connect_CognosConnection();	// connect and logOn handled here
	
	navCC(navSequence);	// folder navigation

	web_set_max_html_param_len("16384");

	return 0; 
}

action

action()
{
   lr_continue_on_error(3);

   /* Executes the report using ReportName and datacheck. Report name and datacheck can
 be hard coded here if there is only 1 report to run.  If running multiple reports, the
 name and datacheck could be changed to parameters and stored in a .dat file*/

	run_Report("ReportName","DataCheck");	

	/* Release the report and return to portal */
	returnToPortalRelease();  
	return 0;
}

vuser_end

vuser_end()
{
	/* Logs user off the system */
	logOff();

	return 0;
}

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Big data and analytics on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Big data and analytics
ArticleID=954822
ArticleTitle=IBM Business Analytics Proven Practices: Scripting Basic IBM Cognos 10 Report Execution Using LoadRunner
publish-date=12062013