summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--selftest/real_suite/default-suites.conf2
-rw-r--r--selftest/real_suite/default.conf12
-rw-r--r--selftest/real_suite/resources.conf6
-rw-r--r--selftest/real_suite/scenarios/sysmo.conf3
-rwxr-xr-xselftest/real_suite/suites/sms/mo_mt_sms.py4
-rw-r--r--src/osmo_gsm_tester/bts_osmotrx.py7
-rw-r--r--src/osmo_gsm_tester/bts_sysmo.py75
-rw-r--r--src/osmo_gsm_tester/log.py7
-rw-r--r--src/osmo_gsm_tester/osmo_ctrl.py2
-rw-r--r--src/osmo_gsm_tester/process.py37
-rw-r--r--src/osmo_gsm_tester/suite.py16
11 files changed, 126 insertions, 45 deletions
diff --git a/selftest/real_suite/default-suites.conf b/selftest/real_suite/default-suites.conf
index 84a28b6..601076a 100644
--- a/selftest/real_suite/default-suites.conf
+++ b/selftest/real_suite/default-suites.conf
@@ -1 +1 @@
-- sms:trx
+- sms:sysmo
diff --git a/selftest/real_suite/default.conf b/selftest/real_suite/default.conf
index b247722..251a7b8 100644
--- a/selftest/real_suite/default.conf
+++ b/selftest/real_suite/default.conf
@@ -17,12 +17,12 @@ nitb_bts:
timeslot_list:
- phys_chan_config: CCCH+SDCCH4
- phys_chan_config: SDCCH8
- - phys_chan_config: TCH_F/TCH_H/PDCH
- - phys_chan_config: TCH_F/TCH_H/PDCH
- - phys_chan_config: TCH_F/TCH_H/PDCH
- - phys_chan_config: TCH_F/TCH_H/PDCH
- - phys_chan_config: TCH_F/TCH_H/PDCH
- - phys_chan_config: TCH_F/TCH_H/PDCH
+ - phys_chan_config: TCH/F_TCH/H_PDCH
+ - phys_chan_config: TCH/F_TCH/H_PDCH
+ - phys_chan_config: TCH/F_TCH/H_PDCH
+ - phys_chan_config: TCH/F_TCH/H_PDCH
+ - phys_chan_config: TCH/F_TCH/H_PDCH
+ - phys_chan_config: TCH/F_TCH/H_PDCH
osmo_bts_sysmo:
ipa_unit_id: 1123
diff --git a/selftest/real_suite/resources.conf b/selftest/real_suite/resources.conf
index a6c396b..5fe4ca5 100644
--- a/selftest/real_suite/resources.conf
+++ b/selftest/real_suite/resources.conf
@@ -1,9 +1,9 @@
# all hardware and interfaces available to this osmo-gsm-tester
nitb_iface:
-- addr: 127.0.0.10
-- addr: 127.0.0.11
-- addr: 127.0.0.12
+- addr: 10.42.42.1
+- addr: 10.42.42.2
+- addr: 10.42.42.3
bts:
- label: sysmoBTS 1002
diff --git a/selftest/real_suite/scenarios/sysmo.conf b/selftest/real_suite/scenarios/sysmo.conf
new file mode 100644
index 0000000..5980c1a
--- /dev/null
+++ b/selftest/real_suite/scenarios/sysmo.conf
@@ -0,0 +1,3 @@
+resources:
+ bts:
+ - type: sysmo
diff --git a/selftest/real_suite/suites/sms/mo_mt_sms.py b/selftest/real_suite/suites/sms/mo_mt_sms.py
index b97d332..9c8cca9 100755
--- a/selftest/real_suite/suites/sms/mo_mt_sms.py
+++ b/selftest/real_suite/suites/sms/mo_mt_sms.py
@@ -10,7 +10,7 @@ ms_mt = suite.modem()
print('start nitb and bts...')
nitb.bts_add(bts)
nitb.start()
-sleep(.1)
+sleep(1)
assert nitb.running()
bts.start()
@@ -19,7 +19,7 @@ nitb.subscriber_add(ms_mt)
ms_mo.connect(nitb)
ms_mt.connect(nitb)
-wait(nitb.subscriber_attached, ms_mo, ms_mt)
+wait(nitb.subscriber_attached, ms_mo, ms_mt, timeout=20)
sms = ms_mo.sms_send(ms_mt.msisdn)
wait(ms_mt.sms_received, sms)
diff --git a/src/osmo_gsm_tester/bts_osmotrx.py b/src/osmo_gsm_tester/bts_osmotrx.py
index cff63ab..2bdacec 100644
--- a/src/osmo_gsm_tester/bts_osmotrx.py
+++ b/src/osmo_gsm_tester/bts_osmotrx.py
@@ -24,7 +24,6 @@ class OsmoBtsTrx(log.Origin):
suite_run = None
nitb = None
run_dir = None
- processes = None
inst = None
env = None
@@ -37,8 +36,6 @@ class OsmoBtsTrx(log.Origin):
self.conf = conf
self.set_name('osmo-bts-trx')
self.set_log_category(log.C_RUN)
- self.processes = {}
- self.inst = None
self.env = {}
def start(self):
@@ -62,9 +59,6 @@ class OsmoBtsTrx(log.Origin):
self.suite_run.poll()
def launch_process(self, binary_name, *args):
- if self.processes.get(binary_name) is not None:
- raise RuntimeError('Attempt to launch twice: %r' % binary_name)
-
binary = os.path.abspath(self.inst.child('bin', binary_name))
run_dir = self.run_dir.new_dir(binary_name)
if not os.path.isfile(binary):
@@ -72,7 +66,6 @@ class OsmoBtsTrx(log.Origin):
proc = process.Process(binary_name, run_dir,
(binary,) + args,
env=self.env)
- self.processes[binary_name] = proc
self.suite_run.remember_to_stop(proc)
proc.launch()
diff --git a/src/osmo_gsm_tester/bts_sysmo.py b/src/osmo_gsm_tester/bts_sysmo.py
index de79f65..190297f 100644
--- a/src/osmo_gsm_tester/bts_sysmo.py
+++ b/src/osmo_gsm_tester/bts_sysmo.py
@@ -17,18 +17,29 @@
# 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
+import os
+from . import log, config, util, template, process
class SysmoBts(log.Origin):
suite_run = None
nitb = None
run_dir = None
+ inst = None
+ remote_addr = None
+ remote_inst = None
+ remote_env = None
+ remote_dir = None
+
+ REMOTE_DIR = '/osmo-gsm-tester'
+ BTS_SYSMO_BIN = 'osmo-bts-sysmo'
+ BTS_SYSMO_CFG = 'osmo-bts-sysmo.cfg'
def __init__(self, suite_run, conf):
self.suite_run = suite_run
self.conf = conf
self.set_name('osmo-bts-sysmo')
self.set_log_category(log.C_RUN)
+ self.remote_env = {}
def start(self):
if self.nitb is None:
@@ -36,12 +47,68 @@ class SysmoBts(log.Origin):
self.log('Starting sysmoBTS to connect to', self.nitb)
self.run_dir = util.Dir(self.suite_run.trial.get_run_dir().new_dir(self.name()))
self.configure()
- self.err('SysmoBts is not yet implemented')
+
+ self.inst = util.Dir(os.path.abspath(self.suite_run.trial.get_inst(SysmoBts.BTS_SYSMO_BIN)))
+ lib = self.inst.child('lib')
+ if not os.path.isdir(lib):
+ self.raise_exn('No lib/ in', self.inst)
+ if not self.inst.isfile('bin', SysmoBts.BTS_SYSMO_BIN):
+ self.raise_exn('No osmo-bts-sysmo binary in', self.inst)
+
+ self.remote_dir = util.Dir(SysmoBts.REMOTE_DIR)
+ self.remote_inst = util.Dir(self.remote_dir.child(os.path.basename(str(self.inst))))
+
+ self.run_remote('rm-remote-dir', ('test', '!', '-d', SysmoBts.REMOTE_DIR, '||', 'rm', '-rf', SysmoBts.REMOTE_DIR))
+ self.run_remote('mk-remote-dir', ('mkdir', '-p', SysmoBts.REMOTE_DIR))
+ self.run_local('scp-inst-to-sysmobts',
+ ('scp', '-r', str(self.inst), '%s:%s' % (self.remote_addr, str(self.remote_inst))))
+
+ remote_run_dir = self.remote_dir.child(SysmoBts.BTS_SYSMO_BIN)
+ self.run_remote('mk-remote-run-dir', ('mkdir', '-p', remote_run_dir))
+
+ remote_config_file = self.remote_dir.child(SysmoBts.BTS_SYSMO_CFG)
+ self.run_local('scp-cfg-to-sysmobts',
+ ('scp', '-r', self.config_file, '%s:%s' % (self.remote_addr, remote_config_file)))
+
+ remote_lib = self.remote_inst.child('lib')
+ remote_binary = self.remote_inst.child('bin', 'osmo-bts-sysmo')
+ self.launch_remote('osmo-bts-sysmo',
+ ('LD_LIBRARY_PATH=%s' % remote_lib,
+ remote_binary, '-c', remote_config_file, '-r', '1'),
+ remote_cwd=remote_run_dir)
+
+ def _process_remote(self, name, popen_args, remote_cwd=None):
+ run_dir = self.run_dir.new_dir(name)
+ return process.RemoteProcess(name, run_dir, self.remote_addr, remote_cwd,
+ popen_args)
+
+ def run_remote(self, name, popen_args, remote_cwd=None):
+ proc = self._process_remote(name, popen_args, remote_cwd)
+ proc.launch()
+ proc.wait()
+ if proc.result != 0:
+ proc.raise_exn('Exited in error')
+
+ def launch_remote(self, name, popen_args, remote_cwd=None):
+ proc = self._process_remote(name, popen_args, remote_cwd)
+ self.suite_run.remember_to_stop(proc)
+ proc.launch()
+
+ def run_local(self, name, popen_args):
+ run_dir = self.run_dir.new_dir(name)
+ proc = process.Process(name, run_dir, popen_args)
+ proc.launch()
+ proc.wait()
+ if proc.result != 0:
+ proc.raise_exn('Exited in error')
def configure(self):
if self.nitb is None:
raise RuntimeError('BTS needs to be added to a NITB before it can be configured')
- self.config_file = self.run_dir.new_file('osmo-bts-sysmo.cfg')
+
+ self.remote_addr = self.conf.get('addr')
+
+ self.config_file = self.run_dir.new_file(SysmoBts.BTS_SYSMO_CFG)
self.dbg(config_file=self.config_file)
values = { 'osmo_bts_sysmo': config.get_defaults('osmo_bts_sysmo') }
@@ -51,7 +118,7 @@ class SysmoBts(log.Origin):
self.dbg(conf=values)
with open(self.config_file, 'w') as f:
- r = template.render('osmo-bts-sysmo.cfg', values)
+ r = template.render(SysmoBts.BTS_SYSMO_CFG, values)
self.dbg(r)
f.write(r)
diff --git a/src/osmo_gsm_tester/log.py b/src/osmo_gsm_tester/log.py
index a4f78df..f56d2c9 100644
--- a/src/osmo_gsm_tester/log.py
+++ b/src/osmo_gsm_tester/log.py
@@ -66,7 +66,7 @@ class LogTarget:
get_time_str = lambda self: time.strftime(self.log_time_fmt)
# sink that gets each complete logging line
- log_sink = sys.stderr.write
+ log_sink = sys.__stdout__.write
category_levels = None
@@ -182,8 +182,9 @@ class LogTarget:
loglevel,
' '.join(log_line))
- self.log_sink(log_str.strip() + '\n')
-
+ if not log_str.endswith('\n'):
+ log_str = log_str + '\n'
+ self.log_sink(log_str)
targets = [ LogTarget() ]
diff --git a/src/osmo_gsm_tester/osmo_ctrl.py b/src/osmo_gsm_tester/osmo_ctrl.py
index c3a09db..736c943 100644
--- a/src/osmo_gsm_tester/osmo_ctrl.py
+++ b/src/osmo_gsm_tester/osmo_ctrl.py
@@ -79,10 +79,12 @@ class OsmoCtrl(log.Origin):
self._send(getmsg)
def __enter__(self):
+ super().__enter__()
self.connect()
return self
def __exit__(self, *exc_info):
self.disconnect()
+ super().__exit__(*exc_info)
# vim: expandtab tabstop=4 shiftwidth=4
diff --git a/src/osmo_gsm_tester/process.py b/src/osmo_gsm_tester/process.py
index 8152ff0..78814c0 100644
--- a/src/osmo_gsm_tester/process.py
+++ b/src/osmo_gsm_tester/process.py
@@ -22,7 +22,7 @@ import time
import subprocess
import signal
-from . import log
+from . import log, test
from .util import Dir
class Process(log.Origin):
@@ -166,7 +166,9 @@ class Process(log.Origin):
if self.result is not None:
self.cleanup()
- def is_running(self):
+ def is_running(self, poll_first=True):
+ if poll_first:
+ self.poll()
return self.process_obj is not None and self.result is None
def get_output(self, which):
@@ -178,9 +180,12 @@ class Process(log.Origin):
return f2.read()
def get_output_tail(self, which, tail=10, prefix=''):
- out = self.get_output(which).splitlines()
+ out = self.get_output(which)
+ if not out:
+ return None
+ out = out.splitlines()
tail = min(len(out), tail)
- return ('\n' + prefix).join(out[-tail:])
+ return prefix + ('\n' + prefix).join(out[-tail:])
def get_stdout(self):
return self.get_output('stdout')
@@ -194,28 +199,32 @@ class Process(log.Origin):
def get_stderr_tail(self, tail=10, prefix=''):
return self.get_output_tail('stderr', tail, prefix)
- def terminated(self):
- self.poll()
+ def terminated(self, poll_first=True):
+ if poll_first:
+ self.poll()
return self.result is not None
- def wait(self):
- self.process_obj.wait()
- self.poll()
+ def wait(self, timeout=300):
+ test.wait(self.terminated, timeout=timeout)
class RemoteProcess(Process):
- def __init__(self, remote_host, remote_cwd, *process_args, **process_kwargs):
- super().__init__(*process_args, **process_kwargs)
+ def __init__(self, name, run_dir, remote_host, remote_cwd, popen_args, **popen_kwargs):
+ super().__init__(name, run_dir, popen_args, **popen_kwargs)
self.remote_host = remote_host
self.remote_cwd = remote_cwd
# hacky: instead of just prepending ssh, i.e. piping stdout and stderr
# over the ssh link, we should probably run on the remote side,
# monitoring the process remotely.
- self.popen_args = ['ssh', '-t', self.remote_host,
- 'cd "%s"; %s' % (self.remote_cwd,
- ' '.join(['"%s"' % arg for arg in self.popen_args]))]
+ if self.remote_cwd:
+ cd = 'cd "%s"; ' % self.remote_cwd
+ else:
+ cd = ''
+ self.popen_args = ['ssh', self.remote_host,
+ '%s%s' % (cd,
+ ' '.join(self.popen_args))]
self.dbg(self.popen_args, dir=self.run_dir, conf=self.popen_kwargs)
# vim: expandtab tabstop=4 shiftwidth=4
diff --git a/src/osmo_gsm_tester/suite.py b/src/osmo_gsm_tester/suite.py
index 2d6c67b..08965b5 100644
--- a/src/osmo_gsm_tester/suite.py
+++ b/src/osmo_gsm_tester/suite.py
@@ -232,9 +232,11 @@ class SuiteRun(log.Origin):
self.log('using MSISDN', msisdn)
return msisdn
- def wait(self, condition, *condition_args, timeout=300, **condition_kwargs):
+ def _wait(self, condition, condition_args, condition_kwargs, timeout, timestep):
if not timeout or timeout < 0:
raise RuntimeError('wait() *must* time out at some point. timeout=%r' % timeout)
+ if timestep < 0.1:
+ timestep = 0.1
started = time.time()
while True:
@@ -244,17 +246,21 @@ class SuiteRun(log.Origin):
waited = time.time() - started
if waited > timeout:
return False
- time.sleep(.1)
+ time.sleep(timestep)
+
+ def wait(self, condition, *condition_args, timeout=300, timestep=1, **condition_kwargs):
+ if not self._wait(condition, condition_args, condition_kwargs, timeout, timestep):
+ raise RuntimeError('Timeout expired')
def sleep(self, seconds):
- self.wait(lambda: False, timeout=seconds)
+ assert seconds > 0.
+ self._wait(lambda: False, [], {}, timeout=seconds, timestep=min(seconds, 1))
def poll(self):
ofono_client.poll()
if self._processes:
for process in self._processes:
- process.poll()
- if not process.is_running():
+ if process.terminated():
process.log_stdout_tail()
process.log_stderr_tail()
process.raise_exn('Process ended prematurely')