This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.
Pau Espin Pedrol gerrit-no-reply at lists.osmocom.orgHello Jenkins Builder, I'd like you to reexamine a change. Please visit https://gerrit.osmocom.org/2884 to look at the new patch set (#3). Add support for SMPP testing As defined in [1], the different related actors are implemented in this commit: ESME and SMSC. SMSC: In Osmocom, the SMSC is currently implemented inside the NITB or the MSC. A new Smsc abstract class is created to shared code between the NITB and the MSC, and also makes it easier for later when the SMSC is splitted. ESMEs can be dynamically added to its configuration in a similar way to how the BTSs are added. ESME: A new class Esme is created which can be used by tests to control an ESME to interact with the SMSC. The ESME functionalities are implemented using python-smpplib. Required version of this library is at least 43cc6f819ec76b2c0a9d36d1d439308634716227, which contains support for python 3 and some required features to poll the socket. This commit already contains a few tests which checks different features and tests the API. Extending tested features or scenarios can be later done quite easily. The tests are not enabled by default right now, because there are several of them in a suite and the ip_address resources are not freed after every tests which ends up in the suite failing due to missing reserved resources. All the tests run alone work though. When the issue is fixed they can then be added to the default list of tests to be run. [1] http://opensmpp.org/specs/SMPP_v3_4_Issue1_2.pdf Change-Id: I14ca3cb009d6d646a449ca99b0200da12085c0da --- M selftest/template_test.ok M selftest/template_test.py M selftest/template_test/osmo-nitb.cfg.tmpl A src/osmo_gsm_tester/esme.py M src/osmo_gsm_tester/osmo_msc.py M src/osmo_gsm_tester/osmo_nitb.py M src/osmo_gsm_tester/sms.py A src/osmo_gsm_tester/smsc.py M src/osmo_gsm_tester/suite.py M src/osmo_gsm_tester/templates/osmo-msc.cfg.tmpl M src/osmo_gsm_tester/templates/osmo-nitb.cfg.tmpl M src/osmo_gsm_tester/test.py A suites/aoip_smpp/esme_connect_policy_acceptall.py A suites/aoip_smpp/esme_connect_policy_closed.py A suites/aoip_smpp/esme_ms_sms.py A suites/aoip_smpp/suite.conf A suites/smpp/esme_connect_policy_acceptall.py A suites/smpp/esme_connect_policy_closed.py A suites/smpp/esme_ms_sms.py A suites/smpp/suite.conf 20 files changed, 520 insertions(+), 38 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmo-gsm-tester refs/changes/84/2884/3 diff --git a/selftest/template_test.ok b/selftest/template_test.ok index 1267dac..b16ea62 100644 --- a/selftest/template_test.ok +++ b/selftest/template_test.ok @@ -136,10 +136,13 @@ phys_chan_config val_phys_chan_config_3 smpp local-tcp-ip val_ip_address 2775 - system-id test - policy closed - esme test - password test + system-id test-nitb + policy val_smsc_policy + esme val_system_id_esme0 + password val_password_esme0 + default-route + esme val_system_id_esme1 + password val_password_esme1 default-route ctrl bind val_ip_address diff --git a/selftest/template_test.py b/selftest/template_test.py index 45347b6..76fb86b 100755 --- a/selftest/template_test.py +++ b/selftest/template_test.py @@ -35,6 +35,11 @@ ) } +mock_esme = { + 'system_id': 'val_system_id', + 'password': 'val_password' +} + def clone_mod(d, val_ext): c = dict(d) for name in c.keys(): @@ -47,7 +52,14 @@ mock_bts0 = clone_mod(mock_bts, '_bts0') mock_bts1 = clone_mod(mock_bts, '_bts1') +mock_esme0 = clone_mod(mock_esme, '_esme0') +mock_esme1 = clone_mod(mock_esme, '_esme1') + vals = dict(nitb=dict( + smsc=dict( + policy='val_smsc_policy', + esme_list=(mock_esme0, mock_esme1) + ), net=dict( mcc='val_mcc', mnc='val_mnc', diff --git a/selftest/template_test/osmo-nitb.cfg.tmpl b/selftest/template_test/osmo-nitb.cfg.tmpl index 3404b7f..d02e3fe 100644 --- a/selftest/template_test/osmo-nitb.cfg.tmpl +++ b/selftest/template_test/osmo-nitb.cfg.tmpl @@ -47,12 +47,14 @@ timer t3119 0 timer t3141 0 smpp - local-tcp-ip ${smpp_bind_ip} 2775 - system-id test - policy closed - esme test - password test + local-tcp-ip ${nitb.ip_address.addr} 2775 + system-id test-nitb + policy ${nitb.smsc.policy} +%for esme in esme_list: + esme ${esme.system_id} + password ${esme.password} default-route +%endfor ctrl bind ${ctrl_bind_ip} %for bts in bts_list: diff --git a/src/osmo_gsm_tester/esme.py b/src/osmo_gsm_tester/esme.py new file mode 100644 index 0000000..31649ed --- /dev/null +++ b/src/osmo_gsm_tester/esme.py @@ -0,0 +1,133 @@ +# osmo_gsm_tester: SMPP ESME to talk to SMSC +# +# Copyright (C) 2017 by sysmocom - s.f.m.c. GmbH +# +# Author: Pau Espin Pedrol <pespin at sysmocom.de> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import smpplib.gsm +import smpplib.client +import smpplib.consts +import smpplib.exceptions + +from . import log, util, event_loop, sms + +# if you want to know what's happening inside python-smpplib +#import logging +#logging.basicConfig(level='DEBUG') + +class Esme(log.Origin): + msisdn = None + client = None + smsc = None + + def __init__(self): + self.system_id = 'esme-id' + self.password = 'esme-pwd' + super().__init__(log.C_TST, self.system_id) + self.connected = False + self.binded = False + self.listen_flag = False + + def __del__(self): + try: + self.disconnect() + except smpplib.exceptions.ConnectionError: + pass + + def set_smsc(self, smsc): + self.smsc = smsc + + def set_system_id(self, name=None): + self.system_id = name + + def set_password(self, password=None): + self.password = password + + def conf_for_smsc(self): + config = { 'system_id': self.system_id, 'password': self.password } + return config + + def poll_handler(self): + self.client.poll() + + def start_listening(self): + self.listen_flag = True + event_loop.register_poll_func(self.poll_handler) + + def stop_listening(self): + if self.listen_flag: + self.listen_flag = False + # Empty the queue before processing the unbind + disconnect PDUs + event_loop.unregister_poll_func(self.poll_handler) + self.poll_handler() + + def connect(self): + host, port = self.smsc.smpp_addr_port() + if self.client: + self.disconnect() + self.client = smpplib.client.Client(host, port, timeout=None) + self.client.set_message_sent_handler( + lambda pdu: self.dbg('message sent:', repr(pdu)) ) + self.client.set_message_received_handler( + lambda pdu: self.dbg('message received:', repr(pdu)) ) + self.client.connect() + self.connected = True + self.client.bind_transceiver(system_id=self.system_id, password=self.password) + self.binded = True + self.log('Connected and binded successfully. Start listening') + self.start_listening() + + def disconnect(self): + self.stop_listening() + if self.binded: + self.client.unbind() + self.binded = False + if self.connected: + self.client.disconnect() + self.connected = False + + def set_msisdn(self, msisdn): + self.msisdn = msisdn + self.set_name('esme-%s' % self.msisdn) + + def run_method_expect_failure(self, errcode, method, *args): + try: + method(*args) + #it should not succeed, raise an exception: + raise log.Error('SMPP Failure: %s should have failed with SMPP error %d (%s) but succeeded.' % (method, errcode, smpplib.consts.DESCRIPTIONS[errcode])) + except smpplib.exceptions.PDUError as e: + if e.args[1] != errcode: + raise e + + def sms_send(self, sms_obj): + parts, encoding_flag, msg_type_flag = smpplib.gsm.make_parts(str(sms_obj)) + + self.log('Sending SMS "%s" to %s' % (str(sms_obj), sms_obj.dst_msisdn())) + for part in parts: + pdu = self.client.send_message( + source_addr_ton=smpplib.consts.SMPP_TON_INTL, + source_addr_npi=smpplib.consts.SMPP_NPI_ISDN, + source_addr=sms_obj.src_msisdn(), + dest_addr_ton=smpplib.consts.SMPP_TON_INTL, + dest_addr_npi=smpplib.consts.SMPP_NPI_ISDN, + destination_addr=sms_obj.dst_msisdn(), + short_message=part, + data_coding=encoding_flag, + esm_class=smpplib.consts.SMPP_MSGMODE_FORWARD, + registered_delivery=False, + ) + +# vim: expandtab tabstop=4 shiftwidth=4 diff --git a/src/osmo_gsm_tester/osmo_msc.py b/src/osmo_gsm_tester/osmo_msc.py index 443b254..d265e36 100644 --- a/src/osmo_gsm_tester/osmo_msc.py +++ b/src/osmo_gsm_tester/osmo_msc.py @@ -20,9 +20,9 @@ import os import pprint -from . import log, util, config, template, process, osmo_ctrl, pcap_recorder +from . import log, util, config, template, process, osmo_ctrl, pcap_recorder, smsc -class OsmoMsc(log.Origin): +class OsmoMsc(log.Origin, smsc.Smsc): suite_run = None ip_address = None run_dir = None @@ -32,7 +32,8 @@ config = None def __init__(self, suite_run, hlr, mgcpgw, ip_address): - super().__init__(log.C_RUN, 'osmo-msc_%s' % ip_address.get('addr')) + log.Origin.__init__(self, log.C_RUN, 'osmo-msc_%s' % ip_address.get('addr')) + smsc.Smsc.__init__(self, (ip_address.get('addr'), 2775)) self.suite_run = suite_run self.ip_address = ip_address self.hlr = hlr @@ -73,8 +74,8 @@ config.overlay(values, dict(msc=dict(ip_address=self.ip_address))) config.overlay(values, self.mgcpgw.conf_for_msc()) config.overlay(values, self.hlr.conf_for_msc()) + config.overlay(values, dict(msc=self.smsc_config())) self.config = values - self.dbg('MSC CONFIG:\n' + pprint.pformat(values)) with open(self.config_file, 'w') as f: diff --git a/src/osmo_gsm_tester/osmo_nitb.py b/src/osmo_gsm_tester/osmo_nitb.py index 3104842..d18fc1a 100644 --- a/src/osmo_gsm_tester/osmo_nitb.py +++ b/src/osmo_gsm_tester/osmo_nitb.py @@ -21,9 +21,9 @@ import re import pprint -from . import log, util, config, template, process, osmo_ctrl, pcap_recorder +from . import log, util, config, template, process, osmo_ctrl, pcap_recorder, smsc -class OsmoNitb(log.Origin): +class OsmoNitb(log.Origin, smsc.Smsc): suite_run = None ip_address = None run_dir = None @@ -32,7 +32,8 @@ bts = None def __init__(self, suite_run, ip_address): - super().__init__(log.C_RUN, 'osmo-nitb_%s' % ip_address.get('addr')) + log.Origin.__init__(self, log.C_RUN, 'osmo-nitb_%s' % ip_address.get('addr')) + smsc.Smsc.__init__(self, (ip_address.get('addr'), 2775)) self.suite_run = suite_run self.ip_address = ip_address self.bts = [] @@ -75,8 +76,8 @@ for bts in self.bts: bts_list.append(bts.conf_for_bsc()) config.overlay(values, dict(nitb=dict(net=dict(bts_list=bts_list)))) + config.overlay(values, dict(nitb=self.smsc_config())) self.config = values - self.dbg('NITB CONFIG:\n' + pprint.pformat(values)) with open(self.config_file, 'w') as f: diff --git a/src/osmo_gsm_tester/sms.py b/src/osmo_gsm_tester/sms.py index 570ef96..e264b66 100644 --- a/src/osmo_gsm_tester/sms.py +++ b/src/osmo_gsm_tester/sms.py @@ -21,14 +21,16 @@ _last_sms_idx = 0 msg = None - def __init__(self, from_msisdn=None, to_msisdn=None, *tokens): + def __init__(self, src_msisdn=None, dst_msisdn=None, *tokens): Sms._last_sms_idx += 1 + self._src_msisdn = src_msisdn + self._dst_msisdn = dst_msisdn msgs = ['message nr. %d' % Sms._last_sms_idx] msgs.extend(tokens) - if from_msisdn: - msgs.append('from %s' % from_msisdn) - if to_msisdn: - msgs.append('to %s' % to_msisdn) + if src_msisdn: + msgs.append('from %s' % src_msisdn) + if dst_msisdn: + msgs.append('to %s' % dst_msisdn) self.msg = ', '.join(msgs) def __str__(self): @@ -42,6 +44,12 @@ return self.msg == other.msg return self.msg == other + def src_msisdn(self): + return self._src_msisdn + + def dst_msisdn(self): + return self._dst_msisdn + def matches(self, msg): return self.msg == msg diff --git a/src/osmo_gsm_tester/smsc.py b/src/osmo_gsm_tester/smsc.py new file mode 100644 index 0000000..e255be0 --- /dev/null +++ b/src/osmo_gsm_tester/smsc.py @@ -0,0 +1,51 @@ +# osmo_gsm_tester: smsc interface +# +# Copyright (C) 2016-2017 by sysmocom - s.f.m.c. GmbH +# +# Author: Pau Espin Pedrol <pespin at sysmocom.de> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +from . import log, config, util, template, process + +class Smsc: + esmes = None + + SMSC_POLICY_CLOSED = 'closed' + SMSC_POLICY_ACCEPT_ALL = 'accept-all' + + def __init__(self, smpp_addr_port): + self.addr_port = smpp_addr_port + self.policy = self.SMSC_POLICY_CLOSED + self.esmes = [] + + def smsc_config(self): + values = { 'smsc': { 'policy': self.policy } } + esme_list = [] + for esme in self.esmes: + esme_list.append(esme.conf_for_smsc()) + config.overlay(values, dict(smsc=dict(esme_list=esme_list))) + return values + + def esme_add(self, esme): + self.esmes.append(esme) + esme.set_smsc(self) + + def smpp_addr_port(self): + return self.addr_port + + def set_smsc_policy(self, smsc_policy): + self.policy = smsc_policy + +# vim: expandtab tabstop=4 shiftwidth=4 diff --git a/src/osmo_gsm_tester/suite.py b/src/osmo_gsm_tester/suite.py index 5c567f8..f30333e 100644 --- a/src/osmo_gsm_tester/suite.py +++ b/src/osmo_gsm_tester/suite.py @@ -23,7 +23,7 @@ import copy import traceback import pprint -from . import config, log, template, util, resource, schema, ofono_client, event_loop +from . import config, log, template, util, resource, schema, ofono_client, event_loop, esme, sms from . import osmo_nitb from . import osmo_hlr, osmo_mgcpgw, osmo_msc, osmo_bsc, osmo_stp from . import test @@ -92,7 +92,7 @@ log.large_separator(self.suite_run.trial.name(), self.suite_run.name(), self.name(), sublevel=3) self.status = Test.UNKNOWN self.start_timestamp = time.time() - test.setup(self.suite_run, self, ofono_client, sys.modules[__name__], event_loop) + test.setup(self.suite_run, self, ofono_client, sys.modules[__name__], event_loop, sms) with self.redirect_stdout(): util.run_python_file('%s.%s' % (self.suite_run.definition.name(), self.basename), self.path) @@ -343,8 +343,13 @@ l.append(self.modem()) return l + def esme(self): + esme_obj = esme.Esme() + esme_obj.set_msisdn(self.msisdn()) + return esme_obj + def msisdn(self): - msisdn = self.resources_pool.next_msisdn(self.origin) + msisdn = self.resources_pool.next_msisdn(self) self.log('using MSISDN', msisdn) return msisdn diff --git a/src/osmo_gsm_tester/templates/osmo-msc.cfg.tmpl b/src/osmo_gsm_tester/templates/osmo-msc.cfg.tmpl index 247365e..1a00af7 100644 --- a/src/osmo_gsm_tester/templates/osmo-msc.cfg.tmpl +++ b/src/osmo_gsm_tester/templates/osmo-msc.cfg.tmpl @@ -21,12 +21,14 @@ assign-tmsi ctrl bind ${msc.ip_address.addr} -smpp - local-tcp-ip ${msc.ip_address.addr} 2775 - system-id test - policy closed - esme test - password test - default-route + smpp + local-tcp-ip ${msc.ip_address.addr} 2775 + system-id test-nitb + policy ${msc.smsc.policy} + %for esme in msc.smsc.esme_list: + esme ${esme.system_id} + password ${esme.password} + default-route + %endfor hlr remote-ip ${hlr.ip_address.addr} diff --git a/src/osmo_gsm_tester/templates/osmo-nitb.cfg.tmpl b/src/osmo_gsm_tester/templates/osmo-nitb.cfg.tmpl index a47ac02..a2bd249 100644 --- a/src/osmo_gsm_tester/templates/osmo-nitb.cfg.tmpl +++ b/src/osmo_gsm_tester/templates/osmo-nitb.cfg.tmpl @@ -76,10 +76,12 @@ %endfor smpp local-tcp-ip ${nitb.ip_address.addr} 2775 - system-id test - policy closed - esme test - password test + system-id test-nitb + policy ${nitb.smsc.policy} +%for esme in nitb.smsc.esme_list: + esme ${esme.system_id} + password ${esme.password} default-route +%endfor ctrl bind ${nitb.ip_address.addr} diff --git a/src/osmo_gsm_tester/test.py b/src/osmo_gsm_tester/test.py index 2958501..49911b3 100644 --- a/src/osmo_gsm_tester/test.py +++ b/src/osmo_gsm_tester/test.py @@ -33,9 +33,10 @@ poll = None prompt = None Timeout = None +Sms = None -def setup(suite_run, _test, ofono_client, suite_module, event_module): - global trial, suite, test, resources, log, dbg, err, wait, wait_no_raise, sleep, poll, prompt, Timeout +def setup(suite_run, _test, ofono_client, suite_module, event_module, sms_module): + global trial, suite, test, resources, log, dbg, err, wait, wait_no_raise, sleep, poll, prompt, Timeout, Sms trial = suite_run.trial suite = suite_run test = _test @@ -49,5 +50,6 @@ poll = event_module.poll prompt = suite_run.prompt Timeout = suite_module.Timeout + Sms = sms_module.Sms # vim: expandtab tabstop=4 shiftwidth=4 diff --git a/suites/aoip_smpp/esme_connect_policy_acceptall.py b/suites/aoip_smpp/esme_connect_policy_acceptall.py new file mode 100755 index 0000000..d3ec2f5 --- /dev/null +++ b/suites/aoip_smpp/esme_connect_policy_acceptall.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 + +# This test checks following use-cases while in 'accept-all' policy: +# * SMPP interface of SMSC accepts SMPP clients (ESMEs) which do not appear on the config file + +from osmo_gsm_tester.test import * + +hlr = suite.hlr() +bts = suite.bts() +mgcpgw = suite.mgcpgw(bts_ip=bts.remote_addr()) +msc = suite.msc(hlr, mgcpgw) +bsc = suite.bsc(msc) +bsc.bts_add(bts) + +esme = suite.esme() +msc.set_smsc_policy(msc.SMSC_POLICY_ACCEPT_ALL) + +# here we deliberately ommit calling msc.esme_add() to avoid having it included in the smsc config. +hlr.start() +msc.start() +mgcpgw.start() +bsc.start() +bts.start() + +# Connect should work even if we didn't previously configure the esme in the smsc. +esme.set_smsc(msc) +esme.connect() +esme.disconnect() diff --git a/suites/aoip_smpp/esme_connect_policy_closed.py b/suites/aoip_smpp/esme_connect_policy_closed.py new file mode 100755 index 0000000..0c989b5 --- /dev/null +++ b/suites/aoip_smpp/esme_connect_policy_closed.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 + +# This test checks following use-cases while in 'closed' policy: +# * SMPP interface of SMSC accepts SMPP clients (ESMEs) with password previously +# defined in its configuration file. +# * SMPP interface of SMSC rejects ESMEs with known system id but wrong password. +# * SMPP interface of SMSC rejects ESEMs with unknown system id + +from osmo_gsm_tester.test import * + +SMPP_ESME_RINVPASWD = 0x0000000E +SMPP_ESME_RINVSYSID = 0x0000000F + +hlr = suite.hlr() +bts = suite.bts() +mgcpgw = suite.mgcpgw(bts_ip=bts.remote_addr()) +msc = suite.msc(hlr, mgcpgw) +bsc = suite.bsc(msc) +bsc.bts_add(bts) + +esme = suite.esme() +msc.set_smsc_policy(msc.SMSC_POLICY_CLOSED) +msc.esme_add(esme) + +hlr.start() +msc.start() +mgcpgw.start() +bsc.start() +bts.start() + +# Connect should work as we configured msc properly at esme_add() time. +log('Test with correct credentials...') +esme.connect() +esme.disconnect() + +# We now change the password, it should fail: +log('Test with bad password...') +correct_password = esme.password +new_password = 'barfoo' if correct_password == 'foobar' else 'foobar' +esme.set_password(new_password) +esme.run_method_expect_failure(SMPP_ESME_RINVPASWD, esme.connect) +esme.set_password(correct_password) + +# We now change the system_id, it should fail: +log('Test with bad system id...') +correct_system_id = esme.system_id +new_system_id = 'barfoo' if correct_system_id == 'foobar' else 'foobar' +esme.set_system_id(new_system_id) +esme.run_method_expect_failure(SMPP_ESME_RINVSYSID, esme.connect) +esme.set_system_id(correct_system_id) diff --git a/suites/aoip_smpp/esme_ms_sms.py b/suites/aoip_smpp/esme_ms_sms.py new file mode 100755 index 0000000..41cf9b5 --- /dev/null +++ b/suites/aoip_smpp/esme_ms_sms.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 + +# This test checks following use-cases: +# * SMPP interface of SMSC accepts SMPP clients (ESMEs) with password previously +# defined in its configuration file. +# * ESME can send an SMS to an already registered MS when SMSC is in 'forward' mode. + +from osmo_gsm_tester.test import * + +SMPP_ESME_RINVDSTADR = 0x0000000B + +hlr = suite.hlr() +bts = suite.bts() +mgcpgw = suite.mgcpgw(bts_ip=bts.remote_addr()) +msc = suite.msc(hlr, mgcpgw) +bsc = suite.bsc(msc) +bsc.bts_add(bts) + +ms = suite.modem() +esme = suite.esme() +msc.esme_add(esme) +print('start msc and bts...') +hlr.start() +msc.start() +mgcpgw.start() +bsc.start() +bts.start() + +esme.connect() +hlr.subscriber_add(ms) +ms.connect(msc.mcc_mnc()) + +ms.log_info() +print('waiting for modem to attach...') +wait(ms.is_connected, nitb.mcc_mnc()) +wait(msc.subscriber_attached, ms) + +print('sending first sms...') +msg = Sms(esme.msisdn, ms.msisdn, 'smpp send message') +esme.sms_send(msg) +wait(ms.sms_was_received, msg) + +print('sending second sms (unicode chars not in gsm aplhabet)...') +msg = Sms(esme.msisdn, ms.msisdn, 'chars:[кизаçйж]') +esme.sms_send(msg) +wait(ms.sms_was_received, msg) + +# FIXME: This test is not failing with error but succeeds, need to check why: (forward vs store policy?) +# wrong_msisdn = ms.msisdn + esme.msisdn +# print('sending third sms (with wrong msisdn %s)' % wrong_msisdn) +# msg = Sms(esme.msisdn, wrong_msisdn, 'smpp message with wrong dest') +# esme.run_method_expect_failure(SMPP_ESME_RINVDSTADR, esme.sms_send, msg) + +esme.disconnect() diff --git a/suites/aoip_smpp/suite.conf b/suites/aoip_smpp/suite.conf new file mode 100644 index 0000000..1a863a7 --- /dev/null +++ b/suites/aoip_smpp/suite.conf @@ -0,0 +1,10 @@ +resources: + ip_address: + - times: 4 + bts: + - times: 1 + modem: + - times: 1 + +defaults: + timeout: 60s diff --git a/suites/smpp/esme_connect_policy_acceptall.py b/suites/smpp/esme_connect_policy_acceptall.py new file mode 100755 index 0000000..7efc759 --- /dev/null +++ b/suites/smpp/esme_connect_policy_acceptall.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 + +# This test checks following use-cases while in 'accept-all' policy: +# * SMPP interface of SMSC accepts SMPP clients (ESMEs) which do not appear on the config file + +from osmo_gsm_tester.test import * + +nitb = suite.nitb() +esme = suite.esme() + +nitb.set_smsc_policy(nitb.SMSC_POLICY_ACCEPT_ALL) +# here we deliberately ommit calling nitb.esme_add() to avoid having it included in the smsc config. +nitb.start() + +# Connect should work even if we didn't previously configure the esme in the smsc. +esme.set_smsc(nitb) +esme.connect() +esme.disconnect() diff --git a/suites/smpp/esme_connect_policy_closed.py b/suites/smpp/esme_connect_policy_closed.py new file mode 100755 index 0000000..916fade --- /dev/null +++ b/suites/smpp/esme_connect_policy_closed.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 + +# This test checks following use-cases while in 'closed' policy: +# * SMPP interface of SMSC accepts SMPP clients (ESMEs) with password previously +# defined in its configuration file. +# * SMPP interface of SMSC rejects ESMEs with known system id but wrong password. +# * SMPP interface of SMSC rejects ESEMs with unknown system id + +from osmo_gsm_tester.test import * + +SMPP_ESME_RINVPASWD = 0x0000000E +SMPP_ESME_RINVSYSID = 0x0000000F + +nitb = suite.nitb() +esme = suite.esme() + +nitb.set_smsc_policy(nitb.SMSC_POLICY_CLOSED) +nitb.esme_add(esme) + +nitb.start() + +# Connect should work as we configured nitb properly at esme_add() time. +log('Test with correct credentials...') +esme.connect() +esme.disconnect() + +# We now change the password, it should fail: +log('Test with bad password...') +correct_password = esme.password +new_password = 'barfoo' if correct_password == 'foobar' else 'foobar' +esme.set_password(new_password) +esme.run_method_expect_failure(SMPP_ESME_RINVPASWD, esme.connect) +esme.set_password(correct_password) + +# We now change the system_id, it should fail: +log('Test with bad system id...') +correct_system_id = esme.system_id +new_system_id = 'barfoo' if correct_system_id == 'foobar' else 'foobar' +esme.set_system_id(new_system_id) +esme.run_method_expect_failure(SMPP_ESME_RINVSYSID, esme.connect) +esme.set_system_id(correct_system_id) diff --git a/suites/smpp/esme_ms_sms.py b/suites/smpp/esme_ms_sms.py new file mode 100755 index 0000000..9606e40 --- /dev/null +++ b/suites/smpp/esme_ms_sms.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 + +# This test checks following use-cases: +# * SMPP interface of SMSC accepts SMPP clients (ESMEs) with password previously +# defined in its configuration file. +# * ESME can send an SMS to an already registered MS when SMSC is in 'forward' mode. + +from osmo_gsm_tester.test import * + +SMPP_ESME_RINVDSTADR = 0x0000000B + +nitb = suite.nitb() +bts = suite.bts() +ms = suite.modem() +esme = suite.esme() + +print('start nitb and bts...') +nitb.bts_add(bts) +nitb.esme_add(esme) +nitb.start() +bts.start() + +esme.connect() +nitb.subscriber_add(ms) +ms.connect(nitb.mcc_mnc()) + +ms.log_info() +print('waiting for modem to attach...') +wait(ms.is_connected, nitb.mcc_mnc()) +wait(nitb.subscriber_attached, ms) + +print('sending first sms...') +msg = Sms(esme.msisdn, ms.msisdn, 'smpp send message') +esme.sms_send(msg) +wait(ms.sms_was_received, msg) + +print('sending second sms (unicode chars not in gsm aplhabet)...') +msg = Sms(esme.msisdn, ms.msisdn, 'chars:[кизаçйж]') +esme.sms_send(msg) +wait(ms.sms_was_received, msg) + + +# FIXME: This test is not failing with error but succeeds, need to check why: (forward vs store policy?) +# wrong_msisdn = ms.msisdn + esme.msisdn +# print('sending third sms (with wrong msisdn %s)' % wrong_msisdn) +# msg = Sms(esme.msisdn, wrong_msisdn, 'smpp message with wrong dest') +# esme.run_method_expect_failure(SMPP_ESME_RINVDSTADR, esme.sms_send, msg) + +esme.disconnect() diff --git a/suites/smpp/suite.conf b/suites/smpp/suite.conf new file mode 100644 index 0000000..eb59abb --- /dev/null +++ b/suites/smpp/suite.conf @@ -0,0 +1,10 @@ +resources: + ip_address: + - times: 1 + bts: + - times: 1 + modem: + - times: 1 + +defaults: + timeout: 60s -- To view, visit https://gerrit.osmocom.org/2884 To unsubscribe, visit https://gerrit.osmocom.org/settings Gerrit-MessageType: newpatchset Gerrit-Change-Id: I14ca3cb009d6d646a449ca99b0200da12085c0da Gerrit-PatchSet: 3 Gerrit-Project: osmo-gsm-tester Gerrit-Branch: master Gerrit-Owner: Pau Espin Pedrol <pespin at sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: Neels Hofmeyr <nhofmeyr at sysmocom.de> Gerrit-Reviewer: Pau Espin Pedrol <pespin at sysmocom.de>