Commit 89273216 authored by berge's avatar berge
Browse files

Initial module reorganisation

parent 90a554d3
Loading
Loading
Loading
Loading
+1838 −0

File added.

Preview size limit exceeded, changes collapsed.

+1077 −0

File added.

Preview size limit exceeded, changes collapsed.

+592 −0
Original line number Diff line number Diff line
module LibItsECall_Functions {
    
    import from LibItsECall_TestSystem all;
    import from LibItsECall_TypesAndValues all;
    import from LibItsECall_Pixits all;
    import from LibItsECall_Templates all;
    import from MSDASN1Module language "ASN.1:1997" all
    with {
        encode "MSDEncode";
    };
    import from LibLogger all;
    import from LibUserInterface all;
    
    /**
    * @desc Establish a call. This function waits for a call incoming event and accepts the call. An optional message box is displayed if msg is not empty.
    * @param msg optional message to display before waiting for incoming call, if the message is an empty charstring no message box is displayed
    * @return CallEstablishedEvent
    */
    function f_establishCall(in charstring p_establishMessage := "Establish IVS eCall") runs on PSAPMtc return CallEstablishedEvent {
        template ShowMessageBox localMsg modifies EstablishECallMgs := {msg := p_establishMessage}

        var CallEstablishedEvent callEstablishedEvent;
        timer t := PX_TIMEOUT;

        if (getverdict() == fail or getverdict() == inconc) {
            return null;
        }

        uiPort.send(localMsg);

        t.start;
        alt {
            // cancel was selected
            [] uiPort.receive(MessageBoxSelection:1) {
                f_stopTestcase(inconc, "Call establish aborted by user.");
            }

            // timeout occured or done was selected
            [] uiPort.receive(MessageBoxSelection:?) {
                repeat;
            }

            // received expected call incoming
            [] eCallFeedback.receive(mw_callIncoming(PX_WORKER, ?, PX_IVS_PHONE_NUMBER, PX_PSAP_PHONE_NUMBER, EXTERNAL)) {
                t.stop;
            }

            // nothing of note happened
            [] t.timeout {
                f_stopTestcase(inconc, "Timeout while waiting for call establishment!");
            }
        }

        eCallControl.send(m_callAccept(PX_WORKER));
  
        return f_expectFeedback<CallEstablishedEvent>(mw_callEstablished(PX_WORKER, ?, EXTERNAL));
    }
    
    function f_verifyMSD(in template(present) ECallMessageUnion p_expectedEcallMessage) runs on PSAPMtc {
        f_expectFeedback<InbandMsdReceivedEvent>(mw_inbandMsdReceived(PX_WORKER, ?, f_toTemplate(p_expectedEcallMessage)));

        f_expectFeedback<CallVoiceConnectionEstablishedEvent>(mw_callVoiceConnectionEstablished(PX_WORKER));
    }
    
    /**
    * @desc Clear down the call.
    *
    * @param clearDownType Type of clear down, NETWORK or APPLICATION
    * @param timeoutBeforeHangUp Time to wait until the call hang up command is issued
    */
    function f_clearDown(in ClearDownType p_clearDownType := NETWORK, in float p_timeoutBeforeHangUp := PX_CALL_HANG_UP_DELAY) runs on PSAPMtc {
        if (NETWORK == p_clearDownType) {
            if (p_timeoutBeforeHangUp != 0.0) {
                timer hangUpTimer := p_timeoutBeforeHangUp;

                hangUpTimer.start;
                hangUpTimer.timeout;
            }
      
            eCallControl.send(m_callHangUpC(PX_WORKER));
        }
        else {
            eCallControl.send(m_setAutomaticAlAck(PX_WORKER, true, CLEAR_DOWN_AL_ACK));
            f_expectFeedback<ConfigChangedEvent>(ConfigChangedEvent:?);

            eCallControl.send(m_inbandRequestMsd(PX_WORKER));
            f_verifyMSD(PX_ECALL_MESSAGE);
        }
    }
    
    /**
    * @desc Decodes the encoded eCallMessage if it valid and sets the decoded field of ECallMessageUnion,
    * otherwise the ECallMessageUnion is unchanged.
    *
    * @return ECallMessageUnion with the decoded field set (if the input is valid), otherwise unchanged
    */
    function f_expandMsd(in template(present) ECallMessageUnion p_eCallMessageUnion) return template(present) ECallMessageUnion {
        // expand msd that was given as encoded if valid, otherwise leave as is
        if (ischosen(p_eCallMessageUnion.encoded) and isvalue(p_eCallMessageUnion.encoded)) {
            var ECallMessage msd;

            if (decvalue(oct2bit(p_eCallMessageUnion.encoded), msd) == 0) {
                p_eCallMessageUnion.decoded := msd;
            }
        }

        return p_eCallMessageUnion;
    }

