| /////////////////////////////////////////////////////////////////////////////// |
| // // |
| // Copyright (c) 2000-2019 Ericsson Telecom AB // |
| // // |
| // All rights reserved. This program and the accompanying materials // |
| // are made available under the terms of the Eclipse Public License v2.0 // |
| // which accompanies this distribution, and is available at // |
| // https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html // |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| /////////////////////////////////////////////////////////// |
| // Module: EPTF_LGenBaseDemo_CallerFunctions |
| // |
| // Purpose: |
| // This module contains function used in the Caller component. |
| // |
| // Module Parameters: |
| // - |
| // |
| // Module depends on: |
| // |
| // Current Owner: |
| // ELSZSKU |
| // |
| // Last Review Date: |
| // 20 - - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| module EPTF_LGenBaseDemo_CallerFunctions |
| { |
| import from EPTF_CLL_LGenBase_EventHandlingFunctions all; |
| |
| import from TCCConversion_Functions all; |
| |
| import from EPTF_CLL_Base_Functions all; |
| import from EPTF_CLL_LGenBase_TemplateFunctions all; |
| import from EPTF_LGenBaseDemo_CallerDefinitions all |
| import from EPTF_LGenBaseDemo_TransportDefinitions all |
| import from EPTF_LGenBaseDemo_TransportFunctions all |
| import from EPTF_LGenBaseDemo_TemplateFunctions all; |
| import from EPTF_CLL_LGenBase_Functions all |
| import from EPTF_CLL_LGenBase_ConfigDefinitions all |
| import from EPTF_CLL_LGenBase_ConfigFunctions all |
| import from EPTF_CLL_LGenBase_Definitions all |
| import from EPTF_CLL_LGenBase_TrafficFunctions all |
| import from EPTF_CLL_LGenBaseStats_Definitions all |
| import from EPTF_CLL_Variable_Definitions all |
| import from EPTF_CLL_Variable_Functions all |
| import from EPTF_CLL_Common_Definitions all |
| |
| //The template describing the ReRegister messages is loaded programmatically |
| //This module parameter describes the file |
| modulepar charstring tsp_LGenBaseDemo_msgReRegisterExtTemplateFile := "../EPTF_LGenBaseDemo_msgReRegisterTemplate.txt" |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // This is the starter function of the Caller component |
| // There are samples how to retrieve identifiers of scenarios and traffic cases |
| /////////////////////////////////////////////////////////////////////////////// |
| public function f_LGenBaseDemo_Caller_behavior( |
| in charstring pl_name, |
| in LGenBaseDemo_Transport_CT pl_connectTo) |
| runs on LGenBaseDemo_Caller_CT{ |
| //Initialize the component |
| f_LGenBaseDemo_Caller_init(pl_name, pl_connectTo) |
| //Create the scenario |
| f_EPTF_LGenBase_createScenario2EntityGroup({c_LGenBaseDemo_Caller_entityGroupName,c_LGenBaseDemo_Caller_scenarioName},false) |
| //Store the identifier of the Register traffic case for later use |
| v_LGenBaseDemo_Caller_registerTcIdx := f_EPTF_LGenBase_trafficCaseId( |
| c_LGenBaseDemo_Caller_entityGroupName, |
| c_LGenBaseDemo_Caller_scenarioName, |
| c_LGenBaseDemo_Caller_tcRegisterName) |
| var integer vl_eGrpIdx, vl_scRelIdx |
| //Retrieve the identifiers of the scenario to be started, and... |
| f_EPTF_LGenBase_scenarioRelIdx( |
| f_EPTF_LGenBase_scenarioAbsIdxByName(c_LGenBaseDemo_Caller_entityGroupName, c_LGenBaseDemo_Caller_scenarioName), |
| vl_eGrpIdx, |
| vl_scRelIdx) |
| //start it |
| f_EPTF_LGenBase_enableScenarioOnEntityGroup(vl_eGrpIdx, vl_scRelIdx) |
| //Then come what may... |
| f_EPTF_Base_wait4Shutdown() |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // Initialization of the Caller component |
| /////////////////////////////////////////////////////////////////////////////// |
| public function f_LGenBaseDemo_Caller_init( |
| in charstring pl_name, |
| in LGenBaseDemo_Transport_CT pl_connectTo) |
| runs on LGenBaseDemo_Caller_CT{ |
| f_LGenBaseDemo_Transport_init( |
| pl_name, //the name of the component always must be passed to the extended component |
| refers(f_LGenBaseDemo_Caller_processResponses), |
| pl_connectTo) |
| f_EPTF_LGenBase_init(pl_name) |
| v_LGenBaseDemo_Caller_msgUserDataMarkLen := lengthof(c_LGenBaseDemo_Caller_msgUserDataMark) |
| v_LGenBaseDemo_Caller_msgUserDataSeparatorLen := lengthof(c_LGenBaseDemo_Caller_msgUserDataSeparator) |
| |
| //Some template initialization functions. See the function itself. |
| f_LGenBaseDemo_Caller_templateDef() |
| f_EPTF_Base_registerCleanup(refers(f_LGenBaseDemo_Caller_cleanup)) |
| |
| //Declare a behavior type. |
| //This behavior type can be used for several purposes. |
| //The Caller component uses it only to identify events. See the f_EPTF_LGenBase_declareFsmEvent function calls. |
| //See also the initialization of the Responder component |
| v_LGenBaseDemo_Caller_myBehavId := f_EPTF_LGenBase_declareBehaviorType(c_LGenBaseDemo_Caller_BehaviorName, -1, null, null, null) |
| //These events used to notify the FSMs about the responses of the Responder component |
| f_EPTF_LGenBase_declareFsmEvent(c_LGenBaseDemo_Caller_BehaviorName, c_LGenBaseDemo_Caller_InputNameRespSuccess) |
| f_EPTF_LGenBase_declareFsmEvent(c_LGenBaseDemo_Caller_BehaviorName, c_LGenBaseDemo_Caller_InputNameRespFailed) |
| //At the end of the test a test report is generated. The following listener is called when the |
| //c_EPTF_LGenBase_inputIdx_testMgmt_testFinished is dispatched. See also the trafficFinishedActions |
| //parameter of the "Caller_TcDoMsg" traffic case. |
| f_EPTF_LGenBase_addGeneralEventListener(c_EPTF_LGenBase_bIdx, c_EPTF_LGenBase_inputIdx_testMgmt_testFinished, refers(f_LGenBaseDemo_Caller_testFinishedListener), {}) |
| //We use only one combination of the behaviors (only the "Caller" behavior), therefore |
| //we use only one entity type |
| f_EPTF_LGenBase_declareEntityType(c_LGenBaseDemo_Caller_entityTypeName, {c_LGenBaseDemo_Caller_BehaviorName}) |
| |
| //Declare the functions to be used in the traffic cases |
| //The f_LGenBaseDemo_Caller_registerFinished function will be called when the traffic case "Register" finished |
| //See also the "trafficStartFinish" parameters of the Register traffic case. |
| f_EPTF_LGenBase_declareFunction(c_LGenBaseDemo_Caller_registerFinishedName, {customFinishFunction := refers(f_LGenBaseDemo_Caller_registerFinished)}) |
| //The f_LGenBaseDemo_Caller_entityFinishedInRegister will be called each time an entity of the Register traffic case finished. |
| //See also the "entityFinishActions" parameter of the Register traffic case. |
| f_EPTF_LGenBase_declareFunction(c_LGenBaseDemo_Caller_entityFinishedName, {customFinishFunction := refers(f_LGenBaseDemo_Caller_entityFinishedInRegister)}) |
| |
| //All the test step functions must be declared before their first use |
| //See also the occurance of the c_LGenBaseDemo_Caller_StepName_sendMessage in the f_LGenBaseDemo_Caller_fsm |
| f_EPTF_LGenBase_declareStep(c_LGenBaseDemo_Caller_BehaviorName, {c_LGenBaseDemo_Caller_StepName_sendMessage,refers(f_LGenBaseDemo_Caller_sendMessage)}) |
| |
| //This case an entity represents a user. Therefore the size of the entity group |
| //must be equal to the count of the users to be simulated. |
| //See also the init function of the responder. |
| f_EPTF_LGenBase_createEntityGroup({c_LGenBaseDemo_Caller_entityGroupName, c_LGenBaseDemo_Caller_entityTypeName, tsp_LGenBaseDemo_userCount}) |
| |
| //Since the FSMs of all the traffic cases are almost the same (except the message to be sent to the responder) |
| //the FSMs can be produced by the same function. |
| f_EPTF_LGenBase_declareFSMTable(f_LGenBaseDemo_Caller_fsm( |
| c_LGenBaseDemo_Caller_fsmNameRegister, |
| c_LGenBaseDemo_Caller_MsgRegister)) |
| f_EPTF_LGenBase_declareFSMTable(f_LGenBaseDemo_Caller_fsm( |
| c_LGenBaseDemo_Caller_fsmNameReRegister, |
| c_LGenBaseDemo_Caller_MsgReRegister)) |
| f_EPTF_LGenBase_declareFSMTable(f_LGenBaseDemo_Caller_fsm( |
| c_LGenBaseDemo_Caller_fsmNameDoMsg, |
| c_LGenBaseDemo_Caller_MsgDoMsg)) |
| |
| //A traffic case type must be declared before the traffic case is declred for a scenario |
| //The traffic case type "Caller_TcRegister" uses the FSM "Caller_fsmRegister" |
| //We want to use the f_EPTF_LGenBase_successIfOnceSuccess function to decide the success |
| //of the entities. This must be declared. The default is f_EPTF_LGenBase_successSucNoFail. |
| f_EPTF_LGenBase_declareTrafficCaseType({ |
| c_LGenBaseDemo_Caller_tcRegisterName, |
| c_LGenBaseDemo_Caller_fsmNameRegister, |
| c_LGenBaseDemo_Caller_entityTypeName, |
| { |
| {customEntitySucc := c_EPTF_LGenBase_EntitySucc_successIfOnceSuccessFnName} |
| } |
| }) |
| f_EPTF_LGenBase_declareTrafficCaseType({ |
| c_LGenBaseDemo_Caller_tcReRegisterName, |
| c_LGenBaseDemo_Caller_fsmNameReRegister, |
| c_LGenBaseDemo_Caller_entityTypeName, |
| {} |
| }) |
| f_EPTF_LGenBase_declareTrafficCaseType({ |
| c_LGenBaseDemo_Caller_tcDoMsgName, |
| c_LGenBaseDemo_Caller_fsmNameDoMsg, |
| c_LGenBaseDemo_Caller_entityTypeName, |
| {} |
| }) |
| |
| var float vl_targetCPSOfRegister := tsp_LGenBaseDemo_targetCPS/2.0 |
| |
| //The scenario contains 3 traffic cases. |
| f_EPTF_LGenBase_declareScenarioType3({ |
| name := c_LGenBaseDemo_Caller_scenarioName, |
| tcList := { |
| { |
| tcName := c_LGenBaseDemo_Caller_tcRegisterName, |
| tcParamsList := { |
| //All the entities will be enabled in the traffic case at the start. |
| //The LGenBase starts each entity. |
| {enableEntitiesAtStart := true}, |
| //The traffic case will be enabled at the start of the scenario, so it |
| //will be started too |
| {enabledAtStart := true}, |
| //The entities will be selected in order |
| {entitySelection := round_robin}, |
| {target := {cpsToReach := vl_targetCPSOfRegister} }, |
| //The entities will be started until... |
| {entityFinishConditions := { |
| //the first successful registration |
| {nrOfSuccesses := 1}, |
| //or maximum 3 failed registrations |
| {nrOfFails := 3} |
| }}, |
| {entityFinishActions := { |
| { |
| //When an entity finished, it becomes enabled in the ReRegister traffic case |
| //if it had been registered succesfully |
| enableEntity4Tc := { |
| tcName := c_LGenBaseDemo_Caller_tcReRegisterName, |
| aMode := enableIfPreviousSuccess |
| } |
| }, |
| //When an entity finished, a logger function is called to display the workflow. |
| //See also the f_EPTF_LGenBase_declareFunction calls in the initialization |
| {customFinishFunction := c_LGenBaseDemo_Caller_entityFinishedName} |
| } |
| }, |
| //The traffic case will be finished.. |
| {trafficStartFinish:={ |
| //when all the available entities finished. |
| {availableEntitiesFinished := {{ |
| //Then a logger function is called |
| //See also the f_EPTF_LGenBase_declareFunction calls in the initialization |
| {customFinishFunction := c_LGenBaseDemo_Caller_registerFinishedName}, |
| //When there is no more entities to be registered, the ReRegister traffic case |
| //must be stopped too, and... |
| {disableTc := {c_LGenBaseDemo_Caller_tcReRegisterName}}, |
| //the DoMsg message sending traffic case must be started |
| {enableTc := {c_LGenBaseDemo_Caller_tcDoMsgName,enableIfPreviousSuccess}} |
| }}} |
| }}, |
| //The external templates used in a traffic case can be described |
| //with function calls, or in the traffic case declaration. |
| {templateSet :={ |
| { |
| //The following 2 names must match the name pair used in |
| //the f_EPTF_LGenBase_declareTemplateType. |
| //See <f_LGenBaseDemo_Caller_templateDef> |
| c_LGenBaseDemo_Caller_BehaviorName, |
| c_LGenBaseDemo_Caller_msgRegisterTemplType, |
| //This value must match the name assigned to the external template file |
| //in the tsp_LGenBase_extTemplLoadList in the config file |
| //or in the f_EPTF_LGenBase_loadExtTempl function call. |
| c_LGenBaseDemo_Caller_msgRegisterExtTemplateName |
| } |
| }} |
| } |
| }, |
| { |
| tcName := c_LGenBaseDemo_Caller_tcReRegisterName, |
| tcParamsList := { |
| {enableEntitiesAtStart := false}, |
| {enabledAtStart := true}, |
| {entitySelection := round_robin}, |
| {target := {cpsToReach := tsp_LGenBaseDemo_targetCPS-vl_targetCPSOfRegister} } |
| } |
| }, |
| { |
| tcName := c_LGenBaseDemo_Caller_tcDoMsgName, |
| tcParamsList := { |
| {enableEntitiesAtStart := false}, |
| //This traffic case won't be started when the scenario started. |
| //See also the trafficStartFinish parameter of the Register traffic case |
| {enabledAtStart := false}, |
| //In this tc the entities are selected randomly |
| {entitySelection := random}, |
| {target := {cpsToReach := tsp_LGenBaseDemo_targetCPS} }, |
| //The tc runs for 4 seconds, then stops |
| {trafficStartFinish:={ |
| {execTime := {4.0, {}}} |
| }}, |
| //Let's wait while the response for the last started message arrives, and then stop the test. |
| //See also the f_LGenBaseDemo_Caller_testFinishedListener |
| {trafficFinishedActions := { |
| {testFinished := {}} |
| }}, |
| //The template set of the DoMsg traffic case is described similarly to the |
| //traffic case Register |
| {templateSet :={ |
| { |
| c_LGenBaseDemo_Caller_BehaviorName, |
| c_LGenBaseDemo_Caller_msgDoMsgTemplType, |
| c_LGenBaseDemo_Caller_msgDoMsgExtTemplateName |
| } |
| }} |
| } |
| } |
| }, |
| scParamsList := {} |
| }) |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // The FSMs describe how the entities behave. |
| // This function demonstrates how to describe an FSM. |
| /////////////////////////////////////////////////////////////////////////////// |
| private function f_LGenBaseDemo_Caller_fsm( |
| in charstring pl_fsmName, //The name of the FSM |
| in integer pl_msgType) //Which kind of message to be sent |
| return EPTF_LGenBase_FsmTableDeclarator{ |
| return { |
| name := pl_fsmName, |
| fsmParams := { |
| {stateList := {"idle", "waiting4Reply"}}, |
| {timerList := { |
| {name := "watchdog", startValue := c_LGenBaseDemo_Caller_Watchdog} |
| }}, |
| {varList := { |
| //Temporary variable to handle latency measurement. |
| //The chronometers of each FSM set the content of this variable. |
| //The min/max statistics calculate their values based on this variable. |
| {name := "tcLatency", initValue := {floatVal := 0.0}, scope := TC}, |
| //The "max" statistics store its value in this variable |
| {name := "tcMaxLatency", initValue := {floatVal := 0.0}, scope := TC} |
| }}, |
| {statMeasWithParamsList := { |
| { name := "chronoLatency", |
| providerVarName := "", |
| targetVarName := "tcLatency", |
| statMeasParams := {statType := chrono}, |
| scope := FSM |
| }, |
| { |
| //Calculates the minimal value of the |
| //FSM variable called "tcLatency" |
| //and stores it in a temporary variable |
| name := "minLatency", |
| providerVarName := "tcLatency", |
| targetVarName := "", |
| statMeasParams := {statType := min}, |
| scope := TC |
| }, |
| { |
| //Calculates the maximal value of the |
| //FSM variable called "tcLatency", |
| //and stores it in the variable "tcMaxLatency" |
| name := "maxLatency", |
| providerVarName := "tcLatency", |
| targetVarName := "tcMaxLatency", |
| statMeasParams := {statType := max}, |
| scope := TC |
| } |
| } |
| } |
| }, |
| table := { |
| extendedTable := { |
| { |
| //Listens to the start event |
| events2Listen := { events := {{ singleEvent := { |
| c_EPTF_LGenBase_behavior,c_EPTF_LGenBase_inputName_testMgmt_startTC,fsm |
| }}}}, |
| cellRow := { statedCellRow := { |
| { inState := { state := "idle"}, |
| cell := { |
| actionList := { |
| // Calls a function which creates and sends the appropriate message to the responder |
| {c_LGenBaseDemo_Caller_StepName_sendMessage, {stepContextArgs := {pl_msgType}}}, |
| // Starts the chronometer |
| {c_EPTF_LGenBase_stepName_fsmStartChrono,{statMeasName := "chronoLatency"}}, |
| // Then starts the watchdog timer |
| {c_EPTF_LGenBase_stepName_timerStart,{timerName := "watchdog"}} |
| }, |
| nextStateCalculation := omit, |
| // At the end it puts the FSM to the "waiting4Reply" state |
| nextState := "waiting4Reply" |
| }} |
| }} |
| }, |
| { |
| //Listens to the RespSuccess event |
| { events := {{ singleEvent := { |
| c_LGenBaseDemo_Caller_BehaviorName, |
| c_LGenBaseDemo_Caller_InputNameRespSuccess, |
| fsm |
| }}}}, |
| { statedCellRow := { |
| {{state := "waiting4Reply"}, |
| {{ |
| // Stop the chronometer |
| {c_EPTF_LGenBase_stepName_fsmStopChrono,{statMeasName := "chronoLatency"}}, |
| // Stop the watchdog timer |
| {c_EPTF_LGenBase_stepName_timerCancel,{timerName := "watchdog"}}, |
| // and report successful finish |
| {c_EPTF_LGenBase_stepName_trafficSuccess,omit} |
| }, |
| //Then put back to "idle" state |
| omit,"idle" |
| }} |
| //In any other state we don't take care of it. |
| //Probably a timed out response |
| }} |
| }, |
| { |
| //Listens to the RespFailed event |
| { events := {{ singleEvent := { |
| c_LGenBaseDemo_Caller_BehaviorName, |
| c_LGenBaseDemo_Caller_InputNameRespFailed, |
| fsm |
| }}}}, |
| { statedCellRow := { |
| {{state := "waiting4Reply"}, |
| {{ |
| // Stop the chronometer |
| {c_EPTF_LGenBase_stepName_fsmStopChrono,{statMeasName := "chronoLatency"}}, |
| // Stop the watchdog timer |
| {c_EPTF_LGenBase_stepName_timerCancel,{timerName := "watchdog"}}, |
| // and report finish with failure |
| {c_EPTF_LGenBase_stepName_trafficFailed,omit} |
| }, |
| //Then put back to "idle" state |
| omit,"idle" |
| }} |
| //In any other state we don't take care of it. |
| //Probably a timed out response |
| }} |
| }, |
| { |
| //Listenes to the watchdog timeout |
| { events := {{ singleEvent := { c_EPTF_LGenBase_specialBName_timerTimeout,"watchdog",fsm }}}}, |
| { statedCellRow := { |
| {{state := "waiting4Reply"}, |
| {{ |
| //Reports finish with timeout |
| {c_EPTF_LGenBase_stepName_trafficTimeout,omit} |
| }, |
| //Then put back to "idle" state |
| omit,"idle" |
| }}, |
| //In any other state it's a programming fault. |
| {{anyUndefinedState := {}}, |
| {{ |
| {c_EPTF_LGenBase_stepName_cancelAllTimers, omit}, |
| {c_EPTF_LGenBase_stepName_trafficError,omit} |
| },omit,"idle" |
| }} |
| }} |
| } |
| } |
| } |
| } |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // The cleanup of the component does nothing. |
| // This case the function does not have to be described and registered. |
| /////////////////////////////////////////////////////////////////////////////// |
| private function f_LGenBaseDemo_Caller_cleanup() |
| runs on LGenBaseDemo_Caller_CT{ |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // This function demonstrates how does a custom step function have to look like, |
| // and how can data described in an FSM can be retrieved in the step function. |
| /////////////////////////////////////////////////////////////////////////////// |
| private function f_LGenBaseDemo_Caller_sendMessage(in EPTF_LGenBase_TestStepArgs pl_args) |
| runs on LGenBaseDemo_Caller_CT{ |
| var LGenBaseDemo_Transport_MessageData vl_msgData := c_LGenBaseDemo_Transport_emptyMessageData |
| vl_msgData.entityIdx := pl_args.eIdx |
| vl_msgData.fsmCtxIdx := pl_args.refContext.fCtxIdx |
| select( pl_args.stepArgs[0] ){
|
| case ( c_LGenBaseDemo_Caller_MsgRegister ){ |
| //We describe the template set content for the Register message through config |
| //This case the template set ID can be retrieved from the test step arguments |
| var charstring vl_msg := f_LGenBaseDemo_Caller_encodeRegister(pl_args,vl_msgData) |
| f_LGenBaseDemo_Transport_sendRegister(vl_msg)
|
| }
|
| case ( c_LGenBaseDemo_Caller_MsgReRegister ){ |
| //We describe the template set content for the ReRegister message with function call |
| //This case the template set ID can be stored in component variable, |
| //and not from test step arguments |
| var charstring vl_msg := f_LGenBaseDemo_Caller_encodeReRegister(vl_msgData) |
| f_LGenBaseDemo_Transport_sendReRegister(vl_msg) |
| } |
| case ( c_LGenBaseDemo_Caller_MsgDoMsg ){ |
| //We describe the template set content for the DoMsg message through config |
| //This case the template set ID can be retrieved from the test step arguments, |
| //just like in case of Register message |
| var charstring vl_msg := f_LGenBaseDemo_Caller_encodeDoMsg(pl_args,vl_msgData) |
| f_LGenBaseDemo_Transport_sendDoMsg(vl_msg) |
| } |
| case else{
|
| //TODO error
|
| }
|
| }
|
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // Custom finish function is called when the Register traffic case finished. |
| // See the trafficStartFinish parameter of the tc "Register" in the initialization. |
| // This function demonstrates how to retrieve |
| // - the ID of the entity group associated to a traffic case |
| // - the entity count of an entity group |
| // - statistics about a traffic case |
| /////////////////////////////////////////////////////////////////////////////// |
| private function f_LGenBaseDemo_Caller_registerFinished(in integer pl_tcIdx) |
| runs on LGenBaseDemo_Caller_CT{ |
| action(%definitionId,": The traffic case register finished.") |
| var integer vl_eGrpIdx := f_EPTF_LGenBase_getEGrpIdxOfTc(pl_tcIdx) |
| var integer vl_eGrpCount := f_EPTF_LGenBase_getEGrpECount(vl_eGrpIdx) |
| //var integer vl_eGrpOffset := f_EPTF_LGenBase_getEGrpBaseOffset(vl_eGrpIdx) |
| for ( var integer vl_i := 0; vl_i < vl_eGrpCount ; vl_i := vl_i+1 ){ |
| log("entity#"&int2str(vl_i)&" Started: ",f_EPTF_LGenBase_getEntityStarts(vl_i, pl_tcIdx), |
| " Success: ",f_EPTF_LGenBase_getEntitySuccesses(vl_i, pl_tcIdx), |
| " Fail: ",f_EPTF_LGenBase_getEntityFails(vl_i, pl_tcIdx)) |
| } |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // Custom finish function is called when an entity of the Register traffic case finished. |
| // See the entityFinishActions parameter of the tc "Register" in the initialization. |
| // This function demonstrates also how to retrieve |
| // - the relative index of the entity in the entity group associated to a traffic case |
| // - statistics about an entity |
| /////////////////////////////////////////////////////////////////////////////// |
| private function f_LGenBaseDemo_Caller_entityFinishedInRegister(in integer pl_eIdx) |
| runs on LGenBaseDemo_Caller_CT{ |
| var integer vl_eIdxOfTc := f_EPTF_LGenBase_getERelIdx(pl_eIdx) |
| action("entity#",pl_eIdx," finished. Success: ", |
| f_EPTF_LGenBase_getEntitySuccesses(pl_eIdx, v_LGenBaseDemo_Caller_registerTcIdx)," Fail: ", |
| f_EPTF_LGenBase_getEntityFails(pl_eIdx, v_LGenBaseDemo_Caller_registerTcIdx)) |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // This function demonstrates how to reach LGenBase statistics using variables |
| // and function calls |
| /////////////////////////////////////////////////////////////////////////////// |
| private function f_LGenBaseDemo_Caller_createStats() |
| runs on LGenBaseDemo_Caller_CT{ |
| var charstring vl_log := "\n" |
| //-------------- |
| // Get the nr. of successfully registered entities using variable |
| //-------------- |
| // The variables containing the tc statistics have special names. |
| var charstring vl_succRegVarName := |
| f_EPTF_LGenBase_getNamePrefix( |
| c_LGenBaseDemo_Caller_entityGroupName, |
| c_LGenBaseDemo_Caller_scenarioName, |
| c_LGenBaseDemo_Caller_tcRegisterName)& |
| c_EPTF_LGenBaseStats_nameOfTcNrOfSuccesses |
| var integer vl_varId := f_EPTF_Var_getId(vl_succRegVarName) |
| var EPTF_Var_DirectContent vl_content |
| f_EPTF_Var_getContent(vl_varId, vl_content) |
| //First get the absolute index of the traffic cases |
| var integer vl_tcRegIdx := f_EPTF_LGenBase_trafficCaseId( |
| c_LGenBaseDemo_Caller_entityGroupName, |
| c_LGenBaseDemo_Caller_scenarioName, |
| c_LGenBaseDemo_Caller_tcRegisterName) |
| var integer vl_tcReRegIdx := f_EPTF_LGenBase_trafficCaseId( |
| c_LGenBaseDemo_Caller_entityGroupName, |
| c_LGenBaseDemo_Caller_scenarioName, |
| c_LGenBaseDemo_Caller_tcReRegisterName) |
| var integer vl_tcDoMsgIdx := f_EPTF_LGenBase_trafficCaseId( |
| c_LGenBaseDemo_Caller_entityGroupName, |
| c_LGenBaseDemo_Caller_scenarioName, |
| c_LGenBaseDemo_Caller_tcDoMsgName) |
| //Select an entity randomly from the successfully registered (so free) entities from the DoMsg tc. |
| //(The entitySelection of the tc had been set to random. |
| //See the f_EPTF_LGenBase_declareScenarioType3 call in the <f_LGenBaseDemo_Caller_init>.) |
| var integer vl_entityRelIdx := f_EPTF_LGenBase_getNextFreeEntity(vl_tcDoMsgIdx) |
| var integer vl_eAbsIdx := f_EPTF_LGenBase_getEAbsIdxOfTC(vl_entityRelIdx, vl_tcDoMsgIdx) |
| |
| var charstring vl_maxLatencyVarName := |
| f_EPTF_LGenBase_varNameOfTCVar(v_LGenBaseDemo_Caller_registerTcIdx, "tcMaxLatency") |
| vl_varId := f_EPTF_Var_getId(vl_maxLatencyVarName) |
| var EPTF_Var_DirectContent vl_contentLatency |
| f_EPTF_Var_getContent(vl_varId, vl_contentLatency) |
| |
| action(%definitionId,"\nNr. of registered users: ",int2str(vl_content.intVal), |
| //-------------- |
| //Get the nr. of register calls using function call |
| //-------------- |
| "\nNr. of successful Register calls: ",int2str(f_EPTF_LGenBase_getTcSuccesses(vl_tcRegIdx)), |
| //-------------- |
| //Get the nr. of reRegister calls using function call |
| //-------------- |
| "\nNr. of ReRegister calls: ",int2str(f_EPTF_LGenBase_getTcStarts(vl_tcReRegIdx)), |
| //-------------- |
| //Get the nr. of doMsg calls of a successfully registered entity |
| //-------------- |
| "\nNr. of DoMsg calls of entity# ",int2str(vl_eAbsIdx),": ", |
| int2str(f_EPTF_LGenBase_getEntityStarts(vl_entityRelIdx, vl_tcDoMsgIdx)), |
| "\nMax latency of the Register traffic case:",float2str(vl_contentLatency.floatVal) |
| ) |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // This function demonstrates how does a listener function have to look like |
| // This listener will be called when the associated event is dispatched. |
| // The listener can be registered by the f_EPTF_LGenBase_addxxxListener functions, |
| // where the xxx describes the event type. |
| // See <f_LGenBaseDemo_Caller_init> |
| /////////////////////////////////////////////////////////////////////////////// |
| private function f_LGenBaseDemo_Caller_testFinishedListener( |
| EPTF_LGenBase_ReportedEventDescriptor pl_event, |
| EPTF_IntegerList pl_listenerArgs) |
| runs on LGenBaseDemo_Caller_CT{ |
| //Create final statistics |
| f_LGenBaseDemo_Caller_createStats() |
| //Stops the test execution. |
| //When you use ExecCtrl to manage the test execution, you don't have to |
| //add such a listener, because the ExecCtrl component |
| //automatically registers one. |
| f_EPTF_Base_stopAll(pass) |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // There are two ways to use external templates: |
| // - automatically through the configuration |
| // - programmatically |
| // |
| // The external template of the Register and DoMsg messages are handled |
| // automatically, since it's declared in the config file. |
| // However, there is no external template file for the message DoMsg. |
| // |
| // The external template of the ReRegister message is handled |
| // programmatically |
| /////////////////////////////////////////////////////////////////////////////// |
| private function f_LGenBaseDemo_Caller_templateDef() |
| runs on LGenBaseDemo_Caller_CT{ |
| |
| //This statement loads the external template of the ReRegister message |
| v_LGenBaseDemo_Caller_msgReRegisterTemplIdx := f_EPTF_LGenBase_loadExtTempl( |
| tsp_LGenBaseDemo_msgReRegisterExtTemplateFile, |
| c_LGenBaseDemo_Caller_msgReRegisterExtTemplateName, |
| true) |
| |
| //Since the templates are always filled programmatically, it must be declared |
| //what kind of fields are used in all message types. |
| //The following block assignes a name pair to a set of arguments |
| //for each message type. |
| v_LGenBaseDemo_Caller_msgRegisterTemplTypeIdx := f_EPTF_LGenBase_declareTemplateType( |
| {c_LGenBaseDemo_Caller_BehaviorName, c_LGenBaseDemo_Caller_msgRegisterTemplType}, |
| {"phonePrefix", "fromNr", "phonePrefixTo", "toNr", "eIdx", "fIdx"}, |
| {}); |
| v_LGenBaseDemo_Caller_msgReRegisterTemplTypeIdx := f_EPTF_LGenBase_declareTemplateType( |
| {c_LGenBaseDemo_Caller_BehaviorName, c_LGenBaseDemo_Caller_msgReRegisterTemplType}, |
| {"phonePrefix", "fromNr", "eIdx", "fIdx"}, |
| {"phonePrefixTo", "toNr"}); |
| v_LGenBaseDemo_Caller_msgDoMsgTemplTypeIdx := f_EPTF_LGenBase_declareTemplateType( |
| {c_LGenBaseDemo_Caller_BehaviorName, c_LGenBaseDemo_Caller_msgDoMsgTemplType}, |
| {"phonePrefix", "fromNr", "eIdx", "fIdx"}, |
| {"phonePrefixTo", "toNr"}); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // The function is called by the Common component when a message arrived. |
| // Demonstrates how to dispatch an event |
| /////////////////////////////////////////////////////////////////////////////// |
| private function f_LGenBaseDemo_Caller_processResponses(in LGenBaseDemo_Msg pl_msg) |
| runs on LGenBaseDemo_Caller_CT{ |
| var boolean vl_resp := false |
| var LGenBaseDemo_Transport_MessageData vl_msgData := c_LGenBaseDemo_Transport_emptyMessageData |
| log(%definitionId&": Response message received: ",pl_msg) |
| //var integer vl_msgInput |
| var integer vl_msgId |
| if ( ischosen(pl_msg.registerResp) ){ |
| vl_resp := pl_msg.registerResp.resp |
| f_LGenBaseDemo_Caller_decodeUserData(pl_msg.registerResp.msgUserData, vl_msgData) |
| vl_msgId := pl_msg.registerResp.msgId |
| } |
| else if ( ischosen(pl_msg.reRegisterResp) ){ |
| vl_resp := pl_msg.reRegisterResp.resp |
| f_LGenBaseDemo_Caller_decodeUserData(pl_msg.reRegisterResp.msgUserData, vl_msgData) |
| vl_msgId := pl_msg.reRegisterResp.msgId |
| } |
| else if ( ischosen(pl_msg.doMsgResp) ){ |
| vl_resp := pl_msg.doMsgResp.resp |
| f_LGenBaseDemo_Caller_decodeUserData(pl_msg.doMsgResp.msgUserData, vl_msgData) |
| vl_msgId := pl_msg.doMsgResp.msgId |
| } else { |
| //TODO error |
| } |
| //Send ack |
| f_LGenBaseDemo_Transport_sendMsgAck(vl_msgId, true) |
| //Notify the entity about the reception |
| //First fill in an entity |
| var EPTF_LGenBase_ReportedEventDescriptor vl_event := c_EPTF_LGenBase_emptyReportedEventDescriptor |
| vl_event.event.bIdx := v_LGenBaseDemo_Caller_myBehavId |
| vl_event.event.target.eIdx := vl_msgData.entityIdx |
| vl_event.event.target.fsmCtxIdx := vl_msgData.fsmCtxIdx |
| if(vl_resp){ |
| vl_event.event.iIdx := c_LGenBaseDemo_Caller_InputIdxRespSuccess |
| }else{ |
| vl_event.event.iIdx := c_LGenBaseDemo_Caller_InputIdxRespFailed |
| } |
| log(%definitionId&": Dispatching input "&f_EPTF_LGenBase_iIdx2Str(v_LGenBaseDemo_Caller_myBehavId,vl_event.event.iIdx)& |
| " to the entity#"&int2str(vl_event.event.target.eIdx)) |
| f_EPTF_LGenBase_dispatchEvent(vl_event) |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // Some data are encoded into the messages sent to the Responder, and are |
| // sent back. |
| // There is no demo content |
| /////////////////////////////////////////////////////////////////////////////// |
| public function f_LGenBaseDemo_Caller_decodeUserData( |
| in charstring pl_msg, |
| out LGenBaseDemo_Transport_MessageData pl_msgData){ |
| pl_msgData := c_LGenBaseDemo_Transport_emptyMessageData |
| var charstring vl_msgChar := f_LGenBaseDemo_Caller_getUserData(pl_msg) |
| log(%definitionId&": UserData: "&vl_msgChar) |
| var integer vl_sepPos := f_strstr(vl_msgChar, c_LGenBaseDemo_Caller_msgUserDataSeparator, lengthof(c_LGenBaseDemo_Caller_msgUserDataMark)) |
| pl_msgData.entityIdx := str2int(substr(vl_msgChar,lengthof(c_LGenBaseDemo_Caller_msgUserDataMark), vl_sepPos-lengthof(c_LGenBaseDemo_Caller_msgUserDataMark))) |
| var integer vl_userDataTermPos := f_strstr(vl_msgChar, c_LGenBaseDemo_Caller_msgUserDataTerm,vl_sepPos) |
| pl_msgData.fsmCtxIdx := str2int(substr(vl_msgChar,vl_sepPos+lengthof(c_LGenBaseDemo_Caller_msgUserDataSeparator), |
| vl_userDataTermPos-vl_sepPos-lengthof(c_LGenBaseDemo_Caller_msgUserDataSeparator))) |
| log(%definitionId&": MsgData: "&log2str(pl_msgData)) |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // Some data are encoded into the messages sent to the Responder, and are |
| // sent back. |
| // There is no demo content |
| /////////////////////////////////////////////////////////////////////////////// |
| public function f_LGenBaseDemo_Caller_getUserData(in charstring pl_msg) |
| return charstring |
| { |
| var integer vl_userDataPos := f_strstr(pl_msg, c_LGenBaseDemo_Caller_msgUserDataMark, 0)//+ |
| //lengthof(c_LGenBaseDemo_Caller_msgUserDataMark) |
| //TODO check validity |
| return substr(pl_msg,vl_userDataPos,lengthof(pl_msg)-vl_userDataPos) |
| } |
| } // end of module
|