diff options
-rw-r--r-- | bsc/BSC_Tests.cfg | 1 | ||||
-rw-r--r-- | bsc/BSC_Tests.ttcn | 11 | ||||
-rwxr-xr-x | bsc/gen_links.sh | 2 | ||||
-rw-r--r-- | library/IPA_Testing.ttcn | 170 |
4 files changed, 183 insertions, 1 deletions
diff --git a/bsc/BSC_Tests.cfg b/bsc/BSC_Tests.cfg index 175654a..4e6c40e 100644 --- a/bsc/BSC_Tests.cfg +++ b/bsc/BSC_Tests.cfg @@ -74,3 +74,4 @@ BSC_Tests.control #BSC_Tests.TC_err_82_short_msg #BSC_Tests.TC_err_84_unknown_msg #BSC_Tests.TC_ho_int +#BSC_Tests.TC_chopped_ipa_ping diff --git a/bsc/BSC_Tests.ttcn b/bsc/BSC_Tests.ttcn index 4a34310..28ade1e 100644 --- a/bsc/BSC_Tests.ttcn +++ b/bsc/BSC_Tests.ttcn @@ -30,6 +30,7 @@ import from BSSMAP_Templates all; import from IPA_Emulation all; import from IPA_CodecPort all; import from IPA_Types all; +import from IPA_Testing all; import from RSL_Types all; import from RSL_Emulation all; import from MGCP_Emulation all; @@ -2729,6 +2730,14 @@ testcase TC_dyn_pdch_osmo_act_nack() runs on test_CT { setverdict(pass); } +testcase TC_chopped_ipa_ping() runs on test_CT { + const Integers bsc_ipa_ports := {mp_bsc_rsl_port, mp_bsc_oml_port + /* TOOD: This port is failing: mp_bsc_ctrl_port */ }; + for (var integer i := 0; i < lengthof(bsc_ipa_ports); i := i + 1) { + IPA_Testing.f_run_TC_chopped_ipa_ping(mp_bsc_ip, bsc_ipa_ports[i], CONNECT_TO_SERVER); + } +} + /* Dyn PDCH todo: * activate OSMO as TCH/F * activate OSMO as TCH/H @@ -2836,6 +2845,8 @@ control { execute( TC_dyn_pdch_osmo_act_deact() ); execute( TC_dyn_pdch_osmo_act_nack() ); + execute( TC_chopped_ipa_ping() ); + /* at bottom as they might crash OsmoBSC before OS#3182 is fixed */ execute( TC_early_conn_fail() ); execute( TC_late_conn_fail() ); diff --git a/bsc/gen_links.sh b/bsc/gen_links.sh index 3e27cb1..88983d7 100755 --- a/bsc/gen_links.sh +++ b/bsc/gen_links.sh @@ -67,7 +67,7 @@ FILES="TELNETasp_PT.cc TELNETasp_PT.hh TELNETasp_PortType.ttcn" gen_links $DIR $FILES DIR=../library -FILES="General_Types.ttcn Osmocom_Types.ttcn GSM_Types.ttcn Osmocom_VTY_Functions.ttcn Native_Functions.ttcn Native_FunctionDefs.cc IPA_Types.ttcn IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc IPA_Emulation.ttcnpp L3_Templates.ttcn BSSMAP_Templates.ttcn BSSMAP_Emulation.ttcn RLCMAC_CSN1_Types.ttcn GSM_RR_Types.ttcn RSL_Types.ttcn RSL_Emulation.ttcn MGCP_Emulation.ttcn MGCP_Types.ttcn MGCP_Templates.ttcn MGCP_CodecPort.ttcn MGCP_CodecPort_CtrlFunct.ttcn MGCP_CodecPort_CtrlFunctDef.cc BSSAP_CodecPort.ttcn BSSAP_Adapter.ttcn Osmocom_CTRL_Types.ttcn Osmocom_CTRL_Functions.ttcn Osmocom_CTRL_Adapter.ttcn RTP_CodecPort.ttcn RTP_CodecPort_CtrlFunct.ttcn RTP_CodecPort_CtrlFunctDef.cc RTP_Emulation.ttcn IuUP_Types.ttcn IuUP_EncDec.cc IuUP_Emulation.ttcn SCCP_Templates.ttcn" +FILES="General_Types.ttcn Osmocom_Types.ttcn GSM_Types.ttcn Osmocom_VTY_Functions.ttcn Native_Functions.ttcn Native_FunctionDefs.cc IPA_Types.ttcn IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc IPA_Emulation.ttcnpp L3_Templates.ttcn BSSMAP_Templates.ttcn BSSMAP_Emulation.ttcn RLCMAC_CSN1_Types.ttcn GSM_RR_Types.ttcn RSL_Types.ttcn RSL_Emulation.ttcn MGCP_Emulation.ttcn MGCP_Types.ttcn MGCP_Templates.ttcn MGCP_CodecPort.ttcn MGCP_CodecPort_CtrlFunct.ttcn MGCP_CodecPort_CtrlFunctDef.cc BSSAP_CodecPort.ttcn BSSAP_Adapter.ttcn Osmocom_CTRL_Types.ttcn Osmocom_CTRL_Functions.ttcn Osmocom_CTRL_Adapter.ttcn RTP_CodecPort.ttcn RTP_CodecPort_CtrlFunct.ttcn RTP_CodecPort_CtrlFunctDef.cc RTP_Emulation.ttcn IuUP_Types.ttcn IuUP_EncDec.cc IuUP_Emulation.ttcn SCCP_Templates.ttcn IPA_Testing.ttcn" gen_links $DIR $FILES ignore_pp_results diff --git a/library/IPA_Testing.ttcn b/library/IPA_Testing.ttcn new file mode 100644 index 0000000..62aa143 --- /dev/null +++ b/library/IPA_Testing.ttcn @@ -0,0 +1,170 @@ +/* (C) 2018 by sysmocom s.f.m.c. GmbH <info@sysmocom.de> + * Author: Stefan Sperling <ssperling@sysmocom.de> + * All Rights Reserved + * + * Released under the terms of GNU General Public License, Version 2 or + * (at your option) any later version. + */ + +/* + * This module provides functions which implement IPA protocol tests. + * There are no test cases defined here. Instead, there are test functions which + * can be called by test cases in our test suites. Each such function will create + * an IPA_CT component and execute a test on this component, and expects destination + * IP address, TCP port, and connection mode parameters. Depending on the connection + * mode, a test function will either connect to an IPA server on the specified + * address and port, or listen for an IPA client on the specified address and port. + * This allows IPA tests to be run against any IPA speakers used by various test suites. + */ + +module IPA_Testing { + +import from IPL4asp_Types all; +import from IPL4asp_PortType all; +import from IPA_Types all; +import from Osmocom_Types all; + +type enumerated IPA_ConnectionMode { + CONNECT_TO_SERVER, + LISTEN_FOR_CLIENT +}; + +/* Encoded IPA messages (network byte order) */ +const octetstring ipa_msg_ping := '0001FE00'O; +const octetstring ipa_msg_pong := '0001FE01'O; + +/* A component which represents the system on which the IPA speaker is running. */ +type component system_CT { + port IPL4asp_PT IPL4; +} + +/* Main component provided by this module. */ +type component IPA_CT { + port IPL4asp_PT IPL4; + timer g_Tguard; +} + +/* This guard timer prevents us from waiting too long if the IPA TCP connection hangs. */ +private altstep as_Tguard() runs on IPA_CT { + [] g_Tguard.timeout { + setverdict(fail, "Tguard timeout"); + mtc.stop; + } +} + +/* Send an encoded IPA message across an IPA TCP connection. */ +private function f_send_ipa_data(charstring ipa_ip, integer ipa_tcp_port, ConnectionId connId, + octetstring data) runs on IPA_CT { + var IPL4asp_Types.Result res; + var ASP_SendTo asp := { + connId := connId, + remName := ipa_ip, + remPort := ipa_tcp_port, + proto := {tcp := {}}, + msg := data + }; + IPL4.send(asp); +} + +/* Match an incoming IPA message. */ +private template ASP_RecvFrom t_recvfrom(template octetstring msg) := { + connId := ?, + remName := ?, + remPort := ?, + locName := ?, + locPort := ?, + proto := {tcp := {}}, + userData := ?, + msg := msg +} + +/* Perform set up steps for a test function. */ +private function f_init(charstring ipa_ip, integer ipa_tcp_port, + IPA_ConnectionMode conmode) runs on IPA_CT return ConnectionId { + var IPL4asp_Types.Result res; + var ConnectionId connId; + + map(self:IPL4, system:IPL4); + if (conmode == CONNECT_TO_SERVER) { + /* Create an IPA connection over TCP. */ + res := IPL4asp_PortType.f_IPL4_connect(IPL4, ipa_ip, ipa_tcp_port, "", -1, 0, {tcp := {}}); + if (not ispresent(res.connId)) { + setverdict(fail, "Could not connect IPA socket to ", ipa_ip, " port ", + ipa_tcp_port, "; check your configuration"); + mtc.stop; + } + } else { + /* Listen for an incoming IPA connection on TCP. */ + res := IPL4asp_PortType.f_IPL4_listen(IPL4, ipa_ip, ipa_tcp_port, {tcp := {}}); + if (not ispresent(res.connId)) { + setverdict(fail, "Could not listen on address ", ipa_ip, " port ", + ipa_tcp_port, "; check your configuration"); + mtc.stop; + } + } + + /* + * Activate guard timer. When changing the timeout value, keep in mind + * that test functions below may wait for some amount of time, which + * this guard timer should always exceed to avoid spurious failures. + */ + g_Tguard.start(60.0); + activate(as_Tguard()); + + return res.connId; +} + +/* + * Individual test case implementations. + */ + +private function f_send_chopped_ipa_msg(charstring ipa_ip, integer ipa_tcp_port, ConnectionId connId, + octetstring msg) runs on IPA_CT { + const float delay := 6.0; + for (var integer i := 0; i < lengthof(msg); i := i + 1) { + log("sending byte ", msg[i]); + f_send_ipa_data(ipa_ip, ipa_tcp_port, connId, msg[i]); + f_sleep(delay); + } +} + +/* Send a ping message one byte at a time, waiting for TCP buffer to flush between each byte. */ +private function f_TC_chopped_ipa_ping(charstring ipa_ip, integer ipa_tcp_port, + IPA_ConnectionMode conmode) runs on IPA_CT system system_CT { + var ConnectionId connId; + var ASP_RecvFrom asp_rx; + + connId := f_init(ipa_ip, ipa_tcp_port, conmode); + + if (conmode == CONNECT_TO_SERVER) { + f_send_chopped_ipa_msg(ipa_ip, ipa_tcp_port, connId, ipa_msg_ping); + } else { + IPL4.receive(t_recvfrom(omit)) -> value asp_rx { + f_send_chopped_ipa_msg(asp_rx.remName, asp_rx.remPort, connId, ipa_msg_ping); + } + } + + /* Expect a pong response. */ + alt { + [] IPL4.receive(t_recvfrom(ipa_msg_pong)) -> value asp_rx { + log("received pong from ", asp_rx.remName, " port ", asp_rx.remPort, ": ", asp_rx.msg); + setverdict(pass); + } + [] IPL4.receive { + repeat; + } + } +} + +/* + * Public functions. + * Test suites may call these functions to create an IPA_CT component and run a test to completion. + */ + +function f_run_TC_chopped_ipa_ping(charstring ipa_ip, integer ipa_tcp_port, IPA_ConnectionMode conmode) { + var IPA_Testing.IPA_CT vc_IPA_Testing := IPA_Testing.IPA_CT.create; + vc_IPA_Testing.start(IPA_Testing.f_TC_chopped_ipa_ping(ipa_ip, ipa_tcp_port, conmode)); + vc_IPA_Testing.done; +} + +} |