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:
Harald Welte 2019-03-04 18:31:11 +01:00 committed by laforge
parent 6da25e36e6
commit faa4292444
15 changed files with 2252 additions and 1 deletions

View File

@ -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),)

6
deps/Makefile vendored
View File

@ -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

10
remsim/REMSIM_Tests.cfg Normal file
View File

@ -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

View File

@ -0,0 +1,3 @@
[TESTPORT_PARAMETERS]
system.HTTP.http_debugging := "yes"
system.HTTP.use_notification_ASPs := "no"

247
remsim/REMSIM_Tests.ttcn Normal file
View File

@ -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));
}
}
}

349
remsim/RSPRO.asn Normal file
View File

@ -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

26
remsim/RSPRO_EncDec.cc Normal file
View File

@ -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;
}
}

174
remsim/RSPRO_Server.ttcn Normal file
View File

@ -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));
}
}
}

375
remsim/RSPRO_Types.ttcn Normal file
View File

@ -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
}
});
}

110
remsim/RSRES.ttcn Normal file
View File

@ -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" }

View File

@ -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() );
}
}

View File

@ -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() );
}
}

View File

@ -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() );
}
}

43
remsim/gen_links.sh Executable file
View File

@ -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

7
remsim/regen_makefile.sh Executable file
View File

@ -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