    function f_setMSD(ECallMessageUnion p_eCall) runs on IVSMtc {
        var ConfigParameters newConfig := {eCallMessage := p_eCall};

        eCallControl.send(m_setConfig(PX_WORKERS[0].id, {eCallMessage := p_eCall}));
    }

    function f_verifyMsdSentSuccesfully(template(present) AckValueType p_alAckValue := POSITIVE_AL_ACK) runs on IVSMtc {
        f_expectFeedback<InbandStartSignalReceivedEvent>(mw_inbandStartSignalReceived(p_worker := PX_WORKERS[0].id, p_reliable := true));

        f_verifyAckReceived(p_alAckValue);

        eCallMessage.decoded.msd.msdStructure.messageIdentifier := eCallMessage.decoded.msd.msdStructure.messageIdentifier + 1;
        f_setMSD(eCallMessage);
    }

    function f_verifyAckReceived(template(present) AckValueType p_alAckValue := POSITIVE_AL_ACK) runs on IVSMtc {
        timer t := PX_TIMEOUT;

        t.start;
        alt {
            [] eCallFeedback.receive(mw_inbandStartSignalReceived(p_worker := PX_WORKERS[0].id)) {
                t.start;
                repeat;
            }

            [] eCallFeedback.receive(mw_inbandLlAckReceived(p_worker := PX_WORKERS[0].id)) {
                t.start;
                repeat;
            }

            [] eCallFeedback.receive(mw_inbandAlAckReceived(p_worker := PX_WORKERS[0].id, p_val := p_alAckValue)) {
                t.stop;
            }

            [] t.timeout {
                f_stopTestcase(inconc, "Timeout while waiting for ACK from PSAP");
            }
        }
    }

    /**
    * @desc Same as expandMsd but only works on values
    *
    * @return ECallMessageUnion with the decoded field set (if the input is valid), otherwise unchanged
    */
    function f_expandMsdValue(in ECallMessageUnion p_eCallMessageUnion) return ECallMessageUnion {
        // expand msd that was given as encoded if valid, otherwise leave as is
        if (ischosen(p_eCallMessageUnion.encoded)) {
            var ECallMessage msd;

            if (decvalue(oct2bit(p_eCallMessageUnion.encoded), msd) == 0) {
                p_eCallMessageUnion.decoded := msd;
            }
        }

        return p_eCallMessageUnion;
    }
    
    /**
    * @desc Generates a template from the given
    *
    * @return ECallMessageUnion with the decoded field set (if the input is valid), otherwise unchanged
    */
    function f_toTemplate(in template(present) ECallMessageUnion p_eCallMessage) return template(present) ECallMessageUnion {
        p_eCallMessage := f_expandMsd(p_eCallMessage);

        if (ischosen(p_eCallMessage.decoded)) {
            var template(present) ECallMessageUnion finalECallMessageTemplate;

            template ECallMessageUnion noIdentifier modifies p_eCallMessage  := {
                decoded := {
                    id := ?,
                    msd := {
                        msdStructure := {
                            messageIdentifier := ?,
                            timestamp := ?,
                            numberOfPassengers := *
                        },
                        optionalAdditionalData := *
                    }
                }
            };

            finalECallMessageTemplate := noIdentifier;

            if (PX_IGNORE_MSD_POSITION) {
                template(present) ECallMessageUnion tmp modifies finalECallMessageTemplate := {
                    decoded := {
                        msd := {
                            msdStructure := {
                                control_ := {
                                    positionCanBeTrusted := ?//,
                                },
                                vehicleLocation := ?,
                                vehicleDirection := ?,
                                recentVehicleLocationN1 := *,
                                recentVehicleLocationN2 := *
                            }
                        }
                    }
                };

                finalECallMessageTemplate := tmp;
            }

            return finalECallMessageTemplate;
        }
        else {
            return p_eCallMessage;
        }
    }

