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
This commit is contained in:
parent
6da25e36e6
commit
faa4292444
2
Makefile
2
Makefile
|
@ -13,7 +13,7 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
SUBDIRS=bsc bsc-nat bts ggsn_tests hlr mgw msc pcu sccp selftest sgsn sip sysinfo
|
||||
SUBDIRS=bsc bsc-nat bts ggsn_tests hlr mgw msc pcu remsim sccp selftest sgsn sip sysinfo
|
||||
|
||||
NPROC=$(shell nproc 2>/dev/null)
|
||||
ifeq ($(NPROC),)
|
||||
|
|
|
@ -22,6 +22,7 @@ ECLIPSEGIT_REPOS= titan.Libraries.TCCUsefulFunctions \
|
|||
titan.ProtocolModules.ICMP \
|
||||
titan.ProtocolModules.ICMPv6 \
|
||||
titan.ProtocolModules.IP \
|
||||
titan.ProtocolModules.JSON_v07_2006 \
|
||||
titan.ProtocolModules.L2TP \
|
||||
titan.ProtocolModules.M3UA \
|
||||
titan.ProtocolModules.SMPP \
|
||||
|
@ -30,6 +31,8 @@ ECLIPSEGIT_REPOS= titan.Libraries.TCCUsefulFunctions \
|
|||
titan.ProtocolModules.RTP \
|
||||
titan.ProtocolModules.DIAMETER_ProtocolModule_Generator \
|
||||
titan.TestPorts.Common_Components.Socket-API \
|
||||
titan.TestPorts.Common_Components.Abstract_Socket \
|
||||
titan.TestPorts.HTTPmsg \
|
||||
titan.TestPorts.IPL4asp \
|
||||
titan.TestPorts.LANL2asp \
|
||||
titan.TestPorts.PCAPasp \
|
||||
|
@ -84,6 +87,7 @@ titan.ProtocolModules.ICMP_commit= R.2.A
|
|||
titan.ProtocolModules.ICMPv6_commit= R.2.A
|
||||
titan.ProtocolModules.IP_commit= R.10.B-1-g99d0ec9
|
||||
titan.ProtocolModules.ISUP_Q.762_commit= R.8.A
|
||||
titan.ProtocolModules.JSON_v07_2006_commit= R.1.A
|
||||
titan.ProtocolModules.L2TP_commit= R.2.A
|
||||
titan.ProtocolModules.LLC_v7.1.0_commit= 2a3c09fbf7bae22f802aa88689800f38a1f3732d
|
||||
titan.ProtocolModules.MAP_commit= R.2.A-1-g79c6a3d
|
||||
|
@ -104,7 +108,9 @@ titan.ProtocolModules.SUA_commit= R.5.A
|
|||
titan.ProtocolModules.TCP_commit= R.3.A
|
||||
titan.ProtocolModules.UDP_commit= R.4.A
|
||||
titan.TestPorts.Common_Components.Socket-API_commit= R.6.A
|
||||
titan.TestPorts.Common_Components.Abstract_Socket_commit= R.9.B
|
||||
titan.TestPorts.GPIO_commit= R.3.A
|
||||
titan.TestPorts.HTTPmsg_commit= R.9.B
|
||||
titan.TestPorts.IPL4asp_commit= R.29.A
|
||||
titan.TestPorts.LANL2asp_commit= R.8.B
|
||||
titan.TestPorts.MTP3asp_commit= 1cecdad6f3641a5f19b3833703bff6e5005eff11
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
[ORDERED_INCLUDE]
|
||||
# Common configuration, shared between test suites
|
||||
"../Common.cfg"
|
||||
# testsuite specific configuration, not expected to change
|
||||
"./REMSIM_Tests.default"
|
||||
|
||||
[CONTROL]
|
||||
RemsimServer_Tests.control
|
||||
#RemsimBankd_Tests.control
|
||||
#RemsimClient_Tests.control
|
|
@ -0,0 +1,3 @@
|
|||
[TESTPORT_PARAMETERS]
|
||||
system.HTTP.http_debugging := "yes"
|
||||
system.HTTP.use_notification_ASPs := "no"
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,349 @@
|
|||
----------------------------------------------------------------------
|
||||
-- RSPRO - Remote SIM Protocol, part of Osmocom Remote SIM Suite
|
||||
-- (C) 2018 by Harald Welte <laforge@gnumonks.org>
|
||||
-- All Rights Reserved
|
||||
--
|
||||
-- SPDX-License-Identifier: GPL-2.0+
|
||||
--
|
||||
-- This program is free software; you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation; either version 2 of the License, or
|
||||
-- (at your option) any later version.
|
||||
--
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
--
|
||||
-- You should have received a copy of the GNU General Public License along
|
||||
-- with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
-- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
--
|
||||
----------------------------------------------------------------------
|
||||
|
||||
RSPRO {} DEFINITIONS
|
||||
|
||||
IMPLICIT TAGS
|
||||
|
||||
::=
|
||||
|
||||
BEGIN
|
||||
|
||||
EXPORTS
|
||||
RsproPDU
|
||||
;
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- Elementary Data Types
|
||||
----------------------------------------------------------------------
|
||||
|
||||
-- Some random ID the requestor can chose and which the client echos back in a response.
|
||||
-- This allows multiple outstanding commands in flight and matching of responses to requests.
|
||||
OperationTag ::= INTEGER(0..2147483647)
|
||||
|
||||
-- Unique identifier of a given SIM bank
|
||||
BankId ::= INTEGER(0..1023)
|
||||
|
||||
-- Unique identifier of a given client (modem)
|
||||
ClientId ::= INTEGER(0..1023)
|
||||
|
||||
ComponentType ::= ENUMERATED {
|
||||
-- client: Modems / Phones
|
||||
remsimClient (0),
|
||||
-- server: Coordination
|
||||
remsimServer (1),
|
||||
-- bank daemon: SIM cards
|
||||
remsimBankd (2)
|
||||
}
|
||||
ComponentName ::= IA5String (SIZE (1..32))
|
||||
ComponentIdentity ::= SEQUENCE {
|
||||
type ComponentType,
|
||||
name ComponentName,
|
||||
software [0] ComponentName,
|
||||
swVersion [1] ComponentName,
|
||||
hwManufacturer [2] ComponentName OPTIONAL,
|
||||
hwModel [3] ComponentName OPTIONAL,
|
||||
hwSerialNr [4] ComponentName OPTIONAL,
|
||||
hwVersion [5] ComponentName OPTIONAL,
|
||||
fwVersion [6] ComponentName OPTIONAL,
|
||||
...
|
||||
}
|
||||
|
||||
-- IP address / port details
|
||||
Ipv4Address ::= OCTET STRING (SIZE (4))
|
||||
Ipv6Address ::= OCTET STRING (SIZE (16))
|
||||
IpAddress ::= CHOICE {
|
||||
ipv4 [0] Ipv4Address,
|
||||
ipv6 [1] Ipv6Address
|
||||
}
|
||||
PortNumber ::= INTEGER (0..65535)
|
||||
IpPort ::= SEQUENCE {
|
||||
ip IpAddress,
|
||||
port PortNumber
|
||||
}
|
||||
|
||||
-- Result of a given operation
|
||||
ResultCode ::= ENUMERATED {
|
||||
ok (0),
|
||||
-- client / bank / slot ID not accepted
|
||||
illegalClientId (1),
|
||||
illegalBankId (2),
|
||||
illegalSlotId (3),
|
||||
unsupportedProtocolVersion (4),
|
||||
unknownSlotmap (5),
|
||||
|
||||
-- no card is present in given slot
|
||||
cardNotPresent (100),
|
||||
-- card is present but unresponsive in given slot
|
||||
cardUnresponsive (101),
|
||||
-- unrecoverable transmission errors detected
|
||||
cardTransmissionError (102),
|
||||
...
|
||||
}
|
||||
|
||||
ErrorCode ::= ENUMERATED {
|
||||
-- Bankd or Server has received connection form unknown client (no mapping)
|
||||
unknownClientConnected (1),
|
||||
-- unexpected disconnect (typically bankd reports client disconnect)
|
||||
unexpectedDisconnect (2),
|
||||
unexpectedProtocolVersion (3),
|
||||
...
|
||||
}
|
||||
|
||||
ErrorString ::= IA5String (SIZE (1..255))
|
||||
|
||||
ErrorSeverity ::= ENUMERATED {
|
||||
minor (1),
|
||||
major (2),
|
||||
fatal (3),
|
||||
...
|
||||
}
|
||||
|
||||
-- Slot number within a SIM bank or a client.
|
||||
SlotNumber ::= INTEGER(0..1023)
|
||||
|
||||
-- Slot identity on client (modem) side
|
||||
ClientSlot ::= SEQUENCE {
|
||||
clientId ClientId,
|
||||
slotNr SlotNumber,
|
||||
...
|
||||
}
|
||||
|
||||
-- Slot identity on SIM bank side
|
||||
BankSlot ::= SEQUENCE {
|
||||
bankId BankId,
|
||||
slotNr SlotNumber,
|
||||
...
|
||||
}
|
||||
|
||||
ATR ::= OCTET STRING (SIZE (1..55))
|
||||
|
||||
-- flags related to a TPDU in either of the two directions
|
||||
TpduFlags ::= SEQUENCE {
|
||||
-- indicates a TPDU header is present in this message
|
||||
tpduHeaderPresent BOOLEAN,
|
||||
-- indicates last part of transmission in this direction
|
||||
finalPart BOOLEAN,
|
||||
-- indicates a PB is present and we should continue with TX
|
||||
procByteContinueTx BOOLEAN,
|
||||
-- indicates a PB is present and we should continue with RX
|
||||
procByteContinueRx BOOLEAN,
|
||||
...
|
||||
}
|
||||
|
||||
--- physical state of a given slot
|
||||
SlotPhysStatus ::= SEQUENCE {
|
||||
-- is RST activated by the modem?
|
||||
resetActive [0] BOOLEAN,
|
||||
-- is VCC applied by the modem?
|
||||
vccPresent [1] BOOLEAN OPTIONAL,
|
||||
-- is CLK applied by the modem?
|
||||
clkActive [2] BOOLEAN OPTIONAL, -- not all hardware supports this
|
||||
-- is card presence signalled to the modem?
|
||||
cardPresent [3] BOOLEAN OPTIONAL,
|
||||
...
|
||||
}
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- Messages
|
||||
----------------------------------------------------------------------
|
||||
|
||||
|
||||
-- BANKD->SERVER: SIM Bank connects to central server
|
||||
ConnectBankReq ::= SEQUENCE {
|
||||
-- identity of the bank that is connecting to the server
|
||||
identity ComponentIdentity,
|
||||
-- bank number, pre-configured on bank side
|
||||
bankId BankId,
|
||||
numberOfSlots SlotNumber,
|
||||
-- IP/Port to which this bankd has bound and is listening for clients
|
||||
bound IpPort OPTIONAL,
|
||||
...
|
||||
}
|
||||
ConnectBankRes ::= SEQUENCE {
|
||||
-- identity of the server to which the bank is connecting
|
||||
identity ComponentIdentity,
|
||||
result ResultCode,
|
||||
...
|
||||
}
|
||||
|
||||
-- CLIENT->SERVER or CLIENT->BANKD
|
||||
ConnectClientReq ::= SEQUENCE {
|
||||
-- identity of the client that is connecting to the server/bankd
|
||||
identity ComponentIdentity,
|
||||
clientSlot ClientSlot OPTIONAL, -- mandatory for CL->BANKD; CL->SERVER: old identity, if any
|
||||
...
|
||||
}
|
||||
ConnectClientRes ::= SEQUENCE {
|
||||
-- identity of the bankd/server to which the client is connecting
|
||||
identity ComponentIdentity,
|
||||
result ResultCode,
|
||||
...
|
||||
}
|
||||
|
||||
-- SERVER->BANKD: create a mapping between a given Bank:Slot <-> Client:Slot
|
||||
CreateMappingReq ::= SEQUENCE {
|
||||
client ClientSlot,
|
||||
bank BankSlot,
|
||||
...
|
||||
}
|
||||
CreateMappingRes ::= SEQUENCE {
|
||||
result ResultCode,
|
||||
...
|
||||
}
|
||||
|
||||
-- SERVER->BANKD: remove a mapping between a given Bank:Slot <-> Client:Slot
|
||||
RemoveMappingReq ::= SEQUENCE {
|
||||
client ClientSlot,
|
||||
bank BankSlot,
|
||||
...
|
||||
}
|
||||
RemoveMappingRes ::= SEQUENCE {
|
||||
result ResultCode,
|
||||
...
|
||||
}
|
||||
|
||||
-- SERVER->CLIENT: set Client ID
|
||||
ConfigClientIdReq ::= SEQUENCE {
|
||||
-- server-allocated assignment of a client ID
|
||||
clientSlot ClientSlot,
|
||||
...
|
||||
}
|
||||
ConfigClientIdRes ::= SEQUENCE {
|
||||
result ResultCode,
|
||||
...
|
||||
}
|
||||
|
||||
-- SERVER->CLIENT: set BankId/Slot and IP/Port
|
||||
ConfigClientBankReq ::= SEQUENCE {
|
||||
-- server-allocated assignment of a client ID
|
||||
bankSlot BankSlot,
|
||||
-- bank to which the client shall connect
|
||||
bankd IpPort,
|
||||
...
|
||||
}
|
||||
ConfigClientBankRes ::= SEQUENCE {
|
||||
result ResultCode,
|
||||
...
|
||||
}
|
||||
|
||||
|
||||
-- BANKD->CLIENT: configure the ATR which the card emulator (client) shall send to the modem
|
||||
SetAtrReq ::= SEQUENCE {
|
||||
slot ClientSlot,
|
||||
atr ATR,
|
||||
...
|
||||
}
|
||||
SetAtrRes ::= SEQUENCE {
|
||||
result ResultCode,
|
||||
...
|
||||
}
|
||||
|
||||
-- CLIENT->BANKD: TPDU in Modem -> Card direction
|
||||
TpduModemToCard ::= SEQUENCE {
|
||||
-- we include fully-qualified bank and client slots for easier debugging
|
||||
fromClientSlot ClientSlot,
|
||||
toBankSlot BankSlot,
|
||||
flags TpduFlags,
|
||||
data OCTET STRING,
|
||||
...
|
||||
}
|
||||
|
||||
-- BANKD->CLIENT: TPDU in Card -> Modem direction
|
||||
TpduCardToModem ::= SEQUENCE {
|
||||
-- we include fully-qualified bank and client slots for easier debugging
|
||||
fromBankSlot BankSlot,
|
||||
toClientSlot ClientSlot,
|
||||
flags TpduFlags,
|
||||
data OCTET STRING,
|
||||
...
|
||||
}
|
||||
|
||||
-- CLIENT->BANKD: indciation about the current status of a client (modem side)
|
||||
ClientSlotStatusInd ::= SEQUENCE {
|
||||
fromClientSlot ClientSlot,
|
||||
toBankSlot BankSlot,
|
||||
slotPhysStatus SlotPhysStatus,
|
||||
...
|
||||
}
|
||||
|
||||
-- BANKD->CLIENT: indciation about the current status of a bank (modem side)
|
||||
BankSlotStatusInd ::= SEQUENCE {
|
||||
fromBankSlot BankSlot,
|
||||
toClientSlot ClientSlot,
|
||||
slotPhysStatus SlotPhysStatus,
|
||||
...
|
||||
}
|
||||
|
||||
-- *->SERVER: indication about some kind of error
|
||||
ErrorInd ::= SEQUENCE {
|
||||
-- whoever is detecting + sending us the error
|
||||
sender ComponentType,
|
||||
severity ErrorSeverity,
|
||||
code ErrorCode,
|
||||
-- any bank-side slot that's affected
|
||||
bankSlot [0] BankSlot OPTIONAL,
|
||||
-- any client-side slot that's affected
|
||||
clientSlot [1] ClientSlot OPTIONAL,
|
||||
-- any additional textual information
|
||||
errorString [2] ErrorString OPTIONAL,
|
||||
...
|
||||
}
|
||||
|
||||
|
||||
----------------------------------------------------------------------
|
||||
-- PDU
|
||||
----------------------------------------------------------------------
|
||||
|
||||
RsproPDUchoice ::= CHOICE {
|
||||
-- configuration + management
|
||||
connectBankReq [0] ConnectBankReq,
|
||||
connectBankRes [1] ConnectBankRes,
|
||||
connectClientReq [2] ConnectClientReq,
|
||||
connectClientRes [3] ConnectClientRes,
|
||||
createMappingReq [4] CreateMappingReq,
|
||||
createMappingRes [5] CreateMappingRes,
|
||||
removeMappingReq [6] RemoveMappingReq,
|
||||
removeMappingRes [7] RemoveMappingRes,
|
||||
configClientIdReq [8] ConfigClientIdReq,
|
||||
configClientIdRes [9] ConfigClientIdRes,
|
||||
configClientBankReq [17] ConfigClientBankReq,
|
||||
configClientBankRes [18] ConfigClientBankRes,
|
||||
errorInd [16] ErrorInd,
|
||||
-- APDUs etc.
|
||||
setAtrReq [10] SetAtrReq,
|
||||
setAtrRes [11] SetAtrRes,
|
||||
tpduModemToCard [12] TpduModemToCard,
|
||||
tpduCardToModem [13] TpduCardToModem,
|
||||
clientSlotStatusInd [14] ClientSlotStatusInd,
|
||||
bankSlotStatusInd [15] BankSlotStatusInd,
|
||||
...
|
||||
}
|
||||
|
||||
RsproPDU ::= SEQUENCE {
|
||||
version [0] INTEGER(0..32),
|
||||
tag [1] OperationTag,
|
||||
msg [2] RsproPDUchoice
|
||||
}
|
||||
|
||||
END
|
|
@ -0,0 +1,26 @@
|
|||
#include "RSPRO.hh"
|
||||
|
||||
namespace RSPRO__Types {
|
||||
|
||||
using namespace RSPRO;
|
||||
|
||||
TTCN_Module RSPRO__EncDec("RSPRO_EncDec", __DATE__, __TIME__);
|
||||
|
||||
OCTETSTRING enc__RsproPDU(const RsproPDU& pdu) {
|
||||
TTCN_Buffer buf;
|
||||
|
||||
buf.clear();
|
||||
pdu.encode(RsproPDU_descr_, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER);
|
||||
return OCTETSTRING(buf.get_len(), buf.get_data());
|
||||
}
|
||||
|
||||
RsproPDU dec__RsproPDU(const OCTETSTRING &stream) {
|
||||
TTCN_Buffer buf;
|
||||
RsproPDU pdu;
|
||||
buf.put_os(stream);
|
||||
|
||||
pdu.decode(RsproPDU_descr_, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
|
||||
return pdu;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
module RSPRO_Server {
|
||||
|
||||
/* Utility functions implementing an RSRPO server.
|
||||
* (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;
|
||||
|
||||
|
||||
type record RSPRO_Server {
|
||||
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
|
||||
};
|
||||
|
||||
const integer NUM_SERVER := 2;
|
||||
|
||||
type component rspro_server_CT {
|
||||
var RSPRO_Server g_rspro_srv[NUM_SERVER];
|
||||
port IPA_RSPRO_PT RSPRO_SRV[NUM_SERVER];
|
||||
};
|
||||
|
||||
|
||||
altstep as_ignore_id_ack(integer i) runs on rspro_server_CT {
|
||||
[] RSPRO_SRV[i].receive(ASP_IPA_Event:{up_down := ASP_IPA_EVENT_ID_ACK}) { repeat; }
|
||||
}
|
||||
|
||||
|
||||
function f_rspro_srv_exp_connect(integer i)
|
||||
runs on rspro_server_CT
|
||||
{
|
||||
timer T := 20.0;
|
||||
T.start;
|
||||
alt {
|
||||
[] RSPRO_SRV[i].receive(ASP_IPA_Event:{up_down := ASP_IPA_EVENT_UP}) { }
|
||||
[] T.timeout {
|
||||
setverdict(fail, "Timeout waiting for ASP_IPA_EVENT_UP");
|
||||
mtc.stop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function f_rspro_srv_init(integer i, charstring bind_host, integer bind_port,
|
||||
ComponentIdentity rspro_id, boolean exp_connect := true)
|
||||
runs on rspro_server_CT
|
||||
{
|
||||
g_rspro_srv[i].id := "RSPRO_SRV" & int2str(i);
|
||||
g_rspro_srv[i].vc_IPA := IPA_Emulation_CT.create(g_rspro_srv[i].id);
|
||||
g_rspro_srv[i].ccm_pars := c_IPA_default_ccm_pars;
|
||||
g_rspro_srv[i].ccm_pars.name := "Osmocom TTCN-3 RSPRO server simulator";
|
||||
g_rspro_srv[i].rspro_id := rspro_id;
|
||||
|
||||
map(g_rspro_srv[i].vc_IPA:IPA_PORT, system:IPA_CODEC_PT);
|
||||
connect(g_rspro_srv[i].vc_IPA:IPA_RSPRO_PORT, self:RSPRO_SRV[i]);
|
||||
|
||||
g_rspro_srv[i].vc_IPA.start(IPA_Emulation.main_server(bind_host, bind_port));
|
||||
|
||||
activate(as_ignore_id_ack(i));
|
||||
|
||||
if (exp_connect) {
|
||||
f_rspro_srv_exp_connect(i);
|
||||
}
|
||||
}
|
||||
|
||||
function f_rspro_srv_fini(integer i)
|
||||
runs on rspro_server_CT
|
||||
{
|
||||
g_rspro_srv[i].vc_IPA.stop;
|
||||
disconnect(g_rspro_srv[i].vc_IPA:IPA_RSPRO_PORT, self:RSPRO_SRV[i]);
|
||||
unmap(g_rspro_srv[i].vc_IPA:IPA_PORT, system:IPA_CODEC_PT);
|
||||
}
|
||||
|
||||
|
||||
function f_rspro_srv_restart(integer i, charstring bind_host, integer bind_port)
|
||||
runs on rspro_server_CT
|
||||
{
|
||||
g_rspro_srv[i].vc_IPA.stop;
|
||||
g_rspro_srv[i].vc_IPA.start(IPA_Emulation.main_server(bind_host, bind_port));
|
||||
}
|
||||
|
||||
|
||||
function f_rspro_srv_exp(template RsproPDU exp, integer i := 0, float tout := 10.0)
|
||||
runs on rspro_server_CT return RsproPDU
|
||||
{
|
||||
var RsproPDU pdu;
|
||||
|
||||
timer T := tout;
|
||||
T.start;
|
||||
alt {
|
||||
[] RSPRO_SRV[i].receive(exp) -> value pdu {
|
||||
setverdict(pass);
|
||||
}
|
||||
[] RSPRO_SRV[i].receive(RsproPDU:?) -> value pdu {
|
||||
setverdict(fail, "Received unexpected RPSRO", pdu, " instead of ", exp);
|
||||
mtc.stop;
|
||||
}
|
||||
[] as_ignore_id_ack(i) { repeat; }
|
||||
[] RSPRO_SRV[i].receive {
|
||||
setverdict(fail, "Received unexpected != RPSRO");
|
||||
mtc.stop;
|
||||
}
|
||||
[] T.timeout {
|
||||
setverdict(fail, "Timeout waiting for ", exp);
|
||||
mtc.stop;
|
||||
}
|
||||
}
|
||||
return pdu;
|
||||
}
|
||||
|
||||
function f_rspro_srv_create_slotmap(ClientSlot cslot, BankSlot bslot,
|
||||
template ResultCode exp_res := ok, integer i := 0)
|
||||
runs on rspro_server_CT
|
||||
{
|
||||
RSPRO_SRV[i].send(ts_RSPRO_CreateMappingReq(cslot, bslot));
|
||||
f_rspro_srv_exp(tr_RSPRO_CreateMappingRes(exp_res), i);
|
||||
}
|
||||
|
||||
function f_rspro_srv_remove_slotmap(ClientSlot cslot, BankSlot bslot,
|
||||
template ResultCode exp_res := ok, integer i := 0)
|
||||
runs on rspro_server_CT
|
||||
{
|
||||
RSPRO_SRV[i].send(ts_RSPRO_RemoveMappingReq(cslot, bslot));
|
||||
f_rspro_srv_exp(tr_RSPRO_RemoveMappingRes(exp_res), i);
|
||||
}
|
||||
|
||||
function f_rspro_config_client_bank(template (value) BankSlot bank_slot,
|
||||
template (value) IpPort bank_iport,
|
||||
template ResultCode exp_res := ok, integer i := 0)
|
||||
runs on rspro_server_CT {
|
||||
RSPRO_SRV[i].send(ts_RSPRO_ConfigClientBankReq(bank_slot, bank_iport));
|
||||
f_rspro_srv_exp(tr_RSPRO_ConfigClientBankRes(exp_res));
|
||||
}
|
||||
|
||||
|
||||
altstep as_connectBankReq(template ComponentIdentity comp_id := tr_CompId(remsimBankd, ?,
|
||||
"remsim-bankd", ?),
|
||||
template BankId bid := ?,
|
||||
template SlotNumber nslots := ?,
|
||||
ResultCode res := ok, integer i := 0)
|
||||
runs on rspro_server_CT {
|
||||
[] RSPRO_SRV[i].receive(tr_RSPRO_ConnectBankReq(comp_id, bid, nslots)) {
|
||||
RSPRO_SRV[i].send(ts_RSPRO_ConnectBankRes(g_rspro_srv[i].rspro_id, res));
|
||||
}
|
||||
}
|
||||
|
||||
altstep as_connectClientReq(template ComponentIdentity comp_id := tr_CompId(remsimClient, ?,
|
||||
"remsim-client", ?),
|
||||
template ClientSlot cslot := *,
|
||||
ResultCode res := ok, integer i := 0)
|
||||
runs on rspro_server_CT {
|
||||
[] RSPRO_SRV[i].receive(tr_RSPRO_ConnectClientReq(comp_id, cslot)) {
|
||||
RSPRO_SRV[i].send(ts_RSPRO_ConnectClientRes(g_rspro_srv[i].rspro_id, res));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,375 @@
|
|||
module RSPRO_Types {
|
||||
|
||||
/* Templates and utility functions for the RSPRO protocol.
|
||||
* (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 RSPRO all;
|
||||
import from Native_Functions all;
|
||||
|
||||
template ResultCode tr_Status_ok_or_nocard := (ok, cardNotPresent);
|
||||
|
||||
external function dec_RsproPDU(in octetstring stream) return RsproPDU;
|
||||
external function enc_RsproPDU(in RsproPDU pdu) return octetstring;
|
||||
|
||||
type integer RsproVersion (0..32);
|
||||
|
||||
template (value) BankSlot ts_BankSlot(template (value) BankId bid,
|
||||
template (value) SlotNumber slot) := {
|
||||
bankId := bid,
|
||||
slotNr := slot
|
||||
}
|
||||
|
||||
template (value) ClientSlot ts_ClientSlot(template (value) ClientId cid,
|
||||
template (value) SlotNumber slot) := {
|
||||
clientId := cid,
|
||||
slotNr := slot
|
||||
}
|
||||
|
||||
template (value) ComponentIdentity ts_CompId(template (value) ComponentType ctype,
|
||||
template (value) ComponentName name,
|
||||
template (value) ComponentName sw := "TTCN3",
|
||||
template (value) ComponentName sw_version := "0.1") := {
|
||||
type_ := ctype,
|
||||
name := name,
|
||||
software := sw,
|
||||
swVersion := sw_version,
|
||||
hwManufacturer := "sysmocom",
|
||||
hwModel := omit,
|
||||
hwSerialNr := omit,
|
||||
hwVersion := omit,
|
||||
fwVersion := omit
|
||||
}
|
||||
template ComponentIdentity tr_CompId(template ComponentType ctype,
|
||||
template ComponentName name,
|
||||
template ComponentName sw := "TTCN3",
|
||||
template ComponentName sw_version := "0.1") := {
|
||||
type_ := ctype,
|
||||
name := name,
|
||||
software := sw,
|
||||
swVersion := sw_version,
|
||||
hwManufacturer := *,
|
||||
hwModel := *,
|
||||
hwSerialNr := *,
|
||||
hwVersion := *,
|
||||
fwVersion := *
|
||||
}
|
||||
|
||||
template (value) IpPort ts_IpPort(template (value) IpAddress ip,
|
||||
template (value) PortNumber port_nr) := {
|
||||
ip := ip,
|
||||
port_ := port_nr
|
||||
}
|
||||
template IpPort tr_IpPort(template IpAddress ip, template PortNumber port_nr) := {
|
||||
ip := ip,
|
||||
port_ := port_nr
|
||||
}
|
||||
|
||||
template (value) IpAddress ts_IPv4(charstring ip_str) := {
|
||||
ipv4 := f_inet_addr(ip_str)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template (value) RsproPDU ts_RSPRO(template (value) RsproPDUchoice msg,
|
||||
template (value) RsproVersion version := 2,
|
||||
template (value) OperationTag tag := 0) := {
|
||||
version := version,
|
||||
tag := tag,
|
||||
msg := msg
|
||||
}
|
||||
|
||||
template RsproPDU tr_RSPRO(template RsproPDUchoice msg,
|
||||
template RsproVersion version := 2,
|
||||
template OperationTag tag := ?) := {
|
||||
version := version,
|
||||
tag := tag,
|
||||
msg := msg
|
||||
}
|
||||
|
||||
|
||||
template (value) RsproPDU ts_RSPRO_ConnectClientReq(template (value) ComponentIdentity id,
|
||||
template (omit) ClientSlot clslot) :=
|
||||
ts_RSPRO(RsproPDUchoice:{
|
||||
connectClientReq := {
|
||||
identity := id,
|
||||
clientSlot := clslot
|
||||
}
|
||||
});
|
||||
template RsproPDU tr_RSPRO_ConnectClientReq(template ComponentIdentity id,
|
||||
template ClientSlot clslot) :=
|
||||
tr_RSPRO(RsproPDUchoice:{
|
||||
connectClientReq := {
|
||||
identity := id,
|
||||
clientSlot := clslot
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
template (value) RsproPDU ts_RSPRO_ConnectClientRes(template (value) ComponentIdentity id,
|
||||
template (value) ResultCode res) :=
|
||||
ts_RSPRO(RsproPDUchoice:{
|
||||
connectClientRes := {
|
||||
identity := id,
|
||||
result := res
|
||||
}
|
||||
});
|
||||
template RsproPDU tr_RSPRO_ConnectClientRes(template ComponentIdentity id := ?,
|
||||
template ResultCode res := ?) :=
|
||||
tr_RSPRO(RsproPDUchoice:{
|
||||
connectClientRes := {
|
||||
identity := id,
|
||||
result := res
|
||||
}
|
||||
});
|
||||
|
||||
template (value) RsproPDU ts_RSPRO_ConnectBankReq(template (value) ComponentIdentity id,
|
||||
template (value) BankId bid,
|
||||
template (value) SlotNumber nslots,
|
||||
template (omit) IpPort bound) :=
|
||||
ts_RSPRO(RsproPDUchoice:{
|
||||
connectBankReq := {
|
||||
identity := id,
|
||||
bankId := bid,
|
||||
numberOfSlots := nslots,
|
||||
bound := bound
|
||||
}
|
||||
});
|
||||
template RsproPDU tr_RSPRO_ConnectBankReq(template ComponentIdentity id,
|
||||
template BankId bid,
|
||||
template SlotNumber nslots,
|
||||
template IpPort bound := *) :=
|
||||
tr_RSPRO(RsproPDUchoice:{
|
||||
connectBankReq := {
|
||||
identity := id,
|
||||
bankId := bid,
|
||||
numberOfSlots := nslots,
|
||||
bound := *
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
template (value) RsproPDU ts_RSPRO_ConnectBankRes(template (value) ComponentIdentity id,
|
||||
template (value) ResultCode res) :=
|
||||
ts_RSPRO(RsproPDUchoice:{
|
||||
connectBankRes := {
|
||||
identity := id,
|
||||
result := res
|
||||
}
|
||||
});
|
||||
template RsproPDU tr_RSPRO_ConnectBankRes(template ComponentIdentity id := ?,
|
||||
template ResultCode res := ?) :=
|
||||
tr_RSPRO(RsproPDUchoice:{
|
||||
connectBankRes := {
|
||||
identity := id,
|
||||
result := res
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
template (value) RsproPDU ts_RSPRO_SetAtrReq(template (value) ClientSlot clslot,
|
||||
template (value) ATR atr) :=
|
||||
ts_RSPRO(RsproPDUchoice:{
|
||||
setAtrReq := {
|
||||
slot := clslot,
|
||||
atr := atr
|
||||
}
|
||||
});
|
||||
template RsproPDU tr_RSPRO_SetAtrReq(template ClientSlot clslot := ?,
|
||||
template ATR atr := ?) :=
|
||||
tr_RSPRO(RsproPDUchoice:{
|
||||
setAtrReq := {
|
||||
slot := clslot,
|
||||
atr := atr
|
||||
}
|
||||
});
|
||||
|
||||
template (value) RsproPDU ts_RSPRO_SetAtrRes(template (value) ResultCode res) :=
|
||||
ts_RSPRO(RsproPDUchoice:{
|
||||
setAtrRes := {
|
||||
result := res
|
||||
}
|
||||
});
|
||||
template RsproPDU tr_RSPRO_SetAtrRes(template ResultCode res := ?) :=
|
||||
tr_RSPRO(RsproPDUchoice:{
|
||||
setAtrRes := {
|
||||
result := res
|
||||
}
|
||||
});
|
||||
|
||||
template (value) RsproPDU ts_RSPRO_TpduModemToCard(template (value) ClientSlot from_clslot,
|
||||
template (value) BankSlot to_bslot,
|
||||
template (value) TpduFlags flags,
|
||||
template (value) octetstring data) :=
|
||||
ts_RSPRO(RsproPDUchoice:{
|
||||
tpduModemToCard := {
|
||||
fromClientSlot := from_clslot,
|
||||
toBankSlot := to_bslot,
|
||||
flags := flags,
|
||||
data := data
|
||||
}
|
||||
});
|
||||
template RsproPDU tr_RSPRO_TpduModemToCard(template ClientSlot from_clslot := ?,
|
||||
template BankSlot to_bslot := ?,
|
||||
template TpduFlags flags := ?,
|
||||
template octetstring data := ?) :=
|
||||
tr_RSPRO(RsproPDUchoice:{
|
||||
tpduModemToCard := {
|
||||
fromClientSlot := from_clslot,
|
||||
toBankSlot := to_bslot,
|
||||
flags := flags,
|
||||
data := data
|
||||
}
|
||||
});
|
||||
|
||||
template (value) RsproPDU ts_RSPRO_TpduCardToModem(template (value) BankSlot from_bslot,
|
||||
template (value) ClientSlot to_clslot,
|
||||
template (value) TpduFlags flags,
|
||||
template (value) octetstring data) :=
|
||||
ts_RSPRO(RsproPDUchoice:{
|
||||
tpduCardToModem := {
|
||||
fromBankSlot := from_bslot,
|
||||
toClientSlot := to_clslot,
|
||||
flags := flags,
|
||||
data := data
|
||||
}
|
||||
});
|
||||
template RsproPDU tr_RSPRO_TpduCardToModem(template BankSlot from_bslot := ?,
|
||||
template ClientSlot to_clslot := ?,
|
||||
template TpduFlags flags := ?,
|
||||
template octetstring data := ?) :=
|
||||
tr_RSPRO(RsproPDUchoice:{
|
||||
tpduCardToModem := {
|
||||
fromBankSlot := from_bslot,
|
||||
toClientSlot := to_clslot,
|
||||
flags := flags,
|
||||
data := data
|
||||
}
|
||||
});
|
||||
|
||||
template (value) RsproPDU ts_RSPRO_CreateMappingReq(template (value) ClientSlot cslot,
|
||||
template (value) BankSlot bslot) :=
|
||||
ts_RSPRO(RsproPDUchoice:{
|
||||
createMappingReq := {
|
||||
client := cslot,
|
||||
bank := bslot
|
||||
}
|
||||
});
|
||||
template RsproPDU tr_RSPRO_CreateMappingReq(template ClientSlot cslot,
|
||||
template BankSlot bslot) :=
|
||||
tr_RSPRO(RsproPDUchoice:{
|
||||
createMappingReq := {
|
||||
client := cslot,
|
||||
bank := bslot
|
||||
}
|
||||
});
|
||||
|
||||
template (value) RsproPDU ts_RSPRO_CreateMappingRes(template (value) ResultCode res) :=
|
||||
ts_RSPRO(RsproPDUchoice:{
|
||||
createMappingRes := {
|
||||
result := res
|
||||
}
|
||||
});
|
||||
template RsproPDU tr_RSPRO_CreateMappingRes(template ResultCode res) :=
|
||||
tr_RSPRO(RsproPDUchoice:{
|
||||
createMappingRes := {
|
||||
result := res
|
||||
}
|
||||
});
|
||||
|
||||
template (value) RsproPDU ts_RSPRO_RemoveMappingReq(template (value) ClientSlot cslot,
|
||||
template (value) BankSlot bslot) :=
|
||||
ts_RSPRO(RsproPDUchoice:{
|
||||
removeMappingReq := {
|
||||
client := cslot,
|
||||
bank := bslot
|
||||
}
|
||||
});
|
||||
template RsproPDU tr_RSPRO_RemoveMappingReq(template ClientSlot cslot,
|
||||
template BankSlot bslot) :=
|
||||
tr_RSPRO(RsproPDUchoice:{
|
||||
removeMappingReq := {
|
||||
client := cslot,
|
||||
bank := bslot
|
||||
}
|
||||
});
|
||||
|
||||
template (value) RsproPDU ts_RSPRO_RemoveMappingRes(template (value) ResultCode res) :=
|
||||
ts_RSPRO(RsproPDUchoice:{
|
||||
removeMappingRes := {
|
||||
result := res
|
||||
}
|
||||
});
|
||||
template RsproPDU tr_RSPRO_RemoveMappingRes(template ResultCode res) :=
|
||||
tr_RSPRO(RsproPDUchoice:{
|
||||
removeMappingRes := {
|
||||
result := res
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
template (value) RsproPDU ts_RSPRO_ConfigClientIdReq(template (value) ClientSlot cslot) :=
|
||||
ts_RSPRO(RsproPDUchoice: {
|
||||
configClientIdReq := {
|
||||
clientSlot := cslot
|
||||
}
|
||||
});
|
||||
template RsproPDU tr_RSPRO_ConfigClientIdReq(template ClientSlot cslot) :=
|
||||
tr_RSPRO(RsproPDUchoice: {
|
||||
configClientIdReq := {
|
||||
clientSlot := cslot
|
||||
}
|
||||
});
|
||||
|
||||
template (value) RsproPDU ts_RSPRO_ConfigClientIdRes(template (value) ResultCode res) :=
|
||||
ts_RSPRO(RsproPDUchoice:{
|
||||
configClientIdRes := {
|
||||
result := res
|
||||
}
|
||||
});
|
||||
template RsproPDU tr_RSPRO_ConfigClientIdRes(template ResultCode res) :=
|
||||
tr_RSPRO(RsproPDUchoice:{
|
||||
configClientIdRes := {
|
||||
result := res
|
||||
}
|
||||
});
|
||||
|
||||
template (value) RsproPDU ts_RSPRO_ConfigClientBankReq(template (value) BankSlot bslot,
|
||||
template (value) IpPort ip_port) :=
|
||||
ts_RSPRO(RsproPDUchoice: {
|
||||
configClientBankReq := {
|
||||
bankSlot := bslot,
|
||||
bankd := ip_port
|
||||
}
|
||||
});
|
||||
template RsproPDU tr_RSPRO_ConfigClientBankReq(template BankSlot bslot,
|
||||
template IpPort ip_port) :=
|
||||
tr_RSPRO(RsproPDUchoice: {
|
||||
configClientBankReq := {
|
||||
bankSlot := bslot,
|
||||
bankd := ip_port
|
||||
}
|
||||
});
|
||||
|
||||
template (value) RsproPDU ts_RSPRO_ConfigClientBankRes(template (value) ResultCode res) :=
|
||||
ts_RSPRO(RsproPDUchoice:{
|
||||
configClientBankRes := {
|
||||
result := res
|
||||
}
|
||||
});
|
||||
template RsproPDU tr_RSPRO_ConfigClientBankRes(template ResultCode res) :=
|
||||
tr_RSPRO(RsproPDUchoice:{
|
||||
configClientBankRes := {
|
||||
result := res
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
module RSRES {
|
||||
|
||||
/* Implementation of the REmote Sim RESt (RSRES) JSON data types 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 RSPRO all;
|
||||
|
||||
/* resembles "enum remsim_server_client_fsm_state" */
|
||||
type enumerated ConnectionState {
|
||||
INIT,
|
||||
ESTABLISHED,
|
||||
CONNECTED_CLIENT,
|
||||
CONNECTED_BANKD
|
||||
};
|
||||
|
||||
type record JsBank {
|
||||
charstring peer,
|
||||
ConnectionState state,
|
||||
ComponentIdentity component_id,
|
||||
BankId bankId,
|
||||
SlotNumber numberOfSlots
|
||||
};
|
||||
type record of JsBank JsBanks;
|
||||
|
||||
template JsBank tr_JsBank(template ConnectionState state,
|
||||
template ComponentIdentity comp_id,
|
||||
template BankId bank_id,
|
||||
template SlotNumber num_of_slots) := {
|
||||
peer := ?,
|
||||
state := state,
|
||||
component_id := comp_id,
|
||||
bankId := bank_id,
|
||||
numberOfSlots := num_of_slots
|
||||
}
|
||||
|
||||
type record JsClient {
|
||||
charstring peer,
|
||||
ConnectionState state,
|
||||
ComponentIdentity component_id
|
||||
};
|
||||
type record of JsClient JsClients;
|
||||
|
||||
template JsClient tr_JsClient(template ConnectionState state,
|
||||
template ComponentIdentity comp_id) := {
|
||||
peer := ?,
|
||||
state := state,
|
||||
component_id := comp_id
|
||||
}
|
||||
|
||||
/* resembles "enum slot_mapping_state" */
|
||||
type enumerated SlotmapState {
|
||||
NEW,
|
||||
UNACKNOWLEDGED,
|
||||
ACTIVE,
|
||||
DELETE_REQ,
|
||||
DELETING
|
||||
};
|
||||
|
||||
type record JsSlotmap {
|
||||
BankSlot bank,
|
||||
ClientSlot client,
|
||||
SlotmapState state optional
|
||||
};
|
||||
type record of JsSlotmap JsSlotmaps;
|
||||
|
||||
template (value) JsSlotmap ts_JsSlotmap(template (value) BankSlot bslot,
|
||||
template (value) ClientSlot cslot,
|
||||
template (omit) SlotmapState state := omit) := {
|
||||
bank := bslot,
|
||||
client := cslot,
|
||||
state := state
|
||||
}
|
||||
template JsSlotmap tr_JsSlotmap(template BankSlot bslot,
|
||||
template ClientSlot cslot,
|
||||
template SlotmapState state := ?) := {
|
||||
bank := bslot,
|
||||
client := cslot,
|
||||
state := state
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* root JSON type expressing what remsim-server can return */
|
||||
type record JsRoot {
|
||||
JsClients clients optional,
|
||||
JsBanks banks optional,
|
||||
JsSlotmaps slotmaps optional
|
||||
};
|
||||
|
||||
external function f_enc_JsRoot(in JsRoot inp) return octetstring
|
||||
with { extension "prototype(convert) encode(JSON)" }
|
||||
external function f_dec_JsRoot(in octetstring inp) return JsRoot
|
||||
with { extension "prototype(convert) decode(JSON)" }
|
||||
|
||||
external function f_enc_JsSlotmap(in JsSlotmap inp) return octetstring
|
||||
with { extension "prototype(convert) encode(JSON)" }
|
||||
external function f_dec_JsSlotmap(in octetstring inp) return JsSlotmap
|
||||
with { extension "prototype(convert) decode(JSON)" }
|
||||
|
||||
|
||||
|
||||
} with { encode "JSON" }
|
|
@ -0,0 +1,298 @@
|
|||
module RemsimBankd_Tests {
|
||||
|
||||
/* Integration Tests for osmo-remsim-bankd
|
||||
* (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
|
||||
*
|
||||
* This test suite tests osmo-remsim-bankd by attaching to the external interfaces
|
||||
* such as RSPRO for simulated clients + server.
|
||||
*/
|
||||
|
||||
import from Osmocom_Types all;
|
||||
import from IPA_Emulation all;
|
||||
import from Misc_Helpers all;
|
||||
|
||||
import from RSPRO all;
|
||||
import from RSRES all;
|
||||
import from RSPRO_Types all;
|
||||
import from RSPRO_Server all;
|
||||
import from REMSIM_Tests all;
|
||||
|
||||
modulepar {
|
||||
integer mp_bank_id := 1;
|
||||
integer mp_num_slots := 8;
|
||||
}
|
||||
|
||||
/* We implement a RSPRO server to simulate the remsim-server and a
|
||||
RSPRO client to simulate a remsim-client connecting to bankd */
|
||||
type component bankd_test_CT extends rspro_server_CT, rspro_client_CT {
|
||||
}
|
||||
|
||||
private function f_init(boolean start_client := false) runs on bankd_test_CT {
|
||||
var ComponentIdentity srv_comp_id := valueof(ts_CompId(remsimServer, "ttcn-server"));
|
||||
|
||||
f_rspro_srv_init(0, mp_server_ip, mp_server_port, srv_comp_id);
|
||||
|
||||
if (start_client) {
|
||||
f_init_client(0);
|
||||
}
|
||||
}
|
||||
|
||||
private function f_init_client(integer i := 0) runs on rspro_client_CT {
|
||||
var ComponentIdentity clnt_comp_id := valueof(ts_CompId(remsimClient, "ttcn-client"));
|
||||
f_rspro_init(rspro[0], mp_bankd_ip, mp_bankd_port, clnt_comp_id, 0);
|
||||
rspro[0].rspro_client_slot := { clientId := 23+i, slotNr := 0 };
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Test if the bankd disconnects the TCP/IPA session if we don't respond to connectBankReq */
|
||||
testcase TC_connectBankReq_timeout() runs on bankd_test_CT {
|
||||
timer T := 20.0;
|
||||
f_init();
|
||||
|
||||
f_rspro_srv_exp(tr_RSPRO_ConnectBankReq(?, ?, ?));
|
||||
T.start;
|
||||
alt {
|
||||
[] RSPRO_SRV[0].receive(ASP_IPA_Event:{up_down := ASP_IPA_EVENT_DOWN}) {
|
||||
setverdict(pass);
|
||||
}
|
||||
[] RSPRO_SRV[0].receive { repeat; }
|
||||
[] T.timeout {
|
||||
setverdict(fail, "Timeout waiting for disconnect");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* accept an inbound connection from bankd to simulated server */
|
||||
testcase TC_connectBankReq() runs on bankd_test_CT {
|
||||
f_init();
|
||||
|
||||
as_connectBankReq(bid := mp_bank_id, nslots := mp_num_slots);
|
||||
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
|
||||
}
|
||||
|
||||
/* attempt to create a mapping */
|
||||
testcase TC_createMapping() runs on bankd_test_CT {
|
||||
f_init();
|
||||
as_connectBankReq(bid := mp_bank_id, nslots := mp_num_slots);
|
||||
var BankSlot bs := { bankId := mp_bank_id, slotNr := 0 };
|
||||
var ClientSlot cs := { clientId := 23, slotNr := 42 };
|
||||
f_rspro_srv_create_slotmap(cs, bs);
|
||||
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
|
||||
}
|
||||
|
||||
/* attempt to create a mapping for a slot that already has a mapping */
|
||||
testcase TC_createMapping_busySlot() runs on bankd_test_CT {
|
||||
f_init();
|
||||
as_connectBankReq(bid := mp_bank_id, nslots := mp_num_slots);
|
||||
var BankSlot bs := { bankId := mp_bank_id, slotNr := 0 };
|
||||
var ClientSlot cs := { clientId := 23, slotNr := 42 };
|
||||
f_rspro_srv_create_slotmap(cs, bs);
|
||||
f_rspro_srv_create_slotmap(cs, bs, exp_res := illegalSlotId);
|
||||
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
|
||||
}
|
||||
|
||||
/* attempt to create a mapping for an out-of-range slot number */
|
||||
testcase TC_createMapping_invalidSlot() runs on bankd_test_CT {
|
||||
f_init();
|
||||
as_connectBankReq(bid := mp_bank_id, nslots := mp_num_slots);
|
||||
var BankSlot bs := { bankId := mp_bank_id, slotNr := 200 };
|
||||
var ClientSlot cs := { clientId := 23, slotNr := 42 };
|
||||
f_rspro_srv_create_slotmap(cs, bs, exp_res := illegalSlotId);
|
||||
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
|
||||
}
|
||||
|
||||
/* attempt to create a mapping for an invalid bankID */
|
||||
testcase TC_createMapping_invalidBank() runs on bankd_test_CT {
|
||||
f_init();
|
||||
as_connectBankReq(bid := mp_bank_id, nslots := mp_num_slots);
|
||||
var BankSlot bs := { bankId := 200, slotNr := 0 };
|
||||
var ClientSlot cs := { clientId := 23, slotNr := 42 };
|
||||
f_rspro_srv_create_slotmap(cs, bs, exp_res := illegalBankId);
|
||||
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
|
||||
}
|
||||
|
||||
/* attempt to remove a non-existant mapping */
|
||||
testcase TC_removeMapping_unknownMap() runs on bankd_test_CT {
|
||||
f_init();
|
||||
as_connectBankReq(bid := mp_bank_id, nslots := mp_num_slots);
|
||||
var BankSlot bs := { bankId := mp_bank_id, slotNr := 0 };
|
||||
var ClientSlot cs := { clientId := 23, slotNr := 42 };
|
||||
f_rspro_srv_remove_slotmap(cs, bs, exp_res := unknownSlotmap);
|
||||
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
|
||||
}
|
||||
|
||||
/* add and then remove a mapping, expect both to be successful */
|
||||
testcase TC_removeMapping() runs on bankd_test_CT {
|
||||
f_init();
|
||||
as_connectBankReq(bid := mp_bank_id, nslots := mp_num_slots);
|
||||
var BankSlot bs := { bankId := mp_bank_id, slotNr := 0 };
|
||||
var ClientSlot cs := { clientId := 23, slotNr := 42 };
|
||||
f_rspro_srv_create_slotmap(cs, bs);
|
||||
f_rspro_srv_remove_slotmap(cs, bs);
|
||||
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
|
||||
}
|
||||
|
||||
/* connect from client to bankd without specifying a clientId */
|
||||
testcase TC_clientConnect_missingSlot() runs on bankd_test_CT {
|
||||
f_init_client(0);
|
||||
RSPRO[0].send(ts_RSPRO_ConnectClientReq(rspro[0].rspro_id, omit));
|
||||
f_rspro_exp(tr_RSPRO_ConnectClientRes(?, ResultCode:illegalClientId), 0);
|
||||
f_rspro_exp_disconnect(0);
|
||||
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
|
||||
}
|
||||
|
||||
/* connect from client to bankd using a clientId for which bankd has no map */
|
||||
testcase TC_clientConnect_unknown() runs on bankd_test_CT {
|
||||
f_init_client(0);
|
||||
f_rspro_connect_client(0, tr_Status_ok_or_nocard);
|
||||
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
|
||||
}
|
||||
|
||||
/* connect from client to bankd using a clientSlot for which bankd has no map */
|
||||
|
||||
|
||||
/* first connect client, then later add matching mapping from server */
|
||||
testcase TC_clientConnect_createMapping() runs on bankd_test_CT {
|
||||
f_init_client(0);
|
||||
f_rspro_connect_client(0, tr_Status_ok_or_nocard);
|
||||
|
||||
f_init();
|
||||
as_connectBankReq(bid := mp_bank_id, nslots := mp_num_slots);
|
||||
|
||||
var BankSlot bs := { bankId := mp_bank_id, slotNr := 0 };
|
||||
f_rspro_srv_create_slotmap(rspro[0].rspro_client_slot, bs);
|
||||
f_sleep(10.0);
|
||||
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
|
||||
}
|
||||
|
||||
|
||||
/* first add mapping, then connect matching client */
|
||||
testcase TC_createMapping_clientConnect() runs on bankd_test_CT {
|
||||
/* FIXME: this would only be done in f_init_client(), but we need it before */
|
||||
rspro[0].rspro_client_slot := { clientId := 23+0, slotNr := 0 };
|
||||
|
||||
f_init();
|
||||
as_connectBankReq(bid := mp_bank_id, nslots := mp_num_slots);
|
||||
|
||||
var BankSlot bs := { bankId := mp_bank_id, slotNr := 0 };
|
||||
f_rspro_srv_create_slotmap(rspro[0].rspro_client_slot, bs);
|
||||
|
||||
f_sleep(1.0);
|
||||
|
||||
f_init_client(0);
|
||||
f_rspro_connect_client(0, tr_Status_ok_or_nocard);
|
||||
/* FIXME: how to determine that bank correctly mapped us */
|
||||
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* add mapping, connect matching client, disconnect + reconnect */
|
||||
testcase TC_createMapping_clientReconnect() runs on bankd_test_CT {
|
||||
/* FIXME: this would only be done in f_init_client(), but we need it before */
|
||||
rspro[0].rspro_client_slot := { clientId := 23+0, slotNr := 0 };
|
||||
|
||||
f_init();
|
||||
as_connectBankReq(bid := mp_bank_id, nslots := mp_num_slots);
|
||||
|
||||
var BankSlot bs := { bankId := mp_bank_id, slotNr := 0 };
|
||||
f_rspro_srv_create_slotmap(rspro[0].rspro_client_slot, bs);
|
||||
|
||||
f_sleep(1.0);
|
||||
|
||||
f_init_client(0);
|
||||
f_rspro_connect_client(0, tr_Status_ok_or_nocard);
|
||||
/* TODO: works only with empty slot, as setAtrReq isn't handled */
|
||||
/* FIXME: how to determine that bank correctly mapped us */
|
||||
f_sleep(5.0);
|
||||
f_rspro_fini(rspro[0], 0);
|
||||
|
||||
f_init_client(0);
|
||||
f_rspro_connect_client(0, tr_Status_ok_or_nocard);
|
||||
/* FIXME: how to determine that bank correctly mapped us */
|
||||
f_sleep(5.0);
|
||||
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* remove mapping while client is connected */
|
||||
testcase TC_removeMapping_connected() runs on bankd_test_CT {
|
||||
f_init_client(0);
|
||||
f_rspro_connect_client(0, tr_Status_ok_or_nocard);
|
||||
/* TODO: works only with empty slot, as setAtrReq isn't handled */
|
||||
|
||||
f_init();
|
||||
as_connectBankReq(bid := mp_bank_id, nslots := mp_num_slots);
|
||||
|
||||
var BankSlot bs := { bankId := mp_bank_id, slotNr := 0 };
|
||||
f_rspro_srv_create_slotmap(rspro[0].rspro_client_slot, bs);
|
||||
/* FIXME: how to determine that bank correctly mapped us */
|
||||
f_sleep(5.0);
|
||||
f_rspro_srv_remove_slotmap(rspro[0].rspro_client_slot, bs);
|
||||
f_rspro_exp_disconnect(0);
|
||||
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
|
||||
}
|
||||
|
||||
/* first add mapping, then connect matching client and exchange some TPDUs */
|
||||
testcase TC_createMapping_exchangeTPDU() runs on bankd_test_CT {
|
||||
/* FIXME: this would only be done in f_init_client(), but we need it before */
|
||||
rspro[0].rspro_client_slot := { clientId := 23+0, slotNr := 0 };
|
||||
|
||||
f_init();
|
||||
as_connectBankReq(bid := mp_bank_id, nslots := mp_num_slots);
|
||||
|
||||
var BankSlot bs := { bankId := mp_bank_id, slotNr := 0 };
|
||||
f_rspro_srv_create_slotmap(rspro[0].rspro_client_slot, bs);
|
||||
|
||||
f_sleep(1.0);
|
||||
|
||||
f_init_client(0);
|
||||
f_rspro_connect_client(0, ok);
|
||||
/* FIXME: how to determine that bank correctly mapped us */
|
||||
f_rspro_exp(tr_RSPRO_SetAtrReq(rspro[0].rspro_client_slot, ?));
|
||||
|
||||
var TpduFlags f := {tpduHeaderPresent:=true, finalPart:=true, procByteContinueTx:=false,
|
||||
procByteContinueRx:=false};
|
||||
for (var integer i := 0; i < 10; i:=i+1) {
|
||||
f_rspro_xceive_mdm2card(0, bs, 'A0A40000023F00'O, f);
|
||||
}
|
||||
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
|
||||
}
|
||||
|
||||
|
||||
|
||||
control {
|
||||
execute( TC_connectBankReq_timeout() );
|
||||
execute( TC_connectBankReq() );
|
||||
|
||||
execute( TC_createMapping() );
|
||||
execute( TC_createMapping_busySlot() );
|
||||
execute( TC_createMapping_invalidSlot() );
|
||||
execute( TC_createMapping_invalidBank() );
|
||||
|
||||
execute( TC_removeMapping_unknownMap() );
|
||||
execute( TC_removeMapping() );
|
||||
|
||||
execute( TC_clientConnect_missingSlot() );
|
||||
execute( TC_clientConnect_unknown() );
|
||||
execute( TC_clientConnect_createMapping() );
|
||||
execute( TC_createMapping_clientConnect() );
|
||||
execute( TC_createMapping_clientReconnect() );
|
||||
execute( TC_removeMapping_connected() );
|
||||
|
||||
execute( TC_createMapping_exchangeTPDU() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
module RemsimClient_Tests {
|
||||
|
||||
/* Integration Tests for osmo-remsim-client
|
||||
* (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
|
||||
*
|
||||
* This test suite tests osmo-remsim-client by attaching to the external interfaces.
|
||||
*/
|
||||
|
||||
import from Osmocom_Types all;
|
||||
import from IPA_Emulation all;
|
||||
|
||||
import from RSPRO all;
|
||||
import from RSPRO_Types all;
|
||||
import from RSPRO_Server all;
|
||||
import from REMSIM_Tests all;
|
||||
|
||||
type component client_test_CT extends rspro_server_CT {
|
||||
var ComponentIdentity g_srv_comp_id, g_bankd_comp_id;
|
||||
};
|
||||
|
||||
private function f_init() runs on client_test_CT {
|
||||
g_srv_comp_id := valueof(ts_CompId(remsimServer, "ttcn-server"));
|
||||
g_bankd_comp_id := valueof(ts_CompId(remsimBankd, "ttcn-bankd"));
|
||||
|
||||
f_rspro_srv_init(0, mp_server_ip, mp_server_port, g_srv_comp_id);
|
||||
f_rspro_srv_init(1, mp_bankd_ip, mp_bankd_port, g_bankd_comp_id, exp_connect := false);
|
||||
}
|
||||
|
||||
|
||||
/* ConnectClientReq from client to remsim-server */
|
||||
testcase TC_srv_connectClient() runs on client_test_CT {
|
||||
f_init();
|
||||
as_connectClientReq();
|
||||
setverdict(pass);
|
||||
f_sleep(1.0);
|
||||
}
|
||||
|
||||
/* ConnectClientReq from client to remsim-server */
|
||||
testcase TC_srv_connectClient_reject() runs on client_test_CT {
|
||||
f_init();
|
||||
as_connectClientReq(res := illegalClientId);
|
||||
/* expect disconnect by client */
|
||||
RSPRO_SRV[0].receive(t_ASP_IPA_EVT_UD(ASP_IPA_EVENT_DOWN));
|
||||
setverdict(pass);
|
||||
f_sleep(1.0);
|
||||
}
|
||||
|
||||
/* ConnectClientReq from client to remsim-server */
|
||||
testcase TC_srv_connectClient_configClientBank() runs on client_test_CT {
|
||||
var BankSlot bslot := { 1, 0 };
|
||||
f_init();
|
||||
as_connectClientReq();
|
||||
f_rspro_config_client_bank(bslot, ts_IpPort(ts_IPv4(mp_bankd_ip), mp_bankd_port));
|
||||
f_rspro_srv_exp_connect(1);
|
||||
as_connectClientReq(i := 1);
|
||||
setverdict(pass);
|
||||
f_sleep(1.0);
|
||||
}
|
||||
|
||||
/* Test if client re-connects to server after connection is lost */
|
||||
testcase TC_srv_reconnect() runs on client_test_CT {
|
||||
var BankSlot bslot := { 1, 0 };
|
||||
f_init();
|
||||
as_connectClientReq();
|
||||
|
||||
/* disconnect the client from server and expect re-establish + re-connect */
|
||||
f_rspro_srv_fini(0);
|
||||
f_rspro_srv_init(0, mp_server_ip, mp_server_port, g_srv_comp_id, exp_connect := true);
|
||||
as_connectClientReq(i := 0);
|
||||
|
||||
setverdict(pass);
|
||||
f_sleep(1.0);
|
||||
}
|
||||
|
||||
/* Test if client re-connects to bank after connection is lost */
|
||||
testcase TC_bank_reconnect() runs on client_test_CT {
|
||||
var BankSlot bslot := { 1, 0 };
|
||||
f_init();
|
||||
as_connectClientReq();
|
||||
f_rspro_config_client_bank(bslot, ts_IpPort(ts_IPv4(mp_bankd_ip), mp_bankd_port));
|
||||
f_rspro_srv_exp_connect(1);
|
||||
as_connectClientReq(i := 1);
|
||||
|
||||
/* disconnect the client from bankd and expect re-establish + re-connect */
|
||||
f_rspro_srv_fini(1);
|
||||
f_rspro_srv_init(1, mp_bankd_ip, mp_bankd_port, g_bankd_comp_id, exp_connect := true);
|
||||
as_connectClientReq(i := 1);
|
||||
|
||||
setverdict(pass);
|
||||
f_sleep(1.0);
|
||||
}
|
||||
|
||||
/* TODO:
|
||||
* send a configClientBankIpReq and change the bank of an active client
|
||||
* send a configClientBankSlotReq and chagne the bank slot of an active client
|
||||
* test keepalive mechanism: do we get IPA PING?
|
||||
* test keepalive mechanism: do we see disconnect+reconnect if we don't respond to IPA PING?
|
||||
* test actual APDU transfers
|
||||
* test messages in invalid state, e.g. APDUs before we're connected to a bank
|
||||
* test messages on server connection which are only permitted on bankd connection
|
||||
*/
|
||||
|
||||
control {
|
||||
execute( TC_srv_connectClient() );
|
||||
execute( TC_srv_connectClient_reject() );
|
||||
execute( TC_srv_connectClient_configClientBank() );
|
||||
execute( TC_srv_reconnect() );
|
||||
execute( TC_bank_reconnect() );
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,485 @@
|
|||
module RemsimServer_Tests {
|
||||
|
||||
/* Integration Tests for osmo-remsim-server
|
||||
* (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
|
||||
*
|
||||
* This test suite tests osmo-remsim-server by attaching to the external interfaces
|
||||
* such as RSPRO for simulated clients + bankds and RSRES (REST backend interface).
|
||||
*/
|
||||
|
||||
import from Osmocom_Types all;
|
||||
|
||||
import from RSPRO all;
|
||||
import from RSRES all;
|
||||
import from RSPRO_Types all;
|
||||
import from REMSIM_Tests all;
|
||||
|
||||
import from IPA_Emulation all;
|
||||
|
||||
import from HTTPmsg_Types all;
|
||||
import from HTTPmsg_PortType all;
|
||||
import from JSON_Types all;
|
||||
|
||||
type component http_CT {
|
||||
port HTTPmsg_PT HTTP;
|
||||
var charstring g_http_host;
|
||||
var integer g_http_port;
|
||||
};
|
||||
|
||||
function f_http_init(charstring host, integer http_port) runs on http_CT {
|
||||
map(self:HTTP, system:HTTP);
|
||||
g_http_host := host;
|
||||
g_http_port := http_port;
|
||||
}
|
||||
|
||||
template (value) Connect ts_HTTP_Connect(template (value) charstring hostname,
|
||||
template (value) integer http_port := 80,
|
||||
template (value) boolean use_ssl := false) := {
|
||||
hostname := hostname,
|
||||
portnumber := http_port,
|
||||
use_ssl := use_ssl
|
||||
}
|
||||
template (value) Close ts_HTTP_Close := { client_id := omit };
|
||||
|
||||
template (value) HeaderLines ts_HTTP_Header(charstring body) := {
|
||||
{ header_name := "Content-Type", header_value := "application/json" },
|
||||
{ header_name := "Content-Length", header_value := int2str(lengthof(body)) }
|
||||
}
|
||||
|
||||
template (value) HTTPMessage ts_HTTP_Req(charstring url,
|
||||
charstring method := "GET",
|
||||
charstring body := "",
|
||||
integer v_maj := 1, integer v_min := 1) := {
|
||||
request := {
|
||||
client_id := omit,
|
||||
method := method,
|
||||
uri := url,
|
||||
version_major := v_maj,
|
||||
version_minor := v_min,
|
||||
header := ts_HTTP_Header(body),
|
||||
body := body
|
||||
}
|
||||
}
|
||||
|
||||
template HTTPMessage tr_HTTP_Resp(template integer sts := ?) := {
|
||||
response := {
|
||||
client_id := ?,
|
||||
version_major := ?,
|
||||
version_minor := ?,
|
||||
statuscode := sts,
|
||||
statustext := ?,
|
||||
header := ?,
|
||||
body := ?
|
||||
}
|
||||
};
|
||||
|
||||
template HTTPMessage tr_HTTP_Resp2xx := tr_HTTP_Resp((200..299));
|
||||
|
||||
/* run a HTTP request and return the response */
|
||||
function f_http_transact(charstring url, charstring method := "GET",
|
||||
charstring body := "", template HTTPMessage exp := tr_HTTP_Resp2xx)
|
||||
runs on http_CT return HTTPMessage {
|
||||
var HTTPMessage resp;
|
||||
timer T := 2.0;
|
||||
|
||||
HTTP.send(ts_HTTP_Connect(g_http_host, g_http_port));
|
||||
//HTTP.receive(Connect_result:?);
|
||||
HTTP.send(ts_HTTP_Req(url, method, body));
|
||||
T.start;
|
||||
alt {
|
||||
[] HTTP.receive(exp) -> value resp {
|
||||
setverdict(pass);
|
||||
}
|
||||
[] HTTP.receive(tr_HTTP_Resp) -> value resp {
|
||||
setverdict(fail, "Unexpected HTTP response ", resp);
|
||||
}
|
||||
[] T.timeout {
|
||||
setverdict(fail, "Timeout waiting for HTTP response");
|
||||
self.stop;
|
||||
}
|
||||
}
|
||||
HTTP.send(ts_HTTP_Close);
|
||||
return resp;
|
||||
}
|
||||
|
||||
/* run a HTTP GET on specified URL expecting json in RSRES format as response */
|
||||
function f_rsres_get(charstring url, template integer exp_sts := 200)
|
||||
runs on http_CT return JsRoot {
|
||||
var HTTPMessage http_resp;
|
||||
http_resp := f_http_transact(url, exp := tr_HTTP_Resp(exp_sts));
|
||||
return f_dec_JsRoot(char2oct(http_resp.response.body));
|
||||
}
|
||||
|
||||
/* run a HTTP PUT to add a new slotmap to the remsim-server */
|
||||
function f_rsres_post_slotmap(JsSlotmap slotmap, template integer exp_sts := 201)
|
||||
runs on http_CT return HTTPResponse {
|
||||
var charstring body := oct2char(f_enc_JsSlotmap(slotmap));
|
||||
var HTTPMessage http_resp;
|
||||
http_resp := f_http_transact(url := "/api/backend/v1/slotmaps", method := "POST",
|
||||
body := body, exp := tr_HTTP_Resp(exp_sts))
|
||||
return http_resp.response;
|
||||
}
|
||||
|
||||
/* run a HTTP PUT to add a new slotmap to the remsim-server */
|
||||
function f_rsres_post_reset(template integer exp_sts := 200)
|
||||
runs on http_CT return HTTPResponse {
|
||||
var HTTPMessage http_resp;
|
||||
http_resp := f_http_transact(url := "/api/backend/v1/global-reset", method := "POST",
|
||||
body := "", exp := tr_HTTP_Resp(exp_sts))
|
||||
return http_resp.response;
|
||||
}
|
||||
|
||||
|
||||
/* run a HTTP DELETE to remove a slotmap from te remsim-server */
|
||||
function f_rsres_delete_slotmap(BankSlot bs, template integer exp_sts := 200)
|
||||
runs on http_CT return HTTPResponse {
|
||||
var HTTPMessage http_resp;
|
||||
var integer slotmap_id := bs.bankId * 65536 + bs.slotNr;
|
||||
http_resp := f_http_transact(url := "/api/backend/v1/slotmaps/" & int2str(slotmap_id),
|
||||
method := "DELETE", exp := tr_HTTP_Resp(exp_sts));
|
||||
return http_resp.response;
|
||||
}
|
||||
|
||||
|
||||
function f_rsres_init() runs on http_CT {
|
||||
f_http_init(mp_server_ip, mp_rsres_port);
|
||||
f_rsres_post_reset();
|
||||
}
|
||||
|
||||
type component test_CT extends rspro_client_CT, http_CT {
|
||||
};
|
||||
|
||||
|
||||
testcase TC_connect_and_nothing() runs on rspro_client_CT {
|
||||
var ComponentIdentity rspro_id := valueof(ts_CompId(remsimClient, "foobar"));
|
||||
timer T := 20.0;
|
||||
|
||||
f_rspro_init(rspro[0], mp_server_ip, mp_server_port, rspro_id, 0);
|
||||
T.start;
|
||||
/* expect that we're disconnected if we never send a ConnectClientReq */
|
||||
alt {
|
||||
[] RSPRO[0].receive(t_ASP_IPA_EVT_UD(ASP_IPA_EVENT_ID_ACK)) { repeat; }
|
||||
[] RSPRO[0].receive(t_ASP_IPA_EVT_UD(ASP_IPA_EVENT_DOWN)) {
|
||||
setverdict(pass);
|
||||
}
|
||||
[] T.timeout {
|
||||
setverdict(fail, "Timeout waiting for disconnect");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
testcase TC_connect_client() runs on test_CT {
|
||||
var ComponentIdentity rspro_id := valueof(ts_CompId(remsimClient, "foobar"));
|
||||
var JsRoot js;
|
||||
|
||||
f_rsres_init();
|
||||
f_rspro_init(rspro[0], mp_server_ip, mp_server_port, rspro_id, 0);
|
||||
rspro[0].rspro_client_slot := valueof(ts_ClientSlot(3,4));
|
||||
|
||||
js := f_rsres_get("/api/backend/v1/clients");
|
||||
if (not match(js.clients, JsClients:{})) {
|
||||
setverdict(fail, "Initial state not empty");
|
||||
mtc.stop;
|
||||
}
|
||||
f_rspro_connect_client(0);
|
||||
js := f_rsres_get("/api/backend/v1/clients");
|
||||
if (not match(js.clients[0], tr_JsClient(CONNECTED_CLIENT, rspro[0].rspro_id))) {
|
||||
setverdict(fail, "Non-matching JSON response");
|
||||
mtc.stop;
|
||||
}
|
||||
//as_rspro_cfg_client_id(0, cslot);
|
||||
setverdict(pass);
|
||||
}
|
||||
|
||||
testcase TC_connect_bank() runs on test_CT {
|
||||
var ComponentIdentity rspro_id := valueof(ts_CompId(remsimBankd, "foobar"));
|
||||
var JsRoot js;
|
||||
|
||||
f_rsres_init();
|
||||
f_rspro_init(rspro[0], mp_server_ip, mp_server_port, rspro_id, 0);
|
||||
rspro[0].rspro_bank_id := 1;
|
||||
rspro[0].rspro_bank_nslots := 8;
|
||||
|
||||
js := f_rsres_get("/api/backend/v1/banks");
|
||||
if (not match(js.banks, JsBanks:{})) {
|
||||
setverdict(fail, "Initial state not empty");
|
||||
mtc.stop;
|
||||
}
|
||||
f_rspro_connect_client(0);
|
||||
js := f_rsres_get("/api/backend/v1/banks");
|
||||
if (not match(js.banks[0], tr_JsBank(CONNECTED_BANKD, rspro[0].rspro_id, rspro[0].rspro_bank_id,
|
||||
rspro[0].rspro_bank_nslots))) {
|
||||
setverdict(fail, "Non-matching JSON response");
|
||||
mtc.stop;
|
||||
}
|
||||
setverdict(pass);
|
||||
}
|
||||
|
||||
function f_ensure_slotmaps(template JsSlotmaps maps)
|
||||
runs on http_CT {
|
||||
var JsRoot js;
|
||||
|
||||
/* check that it is actually added */
|
||||
js := f_rsres_get("/api/backend/v1/slotmaps");
|
||||
if (match(js.slotmaps, maps)) {
|
||||
setverdict(pass);
|
||||
} else {
|
||||
setverdict(fail, "Unexpected slotmaps: ", js);
|
||||
}
|
||||
}
|
||||
|
||||
/* verify that exactly only one slotmap exists (the specified one) */
|
||||
function f_ensure_slotmap_exists_only(template ClientSlot cslot, template BankSlot bslot,
|
||||
template SlotmapState state := ?)
|
||||
runs on http_CT {
|
||||
f_ensure_slotmaps({ tr_JsSlotmap(bslot, cslot, state) } );
|
||||
}
|
||||
|
||||
/* verify that exactly only one slotmap exists (possibly among others) */
|
||||
function f_ensure_slotmap_exists(template ClientSlot cslot, template BankSlot bslot,
|
||||
template SlotmapState state := ?)
|
||||
runs on http_CT {
|
||||
f_ensure_slotmaps({ *, tr_JsSlotmap(bslot, cslot, state), * } );
|
||||
}
|
||||
|
||||
|
||||
/* test adding a single slotmap */
|
||||
testcase TC_slotmap_add() runs on test_CT {
|
||||
f_rsres_init();
|
||||
|
||||
var JsSlotmap sm := valueof(ts_JsSlotmap(ts_BankSlot(1,2), ts_ClientSlot(3,4)));
|
||||
var HTTPResponse res := f_rsres_post_slotmap(sm);
|
||||
|
||||
/* check that it is actually added */
|
||||
f_ensure_slotmap_exists_only(sm.client, sm.bank, NEW);
|
||||
}
|
||||
|
||||
/* test adding a slotmap and then connecting a client + bankd */
|
||||
testcase TC_slotmap_add_conn_cl_b() runs on test_CT {
|
||||
/* Simulate one client */
|
||||
var ComponentIdentity rspro_id := valueof(ts_CompId(remsimClient, testcasename()));
|
||||
f_rspro_init(rspro[0], mp_server_ip, mp_server_port, rspro_id, 0);
|
||||
rspro[0].rspro_client_slot := valueof(ts_ClientSlot(3,4));
|
||||
|
||||
/* Simulate one bankd */
|
||||
var BankSlot bslot := valueof(ts_BankSlot(1,2));
|
||||
var ComponentIdentity rspro_bank_id := valueof(ts_CompId(remsimBankd, testcasename()));
|
||||
f_rspro_init(rspro[1], mp_server_ip, mp_server_port, rspro_bank_id, 1);
|
||||
rspro[1].rspro_bank_id := bslot.bankId;
|
||||
rspro[1].rspro_bank_nslots := 8
|
||||
|
||||
f_rsres_init();
|
||||
var JsSlotmap sm := valueof(ts_JsSlotmap(bslot, rspro[0].rspro_client_slot));
|
||||
var HTTPResponse res;
|
||||
|
||||
/* 1) Create a new slotmap via HTTP */
|
||||
res := f_rsres_post_slotmap(sm);
|
||||
|
||||
/* 2) verify that the slotmap exists and is NEW */
|
||||
f_ensure_slotmap_exists_only(sm.client, sm.bank, NEW);
|
||||
|
||||
/* 3) connect a client for that slotmap */
|
||||
f_rspro_connect_client(0);
|
||||
|
||||
/* 4) connect a bankd for that slotmap */
|
||||
f_rspro_connect_client(1);
|
||||
|
||||
/* 5) verify that the slotmap exists and is UNACKNOWLEDGED */
|
||||
f_ensure_slotmap_exists_only(sm.client, sm.bank, UNACKNOWLEDGED);
|
||||
|
||||
/* 6) expect bankd to receive that mapping */
|
||||
as_rspro_create_mapping(1, sm.client, sm.bank);
|
||||
|
||||
/* 7) verify that the slotmap exists and is ACTIVE */
|
||||
f_ensure_slotmap_exists_only(sm.client, sm.bank, ACTIVE);
|
||||
|
||||
/* 8) expect the client to be configured with bankd side settings */
|
||||
as_rspro_cfg_client_bank(0, bslot, ?);
|
||||
}
|
||||
|
||||
/* test connecting a client and later adding a slotmap for it */
|
||||
testcase TC_conn_cl_b_slotmap_add() runs on test_CT {
|
||||
/* Simulate one client */
|
||||
var ComponentIdentity rspro_id := valueof(ts_CompId(remsimClient, testcasename()));
|
||||
f_rspro_init(rspro[0], mp_server_ip, mp_server_port, rspro_id, 0);
|
||||
rspro[0].rspro_client_slot := valueof(ts_ClientSlot(3,4));
|
||||
|
||||
/* Simulate one bankd */
|
||||
var BankSlot bslot := valueof(ts_BankSlot(1,2));
|
||||
var ComponentIdentity rspro_bank_id := valueof(ts_CompId(remsimBankd, testcasename()));
|
||||
f_rspro_init(rspro[1], mp_server_ip, mp_server_port, rspro_bank_id, 1);
|
||||
rspro[1].rspro_bank_id := bslot.bankId;
|
||||
rspro[1].rspro_bank_nslots := 8
|
||||
|
||||
f_rsres_init();
|
||||
var JsSlotmap sm := valueof(ts_JsSlotmap(bslot, rspro[0].rspro_client_slot));
|
||||
var HTTPResponse res;
|
||||
|
||||
/* 1) connect a client for that slotmap */
|
||||
f_rspro_connect_client(0);
|
||||
|
||||
/* 2) Create a new slotmap via HTTP */
|
||||
res := f_rsres_post_slotmap(sm);
|
||||
|
||||
/* 3) verify that the slotmap exists and is NEW */
|
||||
f_ensure_slotmap_exists_only(sm.client, sm.bank, NEW);
|
||||
|
||||
/* 4) connect a bankd for that slotmap */
|
||||
f_rspro_connect_client(1);
|
||||
|
||||
/* 5) verify that the slotmap exists and is UNACKNOWLEDGED */
|
||||
f_ensure_slotmap_exists_only(sm.client, sm.bank, UNACKNOWLEDGED);
|
||||
|
||||
/* 6) expect bankd to receive that mapping */
|
||||
as_rspro_create_mapping(1, sm.client, sm.bank);
|
||||
|
||||
/* 7) verify that the slotmap exists and is ACTIVE */
|
||||
f_ensure_slotmap_exists_only(sm.client, sm.bank, ACTIVE);
|
||||
|
||||
/* 8) expect the client to be configured with bankd IP/port */
|
||||
as_rspro_cfg_client_bank(0, bslot, ?);
|
||||
}
|
||||
|
||||
/* simple delete of a 'NEW' slotmap */
|
||||
testcase TC_slotmap_del_new() runs on test_CT {
|
||||
f_rsres_init();
|
||||
|
||||
var JsSlotmap sm := valueof(ts_JsSlotmap(ts_BankSlot(1,2), ts_ClientSlot(3,4)));
|
||||
var HTTPResponse res := f_rsres_post_slotmap(sm);
|
||||
log(res);
|
||||
res := f_rsres_delete_slotmap(sm.bank);
|
||||
log(res);
|
||||
}
|
||||
|
||||
/* simple delete of a 'UNACKNOWLEDGED' slotmap */
|
||||
testcase TC_slotmap_del_unack() runs on test_CT {
|
||||
var ComponentIdentity rspro_id := valueof(ts_CompId(remsimBankd, testcasename()));
|
||||
f_rspro_init(rspro[0], mp_server_ip, mp_server_port, rspro_id, 0);
|
||||
rspro[0].rspro_bank_id := 1;
|
||||
rspro[0].rspro_bank_nslots := 8;
|
||||
|
||||
f_rsres_init();
|
||||
var JsSlotmap sm := valueof(ts_JsSlotmap(ts_BankSlot(1,2), ts_ClientSlot(3,4)));
|
||||
var HTTPResponse res;
|
||||
|
||||
/* Create a new slotmap via HTTP */
|
||||
res := f_rsres_post_slotmap(sm);
|
||||
|
||||
/* verify that the slotmap exists and is NEW */
|
||||
f_ensure_slotmap_exists_only(sm.client, sm.bank, NEW);
|
||||
|
||||
/* connect a bankd for that slotmap */
|
||||
f_rspro_connect_client(0);
|
||||
|
||||
/* expect the slotmap to be pushed to bank but don't ACK it */
|
||||
f_rspro_exp(tr_RSPRO_CreateMappingReq(sm.client, sm.bank));
|
||||
|
||||
/* verify that the slotmap exists and is UNACKNOWLEDGED */
|
||||
f_ensure_slotmap_exists_only(sm.client, sm.bank, UNACKNOWLEDGED);
|
||||
|
||||
/* delete the slotmap via REST */
|
||||
res := f_rsres_delete_slotmap(sm.bank);
|
||||
|
||||
/* verify the slotmap is gone */
|
||||
f_ensure_slotmaps({});
|
||||
}
|
||||
|
||||
/* simple delete of a 'ACTIVE' slotmap */
|
||||
testcase TC_slotmap_del_active() runs on test_CT {
|
||||
var ComponentIdentity rspro_id := valueof(ts_CompId(remsimBankd, testcasename()));
|
||||
f_rspro_init(rspro[0], mp_server_ip, mp_server_port, rspro_id, 0);
|
||||
rspro[0].rspro_bank_id := 1;
|
||||
rspro[0].rspro_bank_nslots := 8;
|
||||
|
||||
f_rsres_init();
|
||||
var JsSlotmap sm := valueof(ts_JsSlotmap(ts_BankSlot(1,2), ts_ClientSlot(3,4)));
|
||||
var HTTPResponse res;
|
||||
|
||||
/* Create a new slotmap via HTTP */
|
||||
res := f_rsres_post_slotmap(sm);
|
||||
|
||||
/* verify that the slotmap exists and is NEW */
|
||||
f_ensure_slotmap_exists_only(sm.client, sm.bank, NEW);
|
||||
|
||||
/* connect a bankd for that slotmap */
|
||||
f_rspro_connect_client(0);
|
||||
|
||||
/* expect the slotmap to be pushed to bank and ACK it */
|
||||
as_rspro_create_mapping(0, sm.client, sm.bank);
|
||||
|
||||
/* verify that the slotmap exists and is ACTIVE */
|
||||
f_ensure_slotmap_exists_only(sm.client, sm.bank, ACTIVE);
|
||||
|
||||
f_sleep(1.0);
|
||||
|
||||
/* delete the slotmap via REST */
|
||||
res := f_rsres_delete_slotmap(sm.bank);
|
||||
|
||||
/* verify the slotmap is gone from REST interface immediately */
|
||||
f_ensure_slotmaps({});
|
||||
|
||||
/* verify the slotmap is removed from bankd */
|
||||
as_rspro_remove_mapping(0, sm.client, sm.bank);
|
||||
}
|
||||
|
||||
|
||||
/* Add a slotmap to a currently active bank */
|
||||
testcase TC_slotmap_add_active_bank() runs on test_CT {
|
||||
var ComponentIdentity rspro_id := valueof(ts_CompId(remsimBankd, testcasename()));
|
||||
f_rspro_init(rspro[0], mp_server_ip, mp_server_port, rspro_id, 0);
|
||||
rspro[0].rspro_bank_id := 1;
|
||||
rspro[0].rspro_bank_nslots := 8;
|
||||
|
||||
f_rsres_init();
|
||||
var JsSlotmap sm := valueof(ts_JsSlotmap(ts_BankSlot(1,2), ts_ClientSlot(3,4)));
|
||||
var HTTPResponse res;
|
||||
|
||||
/* connect a bankd for that slotmap */
|
||||
f_rspro_connect_client(0);
|
||||
|
||||
/* Create a new slotmap via HTTP */
|
||||
res := f_rsres_post_slotmap(sm);
|
||||
|
||||
/* expect the slotmap to be pushed to bank and ACK it */
|
||||
as_rspro_create_mapping(0, sm.client, sm.bank);
|
||||
|
||||
/* verify that the slotmap exists and is ACTIVE */
|
||||
f_ensure_slotmap_exists_only(sm.client, sm.bank, ACTIVE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* TODO
|
||||
* - add slotmap, then connect matching client (see if slotmap is sent; check slotmap state)
|
||||
* - connect client w/slotmap; delete slotmap via REST (see if it is deleted)
|
||||
* - don't acknowledge delete from client, disconnect client (see if slotmap is deleted)
|
||||
* - delete non-existing slotmap via REST
|
||||
* - create slotmap with integers out of range via REST
|
||||
|
||||
* - connect from unknown client (name not known, no clientId provisioned?
|
||||
* - add client name/ID mappings from REST API?
|
||||
*/
|
||||
|
||||
|
||||
control {
|
||||
execute( TC_connect_and_nothing() );
|
||||
execute( TC_connect_client() );
|
||||
execute( TC_connect_bank() );
|
||||
execute( TC_slotmap_add() );
|
||||
execute( TC_slotmap_add_conn_cl_b() );
|
||||
execute( TC_conn_cl_b_slotmap_add() );
|
||||
execute( TC_slotmap_del_new() );
|
||||
execute( TC_slotmap_del_unack() );
|
||||
execute( TC_slotmap_del_active() );
|
||||
execute( TC_slotmap_add_active_bank() );
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
#!/bin/bash
|
||||
|
||||
BASEDIR=../deps
|
||||
|
||||
. ../gen_links.sh.inc
|
||||
|
||||
DIR=$BASEDIR/titan.Libraries.TCCUsefulFunctions/src
|
||||
FILES="TCCInterface_Functions.ttcn TCCConversion_Functions.ttcn TCCConversion.cc TCCInterface.cc TCCInterface_ip.h"
|
||||
gen_links $DIR $FILES
|
||||
|
||||
DIR=$BASEDIR/titan.TestPorts.Common_Components.Socket-API/src
|
||||
FILES="Socket_API_Definitions.ttcn"
|
||||
gen_links $DIR $FILES
|
||||
|
||||
DIR=$BASEDIR/titan.TestPorts.IPL4asp/src
|
||||
FILES="IPL4asp_Functions.ttcn IPL4asp_PT.cc IPL4asp_PT.hh IPL4asp_PortType.ttcn IPL4asp_Types.ttcn IPL4asp_discovery.cc IPL4asp_protocol_L234.hh"
|
||||
gen_links $DIR $FILES
|
||||
|
||||
DIR=$BASEDIR/titan.TestPorts.TELNETasp/src
|
||||
FILES="TELNETasp_PT.cc TELNETasp_PT.hh TELNETasp_PortType.ttcn"
|
||||
gen_links $DIR $FILES
|
||||
|
||||
DIR=$BASEDIR/titan.TestPorts.Common_Components.Abstract_Socket/src
|
||||
FILES="Abstract_Socket.cc Abstract_Socket.hh "
|
||||
gen_links $DIR $FILES
|
||||
|
||||
DIR=$BASEDIR/titan.TestPorts.HTTPmsg/src
|
||||
FILES="HTTPmsg_MessageLen.ttcn HTTPmsg_MessageLen_Function.cc HTTPmsg_PT.cc HTTPmsg_PT.hh HTTPmsg_PortType.ttcn HTTPmsg_Types.ttcn "
|
||||
gen_links $DIR $FILES
|
||||
|
||||
DIR=$BASEDIR/titan.ProtocolModules.JSON_v07_2006/src
|
||||
FILES="JSON_EncDec.cc JSON_Types.ttcn "
|
||||
gen_links $DIR $FILES
|
||||
|
||||
|
||||
DIR=../library
|
||||
FILES="Misc_Helpers.ttcn General_Types.ttcn Osmocom_VTY_Functions.ttcn Osmocom_Types.ttcn "
|
||||
FILES+="IPA_Types.ttcn IPA_CodecPort.ttcn IPA_CodecPort_CtrlFunct.ttcn IPA_CodecPort_CtrlFunctDef.cc IPA_Emulation.ttcnpp IPA_CodecPort.ttcn " #RSL_Types.ttcn RSL_Emulation.ttcn "
|
||||
FILES+="Osmocom_CTRL_Types.ttcn Osmocom_CTRL_Functions.ttcn Osmocom_CTRL_Adapter.ttcn "
|
||||
FILES+="Native_Functions.ttcn Native_FunctionDefs.cc "
|
||||
gen_links $DIR $FILES
|
||||
|
||||
ignore_pp_results
|
|
@ -0,0 +1,7 @@
|
|||
#!/bin/sh
|
||||
|
||||
FILES="*.ttcn *.ttcnpp *.asn IPA_CodecPort_CtrlFunctDef.cc IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc TELNETasp_PT.cc Native_FunctionDefs.cc RSPRO_EncDec.cc Abstract_Socket.cc HTTPmsg_PT.cc HTTPmsg_MessageLen_Function.cc JSON_EncDec.cc"
|
||||
|
||||
export CPPFLAGS_TTCN3="-DIPA_EMULATION_RSPRO -DIPA_EMULATION_CTRL"
|
||||
|
||||
../regen-makefile.sh REMSIM_Tests.ttcn $FILES
|
Loading…
Reference in New Issue