blob: 3100c167337fea544553d39c90e1438ab71f8249 [file] [log] [blame]
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000-2018 Ericsson Telecom AB
//
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// which accompanies this distribution, and is available at
// http://www.eclipse.org/legal/epl-v10.html
///////////////////////////////////////////////////////////////////////////////
//
// File: MBT_SpecExpl_Demo.ttcn
// Rev: <RnXnn>
// Prodnr: CNL 113 659
// Updated: 2009-10-01
// Contact: http://ttcn.ericsson.se
///////////////////////////////////////////////////////////////////////////////
module MBT_SpecExpl_Demo
{
import from MBT_SpecExpl_Testcases all;
import from MBT_SUT_SIP_Phone all;
import from EPTF_CLL_Common_Definitions all;
import from EPTF_CLL_Base_Definitions all;
import from EPTF_CLL_Base_Functions all;
import from EPTF_CLL_RBTScheduler_Functions all;
import from EPTF_CLL_LGenBase_Definitions all;
import from EPTF_CLL_LGenBase_ConfigFunctions all;
import from EPTF_CLL_LGenBase_EventHandlingFunctions all;
import from EPTF_MBT_LGen_Definitions all;
import from EPTF_MBT_LGen_Functions all;
import from EPTF_SIP_LGen_Definitions all;
import from EPTF_SIP_LGen_Functions all;
import from EPTF_SIP_Common_Functions all;
import from EPTF_SIP_UserDatabase_Functions all;
import from EPTF_SIP_Transport_Definitions all;
import from EPTF_SIP_Transport_Functions all;
import from EPTF_SIP_MessageHandler_Functions all;
import from EPTF_SIP_TestSteps all;
import from EPTF_SIP_Templates all;
import from EPTF_SIP_Events all;
import from EPTF_SIP_Transaction_Definitions all;
import from TCCFileIO_Functions all;
import from TCCDateTime_Functions all;
modulepar
{
charstring tsp_MBT_Tester_LocalIP := "159.107.193.33";
integer tsp_MBT_Tester_LocalPort := 15000;
charstring tsp_MBT_Tester_RemoteIP := "159.107.193.33";
integer tsp_MBT_Tester_RemotePort := 20000;
charstring tsp_MBT_SIP_Transport := "udp";
}
type component MBT_SpecExpl_Demo_Main_CT
extends
EPTF_Base_CT,
EPTF_MBT_Tester_CT
{}
type record Message
{
charstring name,
boolean type_in,
record of record
{
charstring paramName,
charstring paramValue
} params
}
type record of Message Messages;
type record ExportData
{
charstring tcName,
verdicttype verdict,
Messages messages,
record of charstring states
}
type record of ExportData ExportDatas;
function f_MBT_SpecExpl_Demo_beginTestCase() runs on SpecExpl_CT
{
log(%definitionId, " started");
f_EPTF_Base_init_CT("mtc");
log(%definitionId, " Creating SUT");
var MBT_SpecExpl_Demo_SUT_CT vc_sut := MBT_SpecExpl_Demo_SUT_CT.create;
connect(self:userIn, vc_sut:userIn);
connect(self:userOut, vc_sut:userOut);
connect(self:EPTF_MBT_PCO,vc_sut:EPTF_MBT_PCO);
vc_sut.start(f_MBT_SpecExpl_Demo_SUT_behavior());
EPTF_MBT_PCO.receive(EPTF_MBT_CommandResponse:?) from vc_sut;
EPTF_MBT_PCO.send(EPTF_MBT_ConfigRequest:
{
entityGroupName := "SUT_EntityType",
noEntities := 1,
behaviors := {"MBT_behavior", "Behavior_SIP", "SUT_Behavior"},
fsmName := "MBT_SpecExpl_Demo_SUT_FSM"
}
) to vc_sut;
EPTF_MBT_PCO.receive(EPTF_MBT_ConfigResponse:?) from vc_sut;
log(%definitionId, " SUT ready");
log(%definitionId, " Creating LGen");
var MBT_SpecExpl_Demo_LGen_CT vc_lgen := MBT_SpecExpl_Demo_LGen_CT.create;
connect(self:netIn, vc_lgen:netOut);
connect(self:netOut, vc_lgen:netIn);
connect(self:EPTF_MBT_PCO,vc_lgen:EPTF_MBT_PCO);
vc_lgen.start(f_MBT_SpecExpl_Demo_LGen_behavior());
EPTF_MBT_PCO.receive(EPTF_MBT_CommandResponse:?) from vc_lgen;
EPTF_MBT_PCO.send(EPTF_MBT_ConfigRequest:
{
entityGroupName := "MBT_EntityType",
noEntities := 1,
behaviors := {"MBT_behavior", "Behavior_SIP"},
fsmName := "FSM_MBT"
}
) to vc_lgen;
EPTF_MBT_PCO.receive(EPTF_MBT_ConfigResponse:?) from vc_lgen;
log(%definitionId, " LGen ready");
log(%definitionId, " finished");
}
function f_MBT_SpecExpl_Demo_endTestCase() runs on SpecExpl_CT
{
log("### MAIN: END TESTCASE started");
f_EPTF_Base_stopAll(none, true);
log("### MAIN: END TESTCASE finished");
}
/////////////////////////////////////////////////////////////////////////
//
// M B T Applib
//
/////////////////////////////////////////////////////////////////////////
type component MBT_SpecExpl_Demo_LGen_CT
extends
EPTF_MBT_LGen_CT,
EPTF_SIP_LGen_CT, EPTF_SIP_LocalTransport_CT
{
port netInPort netIn;
port netOutPort netOut;
}
function f_MBT_SpecExpl_Demo_LGen_behavior() runs on MBT_SpecExpl_Demo_LGen_CT
{
//map(self:IPL4_PCO, system:IPL4_PCO);
activate(as_MBT_SpecExpl_Demo_LGen_userMessageHandler());
f_EPTF_MBT_init("MBT_Demo_LGen",0, "MBT_")
f_SIP_applibInit("MBT_Demo_LGen");
f_EPTF_SIP_LocalTransport_init(tsp_MBT_SIP_Transport);
vf_EPTF_SIP_LocalTransport_receive := refers(f_EPTF_SIP_Message_MsgHandler); //receive callback function on LocalTransport
vf_EPTF_SIP_LGen_msgSender := refers(f_EPTF_SIP_LocalTransport_sendSIPMessage); //send callback function on LGen
v_removeUAS := refers(fcb_EPTF_SIP_LocalTransport_removeUAS);
f_EPTF_MBT_initLGenFsm
(
refers(f_MBT_SpecExpl_Demo_LGen_createUserMessage),
refers(f_MBT_SpecExpl_Demo_LGen_fillInDB)
);
EPTF_MBT_PCO.send(EPTF_MBT_CommandResponse:{ ready := {}}) to mtc;
f_EPTF_Base_wait4Shutdown();
}
altstep as_MBT_SpecExpl_Demo_LGen_userMessageHandler()
runs on MBT_SpecExpl_Demo_LGen_CT
{
var SIPResp vl_SIPResp;
var SIPReq vl_SIPReq;
var EPTF_LGenBase_TestStepArgs vl_stepArgs :=
{ eIdx := 0, refContext := { fCtxIdx := 0, fRefArgs := { } }, stepArgs := { } };
[] netOut.receive(SIPResp:?) -> value vl_SIPResp
{
f_EPTF_SchedulerComp_refreshSnapshotTime();
log(%definitionId & "(): incoming ", vl_SIPResp);
if (vl_SIPResp.status == 180)
{
vl_stepArgs.refContext.fRefArgs := {c_status_180Ringing_idx};
f_SIP_step_createResponse(vl_stepArgs);
}
else if (vl_SIPResp.status == 200)
{
if (vl_SIPResp.cseq == "INVITE")
{
vl_stepArgs.refContext.fRefArgs := {c_status_200OK_idx, c_SIP_Method_INVITE};
f_SIP_step_createResponse(vl_stepArgs);
}
else if (vl_SIPResp.cseq == "CANCEL")
{
vl_stepArgs.refContext.fRefArgs := {c_status_200OK_idx, c_SIP_Method_CANCEL};
f_SIP_step_createResponse(vl_stepArgs);
}
}
else if (vl_SIPResp.status == 486)
{
vl_stepArgs.refContext.fRefArgs := {c_status_486BusyHere_idx};
f_SIP_step_createResponse(vl_stepArgs);
}
else if (vl_SIPResp.status == 487)
{
vl_stepArgs.refContext.fRefArgs := {c_status_487RequestTerminated_idx, c_SIP_Method_INVITE};
f_SIP_step_createResponse(vl_stepArgs);
}
else
{
log(%definitionId & "(): unhandled SIPResp");
}
repeat;
}
[] netOut.receive(SIPReq:?) -> value vl_SIPReq
{
f_EPTF_SchedulerComp_refreshSnapshotTime();
log(%definitionId & "(): incoming ", vl_SIPReq);
if (vl_SIPReq.op == "BYE")
{
f_SIP_step_createBYE(vl_stepArgs);
}
else
{
log(%definitionId & "(): unhandled SIPResp");
}
repeat;
}
}
function f_MBT_SpecExpl_Demo_LGen_createUserMessage(in EPTF_LGenBase_TestStepArgs pl_ptr)
runs on MBT_SpecExpl_Demo_LGen_CT
{
log(%definitionId & " creating message for:\n", pl_ptr, "\n", pl_ptr.reportedEvent);
var charstring vl_param := "sip:127.0.0.1:5061";
if (pl_ptr.reportedEvent.event.bIdx == v_SIP_myBIdx and pl_ptr.reportedEvent.event.iIdx == c_SIP_eventIdx_INVITE)
{
var integer vl_FSMIdx := -1;
pl_ptr.refContext.fCtxIdx := 0;
if (not f_EPTF_SIP_FSMInitialized(pl_ptr.eIdx, pl_ptr.refContext.fCtxIdx, vl_FSMIdx))
{
f_SIP_step_init(pl_ptr);
f_SIP_step_handleINVITE(pl_ptr);
}
netIn.send(SIPReq:{"INVITE", vl_param});
}
else if (pl_ptr.reportedEvent.event.bIdx == v_SIP_myBIdx and pl_ptr.reportedEvent.event.iIdx == c_SIP_eventIdx_ACK)
{
netIn.send(SIPReq:{"ACK", vl_param});
}
else if (pl_ptr.reportedEvent.event.bIdx == v_SIP_myBIdx and pl_ptr.reportedEvent.event.iIdx == c_SIP_eventIdx_BYE)
{
netIn.send(SIPReq:{"BYE", vl_param});
}
else if (pl_ptr.reportedEvent.event.bIdx == v_SIP_myBIdx and pl_ptr.reportedEvent.event.iIdx == c_SIP_eventIdx_CANCEL)
{
netIn.send(SIPReq:{"CANCEL", vl_param});
}
else if (pl_ptr.reportedEvent.event.bIdx == v_SIP_myBIdx and pl_ptr.reportedEvent.event.iIdx == 200)
{
netIn.send(SIPResp:{200, v_msgToProcess.response.msgHeader.cSeq.method});
}
else if (pl_ptr.reportedEvent.event.bIdx == v_SIP_myBIdx and pl_ptr.reportedEvent.event.iIdx == c_SIP_eventIdx_retransmittedRequest)
{
netIn.send(SIPReq:{v_msgToProcess.request.msgHeader.cSeq.method, vl_param});
}
else
{
log(%definitionId & "(): unhandled incoming message");
}
}
function f_MBT_SpecExpl_Demo_LGen_fillInDB(in EPTF_MBT_ConfigRequest p_req) runs on MBT_SpecExpl_Demo_LGen_CT
{
var integer vl_grpIdx := f_EPTF_LGenBase_entityGrpNameIndex(p_req.entityGroupName);
var integer vl_entityIdx := f_EPTF_LGenBase_getEGrpBaseOffset(vl_grpIdx);
for (var integer i:=0; i<p_req.noEntities; i:=i+1)
{
var EPTF_IntegerList vl_bCtx := f_EPTF_LGenBase_getBehaviorCtx(i + vl_entityIdx, v_SIP_myBIdx);
f_EPTF_SIP_IPL4asp_SetUserData
(
vl_bCtx[0],
tsp_MBT_Tester_LocalIP, // local IP
{tsp_MBT_Tester_LocalPort, tsp_MBT_Tester_LocalPort+1},
tsp_MBT_SIP_Transport,
tsp_MBT_Tester_RemoteIP, // proxy ip
tsp_MBT_Tester_RemotePort // proxy port
);
f_EPTF_SIP_User_SetUserData(
vl_bCtx[0],
{
{
addr := {
nameAddr := {
displayName := "titansim_user_7465000",
addrSpec := {
scheme := "sip",
userInfo := {
userOrTelephoneSubscriber := "titansim_user_7465000",
password := omit
},
hostPort := {
host := "tcj.ics.se",
portField := tsp_MBT_Tester_LocalPort
},
urlParameters := omit,
headers := omit
}
}
},
password := "pass2ICS"
}
},
tsp_MBT_Tester_LocalIP,
{tsp_MBT_Tester_LocalPort, tsp_MBT_Tester_LocalPort+1},
i + vl_entityIdx //entity index
);
f_EPTF_SIP_Session_AddData(vl_bCtx[0], f_EPTF_SIP_getTransport(tsp_MBT_SIP_Transport),345600);
f_EPTF_SIP_IPL4asp_startListening(vl_bCtx[0], true); // Both UDP and TCP
}
}
function f_exportHTML(in ExportDatas db)
{
var charstring vl_datetime := f_getTimeFormatted(f_time(),"%A %d %B %Y %H:%M:%S");
var integer vl_write;
var charstring vl_html_start :=
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">
<html>
<head>
<title>Test results html export " & vl_datetime & "</title>
<meta http-equiv=\"Content-Type\" content=\"text/html; charset=windows-1252\">
<script language=\"JavaScript\" type=\"text/javascript\">
$pass = '#99FF99';
$fail = '#FF9999';
$inconc = '#FFFF99';
$selected = '#9999FF';
function mouseover(row) {row.style.background=$selected;};
function mouseout(row) {if(row.getAttribute(\"verdicttype\")==\"pass\")row.style.background=$pass;
else if(row.getAttribute(\"verdicttype\")==\"fail\")row.style.background=$fail;
else if(row.getAttribute(\"verdicttype\")==\"inconc\")row.style.background=$inconc;};
function mouseclick(tcnum) {window.location = \"#testcase\"+tcnum;}
</script>
<style type=\"text/css\">
body { margin: 0px;
background-color: #CCCCCC;
text-align: center; }
.header { background-color: #DDDDDD; }
.c1 { text-align: left;
vertical-align: top;
width: 120px;}
.c2 { text-align: left;
vertical-align: top;
width: 80px;}
.c3 { text-align: left;
vertical-align: top;
width: 250px;}
.c4 { text-align: left;
vertical-align: top;
width: 300px;}
.r1 {background-color: #99FF99;}
.r2 {background-color: #FF9999;}
.r3 {background-color: #FFFF99;}
.table1 { border: 2px solid black;
border-collapse: collapse;
border-spacing: 0px;
padding: 0px; }
.table1 td{ border: 1px solid black;
border-collapse: collapse; }
.sumtable { border: 2px solid black;
border-collapse: collapse;
border-spacing: 0px;
padding: 0px; }
.maintable { border: 0px solid black;}
.innertable { border: 0px solid black;
width: 100%;
height: 100%;}
#wrapper { position: relative;
top: 36px;
display: inline-block; }
.dtitle { background-color: #DDDDDD;
font-size: 24px;
white-space: pre; }
.dt {background-color: transparent;
font-size: 1px; }
.ds {background-color: #222222;
font-size: 1px;
filter:alpha(opacity=90);
-moz-opacity: 0.9;
opacity: 0.9; }
</style>
</head>
<body>
<div align=\"center\" id=\"wrapper\">
<table align=\"center\" class=\"maintable\" cellpadding=\"0px\" cellspacing=\"0px\">
<tr>
<td>
<table class=\"table1\" cellpadding=\"5px\" cellspacing=\"0px\">
<tr class=\"dtitle\">
<td>" & vl_datetime & "</td>
</tr>
</table>
</td>
<td width=\"10px\" height=\"100%\">
<table class=\"innertable\" cellpadding=\"0px\" cellspacing=\"0px\">
<tr height=\"10px\"><td class=\"dt\">&nbsp;</td></tr>
<tr><td class=\"ds\">&nbsp;</td></tr>
</table>
</td>
</tr>
<tr>
<td height=\"10px\">
<table class=\"innertable\" cellpadding=\"0px\" cellspacing=\"0px\">
<tr><td width=\"10px\" class=\"dt\">&nbsp;</td><td class=\"ds\">&nbsp;</td></tr>
</table>
</td>
<td class=\"ds\">&nbsp;</td>
</tr>
</table>
<br>
<table align=\"center\" class=\"maintable\" cellpadding=\"0px\" cellspacing=\"0px\">
<tr>
<td>
<table class=\"table1\" cellpadding=\"5px\">
<tr class=\"header\">
<th class=\"c1\">TC Name</th><th class=\"c2\">Verdict</th>
</tr>
";
var integer vl_nof_pass := 0;
var integer vl_nof_fail := 0;
var integer vl_nof_inconc := 0;
var integer vl_fd;
var charstring vl_text_out;
vl_fd := f_FIO_open_append_wronly ("exportHTML_"&f_getTimeFormatted(f_time(),"%d_%m_%Y__%H_%M_%S")&".html");
if (vl_fd < 0)
{
log(f_FIO_get_error_string ());
return;
}
vl_write := f_FIO_write_text (vl_fd, vl_html_start);
for(var integer i := 0; i < sizeof(db) ; i:= i+1)
{
//new row
if (db[i].verdict == pass)
{
vl_text_out := " <tr class=\"r1\" verdicttype=\"pass\" onmouseover=\"mouseover(this);\" onmouseout=\"mouseout(this);\" onclick=\"mouseclick(" & int2str(i) & ");\" style=\"cursor: pointer\">\n";
vl_nof_pass := vl_nof_pass +1;
}
else if (db[i].verdict == fail)
{
vl_text_out := " <tr class=\"r2\" verdicttype=\"fail\" onmouseover=\"mouseover(this);\" onmouseout=\"mouseout(this);\" onclick=\"mouseclick(" & int2str(i) & ");\" style=\"cursor: pointer\">\n";
vl_nof_fail := vl_nof_fail +1;
}
else if (db[i].verdict == inconc)
{
vl_text_out := " <tr class=\"r3\" verdicttype=\"inconc\" onmouseover=\"mouseover(this);\" onmouseout=\"mouseout(this);\" onclick=\"mouseclick(" & int2str(i) & ");\" style=\"cursor: pointer\">\n";
vl_nof_inconc := vl_nof_inconc +1;
}
vl_write := f_FIO_write_text (vl_fd,vl_text_out);
//new cell - tcName
vl_text_out := " <td class=\"c1\">\n";
vl_write := f_FIO_write_text (vl_fd,vl_text_out);
//cell content
vl_text_out := " "&db[i].tcName&"\n";
vl_write := f_FIO_write_text (vl_fd,vl_text_out);
//end of cell
vl_text_out := " </td>\n";
vl_write := f_FIO_write_text (vl_fd,vl_text_out);
//new cell - Verdict
vl_text_out := " <td class=\"c2\">\n";
vl_write := f_FIO_write_text (vl_fd,vl_text_out);
//cell content
if (db[i].verdict == pass)
{
vl_text_out := " pass\n";
}
else if (db[i].verdict == fail)
{
vl_text_out := " fail\n";
}
else if (db[i].verdict == inconc)
{
vl_text_out := " error\n";
}
vl_write := f_FIO_write_text (vl_fd,vl_text_out);
//end of cell
vl_text_out := " </td>\n";
vl_write := f_FIO_write_text (vl_fd,vl_text_out);
}
vl_text_out :=
" </table>
</td>
<td width=\"10px\" height=\"100%\">
<table class=\"innertable\" cellpadding=\"0px\" cellspacing=\"0px\">
<tr height=\"10px\"><td class=\"dt\">&nbsp;</td></tr>
<tr><td class=\"ds\">&nbsp;</td></tr>
</table>
</td>
</tr>
<tr>
<td height=\"10px\">
<table class=\"innertable\" cellpadding=\"0px\" cellspacing=\"0px\">
<tr><td width=\"10px\" class=\"dt\">&nbsp;</td><td class=\"ds\">&nbsp;</td></tr>
</table>
</td>
<td class=\"ds\">&nbsp;</td>
</tr>
</table>
<br>
<table align=\"center\" class=\"maintable\" cellpadding=\"0px\" cellspacing=\"0px\">
<tr>
<td>
<table class=\"sumtable\" cellpadding=\"5px\">
<tr>
<td class=\"r1\" style=\"border-left: 1px solid black\">Passed: </td><td class=\"r1\">" & int2str(vl_nof_pass) & "</td>
<td class=\"r2\" style=\"border-left: 1px solid black\">Failed: </td><td class=\"r2\">" & int2str(vl_nof_fail) & "</td>
<td class=\"r3\" style=\"border-left: 1px solid black\">Error: </td><td class=\"r3\">" & int2str(vl_nof_inconc) & "</td>
</tr>
</table>
</td>
<td width=\"10px\" height=\"100%\">
<table class=\"innertable\" cellpadding=\"0px\" cellspacing=\"0px\">
<tr height=\"10px\"><td class=\"dt\">&nbsp;</td></tr>
<tr><td class=\"ds\">&nbsp;</td></tr>
</table>
</td>
</tr>
<tr>
<td height=\"10px\">
<table class=\"innertable\" cellpadding=\"0px\" cellspacing=\"0px\">
<tr><td width=\"10px\" class=\"dt\">&nbsp;</td><td class=\"ds\">&nbsp;</td></tr>
</table>
</td>
<td class=\"ds\">&nbsp;</td>
</tr>
</table>
<br><br><br>
<table align=\"center\" class=\"maintable\" cellpadding=\"0px\" cellspacing=\"0px\">
<tr>
<td>
<table class=\"table1\" cellpadding=\"5px\" cellspacing=\"0px\">
<tr class=\"header\">
<th class=\"c1\">TC Name</th><th class=\"c2\">Verdict</th><th class=\"c3\">Messages</th><th class=\"c4\">States</th>
</tr>
";
vl_write := f_FIO_write_text (vl_fd, vl_text_out);
for(var integer i := 0; i < sizeof(db) ; i:= i+1)
{
//new row
if (db[i].verdict == pass)
{
vl_text_out := " <tr class=\"r1\">\n";
}
else if (db[i].verdict == fail)
{
vl_text_out := " <tr class=\"r2\">\n";
}
else if (db[i].verdict == inconc)
{
vl_text_out := " <tr class=\"r3\">\n";
}
vl_write := f_FIO_write_text (vl_fd,vl_text_out);
//new cell - tcName
vl_text_out := " <td class=\"c1\">\n";
vl_write := f_FIO_write_text (vl_fd,vl_text_out);
//cell content
vl_text_out := " <a name=\"testcase" & int2str(i) & "\">"&db[i].tcName&"</a>\n";
vl_write := f_FIO_write_text (vl_fd,vl_text_out);
//end of cell
vl_text_out := " </td>\n";
vl_write := f_FIO_write_text (vl_fd,vl_text_out);
//new cell - Verdict
vl_text_out := " <td class=\"c2\">\n";
vl_write := f_FIO_write_text (vl_fd,vl_text_out);
//cell content
if (db[i].verdict == pass)
{
vl_text_out := " pass\n";
}
else if (db[i].verdict == fail)
{
vl_text_out := " fail\n";
}
else if (db[i].verdict == inconc)
{
vl_text_out := " error\n";
}
vl_write := f_FIO_write_text (vl_fd,vl_text_out);
//end of cell
vl_text_out := " </td>\n";
vl_write := f_FIO_write_text (vl_fd,vl_text_out);
//new cell - Messages
vl_text_out := " <td class=\"c3\">\n";
vl_write := f_FIO_write_text (vl_fd,vl_text_out);
//cell content
for(var integer j := 0; j < sizeof(db[i].messages); j := j+1)
{
if (db[i].messages[j].type_in) {vl_text_out := "<------- ";} else {vl_text_out := "-------- ";}
vl_text_out := vl_text_out & db[i].messages[j].name;
if (db[i].messages[j].type_in) {vl_text_out := vl_text_out & " --------<br>\n";} else {vl_text_out := vl_text_out & " -------><br>\n";}
vl_write := f_FIO_write_text (vl_fd,vl_text_out);
for(var integer k := 0; k < sizeof(db[i].messages[j].params); k := k+1)
{
vl_text_out := " - " & db[i].messages[j].params[k].paramName & ": \"" & db[i].messages[j].params[k].paramValue & "\"<br>\n";
vl_write := f_FIO_write_text (vl_fd,vl_text_out);
}
}
//end of cell
vl_text_out := " </td>\n";
vl_write := f_FIO_write_text (vl_fd,vl_text_out);
//new cell - States
vl_text_out := " <td class=\"c4\">\n";
vl_write := f_FIO_write_text (vl_fd,vl_text_out);
//cell content
for(var integer j := 0; j < sizeof(db[i].states); j := j+1)
{
vl_text_out := db[i].states[j] & "<br>\n";
vl_write := f_FIO_write_text (vl_fd,vl_text_out);
}
//end of cell
vl_text_out := " </td>\n";
vl_write := f_FIO_write_text (vl_fd,vl_text_out);
//end of row
vl_text_out := " </tr>\n";
vl_write := f_FIO_write_text (vl_fd,vl_text_out);
}
var charstring vl_html_end :=
" </table>
</td>
<td width=\"10px\" height=\"100%\">
<table class=\"innertable\" cellpadding=\"0px\" cellspacing=\"0px\">
<tr height=\"10px\"><td class=\"dt\">&nbsp;</td></tr>
<tr><td class=\"ds\">&nbsp;</td></tr>
</table>
</td>
</tr>
<tr>
<td height=\"10px\">
<table class=\"innertable\" cellpadding=\"0px\" cellspacing=\"0px\">
<tr><td width=\"10px\" class=\"dt\">&nbsp;</td><td class=\"ds\">&nbsp;</td></tr>
</table>
</td>
<td class=\"ds\">&nbsp;</td>
</tr>
</table>
<br>
</div>
</body>
</html>";
vl_write := f_FIO_write_text (vl_fd, vl_html_end);
f_FIO_flush (vl_fd);
f_FIO_close (vl_fd);
}
}