    altstep a_unexpectedEvents() runs on PSAPMtc {
        var CallAbortedEvent callAborted;

        [] uiPort.receive {
            repeat;
        }

        [] eCallFeedback.receive(InbandNackSentEvent:?) {
            repeat;
        }

        [] eCallFeedback.receive(InbandSendSignalReceivedEvent:?) {
            repeat;
        }
        
        [] eCallFeedback.receive(mw_callHangUp(PX_WORKER, ?, EXTERNAL)) {
            f_stopTestcase(fail, "Unexpected external hang up!");
        }

        [] eCallFeedback.receive(CallRejectedEvent:?) {
            f_stopTestcase(fail, "Call was rejected!");
        }

        [] eCallFeedback.receive(CallAbortedEvent:?) -> value callAborted {
            f_stopTestcase(fail, "Call was aborted: """ & callAborted.reason & """!");
        }

        [] eCallFeedback.receive {
            f_stopTestcase(fail, "Wrong message received!");
        }
    }

    function f_stopTestcase(in verdicttype p_verdict, in charstring p_reason) runs on ECallMtc {
        setverdict(p_verdict, p_reason);

        f_configDown();

        stop;
    }
      
    function f_setSimulatorConfiguration(in ConfigParameters p_configuration) runs on PSAPMtc {
        var ConfigParameters finalConfig := modifies p_configuration := {
            t4Timer := PX_T4_TIMER,
            t6Timer := PX_T6_TIMER,
            t8Timer := PX_T8_TIMER,
            internalSubscriber := PX_INTERNAL_SUBSCRIBER
        }

        eCallControl.send(m_setConfig(PX_WORKER, {mode := IVS}));
        f_expectFeedback<ConfigChangedEvent>(p_e := mw_ivsConfigChanged(PX_WORKER,?,?), p_ignoreOtherMessages := true);

        eCallControl.send(m_setConfig(PX_WORKER, finalConfig));
        f_expectFeedback<ConfigChangedEvent>(p_e := mw_psapConfigChanged(PX_WORKER,?,finalConfig), p_ignoreOtherMessages := true);
    }

/**
* @desc Sets the initial simulator configuration, all previous state is lost.
*
* @param workerConf worker to use
* @param configuration configuration to use
*/
    function f_setSimulatorConfiguration2(in WorkerConf p_workerConf, in ConfigParameters p_configuration) runs on IVSMtc {
        var ECallMessageUnion eCallMessageExpanded := f_expandMsd(p_configuration.eCallMessage);
        var ConfigParameters finalConfig := modifies p_configuration := {
            t3Timer := PX_T3_TIMER,
            t5Timer := PX_T5_TIMER,
            t6Timer := PX_T6_TIMER,
            t7Timer := PX_T7_TIMER,
            internalSubscriber := p_workerConf.internalSubscriber,
            eCallMessage := eCallMessageExpanded
        }

        eCallMessage := eCallMessageExpanded;

        eCallControl.send(m_setConfig(PX_WORKERS[0].id, {mode := PSAP}));
        f_expectFeedback<ConfigChangedEvent>(p_e := mw_ivsConfigChanged(p_workerConf.id,?,?), p_ignoreOtherMessages := true);

        eCallControl.send(m_setConfig(PX_WORKERS[0].id, finalConfig));
        f_expectFeedback<ConfigChangedEvent>(p_e := mw_ivsConfigChanged(p_workerConf.id,?,finalConfig), p_ignoreOtherMessages := true);
    }

    function f_expectFeedback<EventType>(template EventType p_e, float p_event_timeout := PX_TIMEOUT, in boolean p_ignoreOtherMessages := false) runs on ECallMtc return EventType {
        timer t := p_event_timeout;
        var EventType received := null;

        if (getverdict() == fail or getverdict() == inconc) {
            return received;
        }

        t.start;
        alt {
            [] eCallFeedback.receive(p_e) -> value received {
                t.stop;
            }

            [p_ignoreOtherMessages] eCallFeedback.receive {
                repeat;
            }

            [] t.timeout {
                f_stopTestcase(inconc, "Timeout!");
            }
        }

        return received;
    }
      
    group altsteps {
        altstep a_default_ui_behaviour() runs on IVSMtc {
            // ignore message box selection by default
            [] uiPort.receive(MessageBoxSelection:?) {
                repeat;
            }
        }
    
    
    
        altstep a_default_behaviour() runs on IVSMtc {
            var CallAbortedEvent callAborted;
            var TimerExpiredEvent timerExpired;

            [] eCallFeedback.receive(LogMessage:?) {
                repeat;
            }

            [] eCallFeedback.receive(CallOutgoingEvent:?) {
                repeat;
            }

            [] eCallFeedback.receive(mw_callEstablished(PX_WORKERS[0].id, ?, INTERNAL)) {
                repeat;
            }

            [] eCallFeedback.receive(mw_callHangUp(PX_WORKERS[0].id, ?, INTERNAL)) {
                repeat;
            }

            [] eCallFeedback.receive(mw_inbandStateChanged(PX_WORKERS[0].id)) {
                repeat;
            }

            [] eCallFeedback.receive(mw_inbandSendSignalReceived(PX_WORKERS[0].id)) {
                repeat;
            }

            [] eCallFeedback.receive(mw_inbandStartSignalReceived(p_worker := PX_WORKERS[0].id, p_reliable := false)) {
                repeat;
            }

            [] eCallFeedback.receive(mw_inbandNackSent(PX_WORKERS[0].id)) {
                repeat;
            }
    
            [] eCallFeedback.receive(mw_inbandNackReceived(PX_WORKERS[0].id)) {
                repeat;
            }
    
            [] eCallFeedback.receive(mw_inbandLlAckSent(PX_WORKERS[0].id)) {
                repeat;
            }

            [] eCallFeedback.receive(mw_inbandAlAckSent(PX_WORKERS[0].id)) {
                repeat;
            }

            [] eCallFeedback.receive(mw_ivsConfigChanged(PX_WORKERS[0].id,?,?)) {
                repeat;
            }

            [] eCallFeedback.receive(mw_timerExpired(p_worker := PX_WORKERS[0].id)) -> value timerExpired {
                f_stopTestcase(fail, "Timer " & timerExpired.name & " expired");
            }

            [] eCallFeedback.receive(mw_callHangUp(PX_WORKERS[0].id, ?, EXTERNAL)) {
                f_stopTestcase(fail, "Unexpected external hang up!");
            }

            [] eCallFeedback.receive(CallRejectedEvent:?) {
                f_stopTestcase(fail, "Call was rejected!");
            }

            [] eCallFeedback.receive(CallAbortedEvent:?) -> value callAborted {
                f_stopTestcase(fail, "Call was aborted: """ & callAborted.reason & """!");
            }

            [] eCallFeedback.receive {
                f_stopTestcase(fail, "Wrong message received!");
                repeat;
            }
        }
    } // end altsteps
      

          
    group configurationFunctions {
	 
        function f_configIvsUp(in ConfigParameters p_configuration) runs on PSAPMtc {
            logComponent := LogComponent.create("Log Component");
            uiComponent := UIComponent.create("UIComponent");

            map(logComponent:logPort, system:logPort);
            map(self:eCallFeedback, system:psapFeedback);
            map(self:eCallControl, system:psapControl);
            connect(self:uiPort, uiComponent:uiPort);

            logComponent.start(f_logBehaviour());
            uiComponent.start(uiComponentBehaviour());

            activate(a_unexpectedEvents());
 
            f_setSimulatorConfiguration(p_configuration);

            initialized := true;
            
        } // end f_configIvsUp
      
        function f_configPsapUp(in ConfigParameters p_configuration) runs on IVSMtc {
            logComponent := LogComponent.create("LogComponent");
            uiComponent := UIComponent.create("UIComponent");

            map(logComponent:logPort, system:logPort);
            map(self:eCallControl, system:ivsControl);
            map(self:eCallFeedback, system:ivsFeedback);
            connect(self:uiPort, uiComponent:uiPort);

            logComponent.start(f_logBehaviour());
            uiComponent.start(uiComponentBehaviour());

            activate(a_default_ui_behaviour());
            activate(a_default_behaviour());

            f_setSimulatorConfiguration2(PX_WORKERS[0], p_configuration);
          
            initialized := true;
          
        } // end f_configPsapUp

        function f_configDown() runs on ECallMtc {
            if (getverdict() == none) {
                setverdict(pass);
            }

            if (not initialized) {
                return;
            }

            logComponent.stop;
            uiComponent.stop;

            disconnect(self:uiPort, uiComponent:uiPort);
            unmap(self:eCallControl, system:psapControl);
            unmap(self:eCallFeedback, system:psapFeedback);
            unmap(logComponent:logPort, system:logPort);
            
        } // end f_configDown

    }
          
    group utilityFunctions {

        /**
        * @desc The time elapsed time between <code>first</code> and <code>second</code> in milliseconds. The format of the timestamp is assumed to be <code>yyyy-MM-dd'T'HH:mm:ss.SSS</code>.
        *
        * @param first first timestamp
        * @param second second timestamp
        * @return second - first (in milliseconds)
        */
        external function fx_timeDiff(charstring p_first, charstring p_second) return integer;

        /**
        * @desc Return a <code>charstring</code> containing onliy the time from the given timestamp. The format of the timestamp is assumed to be <code>yyyy-MM-dd'T'HH:mm:ss.SSS</code>
        *
        * @param ts timestamp to extract time from
        * @return Time in the format <code>HH:mm:ss.SSS</code>
        */
        external function fx_extractTime(charstring p_ts) return charstring;

        /**
        * @desc Return the charstring representation of a float.
        */
        external function fx_float2str(float p_f) return charstring;

        /**
        * @desc Check if the time between <code>timestamp1</code> and <code>timestamp2</code> is less than <code>timeoutDuration</code>
        *
        * @param timestamp1 first timestamp (format <code>HH:mm:ss.SSS</code>)
        * @param timestamp2 second timestamp (format <code>HH:mm:ss.SSS</code>)
        * @param timeoutDuration max difference between <code>timestamp1</code> and <code>timestamp2</code>
        * @param passMsg message to use for pass verdict
        * @param failMsg message to use for fail verdict
        *
        * @return <code>true</code> if <code>timestamp2 - timestamp1 <= timeoutDuration</code>, <code>false</code> otherwise
        */
        function f_timeoutCheck(charstring p_timestamp1, charstring p_timestamp2, float p_timeoutDuration, charstring p_passMsg, charstring p_failMsg) return boolean {
            var integer diff;

            diff := fx_timeDiff(p_timestamp1, p_timestamp2);
            if (diff < 0 or diff > float2int(p_timeoutDuration * 1000.0)) {
                setverdict(fail, p_failMsg);

                return false;
            }

            setverdict(pass, p_passMsg);

            return true;
        }
    } // end utilityFunctions

    function f_userAction(in charstring p_msg) runs on ECallMtc {
        var integer button := f_messageBox("Action", p_msg, {"Done", "Cancel"}, 0);
        if (button != 0) { // message box was closed or cancel was clicked
            f_stopTestcase(inconc, "Action """ & p_msg & """ canceled by user.");
        }
    }

    function f_userVerify(in charstring p_question, in charstring p_passMessage, in charstring p_failMessage, in integer p_passOption := c_mbYes) runs on ECallMtc {
        var integer button := f_messageBoxYesNo("Verify", p_question);
        if (button == p_passOption) {
            setverdict(pass, p_passMessage);
        }
        else {
            f_stopTestcase(fail, p_failMessage);
        }
    }


    /**
    * @desc Validate that all redial attempts from the IVS terminate after <code>IVS_REDIAL_WINDOW</code> has passed.
    *
    * @verdict pass Redial attempts were not done after <code>IVS_REDIAL_WINDOW</code>
    * @verdict fail Redial attempts were done after <code>IVS_REDIAL_WINDOW</code>, or no redial attempts were registered
    */
    function f_validateRedialAttempts() runs on PSAPMtc {
        var boolean redialAttempted;
        timer redialWindowTimer := PX_IVS_REDIAL_WINDOW;
        timer guard := PX_IVS_REDIAL_GUARD_TIMER;

        // monitor redial attempts
        redialWindowTimer.start;
        alt {
            [] eCallFeedback.receive(mw_callIncoming(PX_WORKER, ?, PX_IVS_PHONE_NUMBER, PX_PSAP_PHONE_NUMBER, EXTERNAL)) {
                redialAttempted := true;
                repeat;
            }

            [] eCallFeedback.receive(mw_callCanceled(PX_WORKER, ?, EXTERNAL)) {
                repeat;
            }

            [] redialWindowTimer.timeout {
                if (not redialAttempted) {
                    f_stopTestcase(fail, "No redial was attempted!");
                }
            }
        }

        // no more redial attempts should be registered
        guard.start;
        alt {
            [] eCallFeedback.receive(mw_callIncoming(PX_WORKER, ?, PX_IVS_PHONE_NUMBER, PX_PSAP_PHONE_NUMBER, EXTERNAL)) {
                setverdict(fail, "Redial attempted after two minutes");
            }

            [] guard.timeout {
                setverdict(pass, "No more redial attempts after two minutes");
            }
        }
    }
          
}
 No newline at end of file
+139 −0

File added.

Preview size limit exceeded, changes collapsed.

+430 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading