Initial TTCN-3 test suite for osmo-remsim
This adds shared infrastructure and initial test suites for
osmo-remsim-{server,client,bankd}.
Change-Id: I00034d3a991f0f881cfd8ff0bfc4557113daf830
diff --git a/remsim/REMSIM_Tests.ttcn b/remsim/REMSIM_Tests.ttcn
new file mode 100644
index 0000000..ee2d450
--- /dev/null
+++ b/remsim/REMSIM_Tests.ttcn
@@ -0,0 +1,247 @@
+module REMSIM_Tests {
+
+/* Implementation of RSPRO Client in TTCN-3.
+ * (C) 2019 by Harald Welte <laforge@gnumonks.org>
+ * All rights reserved.
+ *
+ * Released under the terms of GNU General Public License, Version 2 or
+ * (at your option) any later version.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+import from IPL4asp_Types all;
+import from RSPRO all;
+import from RSPRO_Types all;
+import from IPA_Types all;
+import from IPA_Emulation all;
+
+
+modulepar {
+ charstring mp_bankd_ip := "127.0.0.1";
+ integer mp_bankd_port := 9999;
+
+ charstring mp_server_ip := "127.0.0.1";
+ integer mp_server_port := 9998;
+
+ integer mp_rsres_port := 9997;
+}
+
+const integer NUM_CLIENT := 3;
+
+type record RSPRO_Client {
+ IPA_Emulation_CT vc_IPA,
+ IPA_CCM_Parameters ccm_pars,
+ charstring id,
+ ComponentIdentity rspro_id,
+
+ ClientSlot rspro_client_slot optional,
+ BankId rspro_bank_id optional,
+ SlotNumber rspro_bank_nslots optional
+};
+
+type component rspro_client_CT {
+ var RSPRO_Client rspro[NUM_CLIENT];
+ port IPA_RSPRO_PT RSPRO[NUM_CLIENT];
+};
+
+private altstep as_ignore_id_ack(integer i := 0) runs on rspro_client_CT {
+ [] RSPRO[i].receive(ASP_IPA_Event:{up_down := ASP_IPA_EVENT_ID_ACK}) { repeat; }
+}
+
+function f_rspro_init(inout RSPRO_Client clnt, charstring dst_host, integer dst_port,
+ ComponentIdentity rspro_id, integer i)
+runs on rspro_client_CT
+{
+ timer T := 4.0;
+
+ clnt.id := "RSPRO" & int2str(i);
+ clnt.vc_IPA := IPA_Emulation_CT.create(clnt.id);
+ clnt.ccm_pars := c_IPA_default_ccm_pars;
+ clnt.ccm_pars.name := "Osmocom TTCN-3 RSPRO client simulator";
+ clnt.rspro_id := rspro_id;
+
+ /* leave it up to the caller to set those */
+ clnt.rspro_client_slot := omit;
+ clnt.rspro_bank_id := omit;
+ clnt.rspro_bank_nslots := omit;
+
+ map(clnt.vc_IPA:IPA_PORT, system:IPA_CODEC_PT);
+ connect(clnt.vc_IPA:IPA_RSPRO_PORT, self:RSPRO[i]);
+
+ clnt.vc_IPA.start(IPA_Emulation.main_client(dst_host, dst_port, "", 10000+i, clnt.ccm_pars));
+
+ T.start;
+ alt {
+ [] RSPRO[i].receive(ASP_IPA_Event:{up_down := ASP_IPA_EVENT_UP}) { }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for ASP_IPA_EVENT_UP");
+ mtc.stop;
+ }
+ }
+ T.start;
+ alt {
+ [] RSPRO[i].receive(ASP_IPA_Event:{up_down := ASP_IPA_EVENT_ID_ACK}) { }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for ASP_IPA_EVENT_ID_ACK");
+ mtc.stop;
+ }
+ }
+
+
+ activate(as_ignore_id_ack(i));
+}
+
+function f_rspro_fini(inout RSPRO_Client clnt, integer i)
+runs on rspro_client_CT {
+ clnt.vc_IPA.stop;
+ disconnect(clnt.vc_IPA:IPA_RSPRO_PORT, self:RSPRO[i]);
+ unmap(clnt.vc_IPA:IPA_PORT, system:IPA_CODEC_PT);
+}
+
+
+function f_rspro_exp(template RsproPDU exp, integer i := 0)
+runs on rspro_client_CT return RsproPDU
+{
+ var RsproPDU pdu;
+
+ timer T := 10.0;
+ T.start;
+ alt {
+ [] RSPRO[i].receive(exp) -> value pdu {
+ setverdict(pass);
+ }
+ [] RSPRO[i].receive(RsproPDU:?) -> value pdu {
+ setverdict(fail, "Received unexpected RPSRO", pdu);
+ mtc.stop;
+ }
+ [] RSPRO[i].receive {
+ setverdict(fail, "Received unexpected != RPSRO");
+ mtc.stop;
+ }
+ [] T.timeout {
+ setverdict(fail, "Timeout waiting for ", exp);
+ mtc.stop;
+ }
+ }
+ return pdu;
+}
+
+function f_rspro_exp_disconnect(integer i := 0)
+runs on rspro_client_CT {
+ timer T := 10.0;
+ T.start;
+ alt {
+ [] RSPRO[i].receive(ASP_IPA_Event:{up_down := ASP_IPA_EVENT_DOWN}) {
+ setverdict(pass);
+ }
+ [] T.timeout {
+ setverdict(fail, "Timeout expecting disconnect");
+ mtc.stop;
+ }
+ }
+}
+
+
+function f_rspro_connect_client(integer i, template ResultCode exp_res := ok) runs on rspro_client_CT
+{
+ select (rspro[i].rspro_id.type_) {
+ case (remsimClient) {
+ RSPRO[i].send(ts_RSPRO_ConnectClientReq(rspro[i].rspro_id, rspro[i].rspro_client_slot));
+ f_rspro_exp(tr_RSPRO_ConnectClientRes(?, exp_res), i);
+ }
+ case (remsimBankd) {
+ var template IpAddress ip := ts_IPv4(mp_bankd_ip);
+ RSPRO[i].send(ts_RSPRO_ConnectBankReq(rspro[i].rspro_id, rspro[i].rspro_bank_id,
+ rspro[i].rspro_bank_nslots,
+ ts_IpPort(ip, mp_bankd_port)));
+ f_rspro_exp(tr_RSPRO_ConnectBankRes(?, exp_res), i);
+ }
+ case else {
+ setverdict(fail, "Unsupported type ", rspro[i].rspro_id.type_);
+ mtc.stop;
+ }
+ }
+}
+
+function f_rspro_connect_clients() runs on rspro_client_CT
+{
+ var integer i;
+
+ for (i := 0; i < NUM_CLIENT; i := i+1) {
+ select (rspro[i].rspro_id.type_) {
+ case (remsimClient) {
+ RSPRO[i].send(ts_RSPRO_ConnectClientReq(rspro[i].rspro_id,
+ rspro[i].rspro_client_slot));
+ }
+ case (remsimBankd) {
+ var template IpAddress ip := ts_IPv4(mp_bankd_ip);
+ RSPRO[i].send(ts_RSPRO_ConnectBankReq(rspro[i].rspro_id, rspro[i].rspro_bank_id,
+ rspro[i].rspro_bank_nslots,
+ ts_IpPort(ip, mp_bankd_port)));
+ }
+ }
+ }
+ for (i := 0; i < NUM_CLIENT; i := i+1) {
+ select (rspro[i].rspro_id.type_) {
+ case (remsimClient) {
+ f_rspro_exp(tr_RSPRO_ConnectClientRes(?, ResultCode:ok), i);
+ }
+ case (remsimBankd) {
+ f_rspro_exp(tr_RSPRO_ConnectBankRes(?, ResultCode:ok), i);
+ }
+ }
+ }
+}
+
+/* transceive a TPDU from modem to card (and back) */
+function f_rspro_xceive_mdm2card(integer idx, BankSlot bs, template (value) octetstring data,
+ template (value) TpduFlags flags) runs on rspro_client_CT return octetstring {
+ var RsproPDU rx;
+ RSPRO[idx].send(ts_RSPRO_TpduModemToCard(rspro[idx].rspro_client_slot, bs, flags, data));
+ rx := f_rspro_exp(tr_RSPRO_TpduCardToModem(bs, rspro[idx].rspro_client_slot, ?, ?));
+ return rx.msg.tpduCardToModem.data;
+}
+
+/* handle an incoming CreateMapping + ACK it */
+altstep as_rspro_create_mapping(integer i, template ClientSlot cslot := ?, template BankSlot bslot := ?,
+ template ResultCode res := ok)
+runs on rspro_client_CT {
+ var RsproPDU rx;
+ [] RSPRO[i].receive(tr_RSPRO_CreateMappingReq(cslot, bslot)) -> value rx {
+ RSPRO[i].send(ts_RSPRO_CreateMappingRes(res));
+ }
+}
+
+/* handle an incoming RemoveMapping + ACK it */
+altstep as_rspro_remove_mapping(integer i, template ClientSlot cslot := ?, template BankSlot bslot := ?,
+ template ResultCode res := ok)
+runs on rspro_client_CT {
+ var RsproPDU rx;
+ [] RSPRO[i].receive(tr_RSPRO_RemoveMappingReq(cslot, bslot)) -> value rx {
+ RSPRO[i].send(ts_RSPRO_RemoveMappingRes(res));
+ }
+}
+
+altstep as_rspro_cfg_client_id(integer i, template ClientSlot cslot := ?,
+ template (value) ResultCode res := ok)
+runs on rspro_client_CT {
+ var RsproPDU rx;
+ [] RSPRO[i].receive(tr_RSPRO_ConfigClientIdReq(cslot)) -> value rx {
+ RSPRO[i].send(ts_RSPRO_ConfigClientIdRes(res));
+ }
+}
+
+altstep as_rspro_cfg_client_bank(integer i, template BankSlot bslot := ?,
+ template IpPort ip_port := ?,
+ template (value) ResultCode res := ok)
+runs on rspro_client_CT {
+ var RsproPDU rx;
+ [] RSPRO[i].receive(tr_RSPRO_ConfigClientBankReq(bslot, ip_port)) -> value rx {
+ RSPRO[i].send(ts_RSPRO_ConfigClientBankRes(res));
+ }
+}
+
+
+
+}