fix octphy, fix conf, improve logging
Clearly separate the kinds of BTS hardware the GSM tester knows ('type') from
the NITB's bts/type config item ('osmobsc_bts_type' -- not 'osmonitb_...' to
stay in tune with future developments: it is the libbsc that needs this).
For BTS hardware kinds, use the full name of the binary for osmo driven models:
osmo-bts-sysmo, osmo-bts-trx, osmo-bts-octphy.
Change-Id: I1aa9b48e74013a93f9db1a34730f17717fb3b36c
diff --git a/src/osmo-gsm-tester.py b/src/osmo-gsm-tester.py
index 0137f25..17b16b7 100755
--- a/src/osmo-gsm-tester.py
+++ b/src/osmo-gsm-tester.py
@@ -143,38 +143,50 @@
trials = []
for trial_package in args.trial_package:
t = trial.Trial(trial_package)
- t.verify()
- trials.append(t)
+ try:
+ t.verify()
+ trials.append(t)
+ except:
+ t.log_exn()
trials_passed = []
trials_failed = []
for current_trial in trials:
- with current_trial:
- suites_passed = 0
- suites_failed = 0
- for suite_def, scenarios in suite_scenarios:
- suite_run = suite.SuiteRun(current_trial, suite_def, scenarios)
- result = suite_run.run_tests(test_names)
- if result.all_passed:
- suites_passed += 1
- suite_run.log('PASS')
+ try:
+ with current_trial:
+ suites_passed = []
+ suites_failed = []
+ for suite_scenario_str, suite_def, scenarios in suite_scenarios:
+ log.large_separator(current_trial.name(), suite_scenario_str)
+ suite_run = suite.SuiteRun(current_trial, suite_scenario_str, suite_def, scenarios)
+ result = suite_run.run_tests(test_names)
+ if result.all_passed:
+ suites_passed.append(suite_scenario_str)
+ suite_run.log('PASS')
+ else:
+ suites_failed.append(suite_scenario_str)
+ suite_run.err('FAIL')
+ if not suites_failed:
+ current_trial.log('PASS')
+ trials_passed.append(current_trial.name())
else:
- suites_failed += 1
- suite_run.err('FAIL')
- if not suites_failed:
- current_trial.log('PASS')
- trials_passed.append(current_trial.name())
- else:
- current_trial.err('FAIL')
- trials_failed.append(current_trial.name())
+ current_trial.err('FAIL')
+ trials_failed.append((current_trial.name(), suites_passed, suites_failed))
+ except:
+ current_trial.log_exn()
sys.stderr.flush()
sys.stdout.flush()
+ log.large_separator()
if trials_passed:
print('Trials passed:\n ' + ('\n '.join(trials_passed)))
if trials_failed:
- print('Trials failed:\n ' + ('\n '.join(trials_failed)))
+ print('Trials failed:')
+ for trial_name, suites_passed, suites_failed in trials_failed:
+ print(' %s (%d of %d suite runs failed)' % (trial_name, len(suites_failed), len(suites_failed) + len(suites_passed)))
+ for suite in suites_failed:
+ print(' FAIL:', suite)
exit(1)
# vim: expandtab tabstop=4 shiftwidth=4
diff --git a/src/osmo_gsm_tester/bts_octphy.py b/src/osmo_gsm_tester/bts_octphy.py
index 4396108..1f36a79 100644
--- a/src/osmo_gsm_tester/bts_octphy.py
+++ b/src/osmo_gsm_tester/bts_octphy.py
@@ -52,7 +52,7 @@
raise RuntimeError('No lib/ in %r' % self.inst)
self.env = { 'LD_LIBRARY_PATH': lib }
- self.launch_process(OsmoBtsTrx.BIN_BTS_OCTPHY, '-r', '1', '-c', os.path.abspath(self.config_file))
+ self.launch_process(OsmoBtsOctphy.BIN_BTS_OCTPHY, '-r', '1', '-c', os.path.abspath(self.config_file))
self.suite_run.poll()
def launch_process(self, binary_name, *args):
@@ -87,8 +87,6 @@
values = config.get_defaults('nitb_bts')
config.overlay(values, config.get_defaults('osmo_bts_octphy'))
config.overlay(values, self.conf)
- # using type 'sysmobts' for osmo-bts-octphy
- config.overlay(values, { 'type': 'sysmobts' })
self.dbg(conf=values)
return values
diff --git a/src/osmo_gsm_tester/bts_osmotrx.py b/src/osmo_gsm_tester/bts_osmotrx.py
index 417fbf2..71cdd48 100644
--- a/src/osmo_gsm_tester/bts_osmotrx.py
+++ b/src/osmo_gsm_tester/bts_osmotrx.py
@@ -92,8 +92,6 @@
values = config.get_defaults('nitb_bts')
config.overlay(values, config.get_defaults('osmo_bts_trx'))
config.overlay(values, self.conf)
- # using type 'sysmobts' for osmo-bts-trx
- config.overlay(values, { 'type': 'sysmobts' })
self.dbg(conf=values)
return values
diff --git a/src/osmo_gsm_tester/bts_sysmo.py b/src/osmo_gsm_tester/bts_sysmo.py
index 64fa7f4..dd396ff 100644
--- a/src/osmo_gsm_tester/bts_sysmo.py
+++ b/src/osmo_gsm_tester/bts_sysmo.py
@@ -127,7 +127,6 @@
values = config.get_defaults('nitb_bts')
config.overlay(values, config.get_defaults('osmo_bts_sysmo'))
config.overlay(values, self.conf)
- config.overlay(values, { 'type': 'sysmobts' })
self.dbg(conf=values)
return values
diff --git a/src/osmo_gsm_tester/config.py b/src/osmo_gsm_tester/config.py
index cbbfa6f..68bbd13 100644
--- a/src/osmo_gsm_tester/config.py
+++ b/src/osmo_gsm_tester/config.py
@@ -177,6 +177,12 @@
defaults = read_config_file('default.conf', if_missing_return={})
return defaults.get(for_kind, {})
+class Scenario(log.Origin, dict):
+ def __init__(self, name, path):
+ self.set_name(name)
+ self.set_log_category(log.C_TST)
+ self.path = path
+
def get_scenario(name, validation_schema=None):
scenarios_dir = get_scenarios_dir()
if not name.endswith('.conf'):
@@ -184,7 +190,9 @@
path = scenarios_dir.child(name)
if not os.path.isfile(path):
raise RuntimeError('No such scenario file: %r' % path)
- return read(path, validation_schema=validation_schema)
+ sc = Scenario(name, path)
+ sc.update(read(path, validation_schema=validation_schema))
+ return sc
def add(dest, src):
if is_dict(dest):
diff --git a/src/osmo_gsm_tester/log.py b/src/osmo_gsm_tester/log.py
index f56d2c9..3e96999 100644
--- a/src/osmo_gsm_tester/log.py
+++ b/src/osmo_gsm_tester/log.py
@@ -186,6 +186,14 @@
log_str = log_str + '\n'
self.log_sink(log_str)
+ def large_separator(self, *msgs):
+ msg = ' '.join(msgs)
+ if not msg:
+ msg = '------------------------------------------'
+ self.log_sink('------------------------------------------\n'
+ '%s\n'
+ '------------------------------------------\n' % msg)
+
targets = [ LogTarget() ]
def level_str(level):
@@ -207,6 +215,10 @@
for target in targets:
target.log(origin, category, level, src, messages, named_items)
+def large_separator(*msgs):
+ for target in targets:
+ target.large_separator(*msgs)
+
def get_src_from_caller(levels_up=1):
caller = getframeinfo(stack()[levels_up][0])
return '%s:%d' % (os.path.basename(caller.filename), caller.lineno)
diff --git a/src/osmo_gsm_tester/resource.py b/src/osmo_gsm_tester/resource.py
index 5cfbeaf..b842d98 100644
--- a/src/osmo_gsm_tester/resource.py
+++ b/src/osmo_gsm_tester/resource.py
@@ -29,7 +29,7 @@
from . import schema
from . import ofono_client
from . import osmo_nitb
-from . import bts_sysmo, bts_osmotrx
+from . import bts_sysmo, bts_osmotrx, bts_octphy
from .util import is_dict, is_list
@@ -54,7 +54,8 @@
'bts[].ipa_unit_id': schema.INT,
'bts[].addr': schema.IPV4,
'bts[].band': schema.BAND,
- 'bts[].trx[].hw_addr': schema.HWADDR,
+ 'bts[].trx_list[].hw_addr': schema.HWADDR,
+ 'bts[].trx_list[].net_device': schema.STR,
'arfcn[].arfcn': schema.INT,
'arfcn[].band': schema.BAND,
'modem[].label': schema.STR,
@@ -68,8 +69,9 @@
RESOURCES_SCHEMA)
KNOWN_BTS_TYPES = {
- 'sysmo': bts_sysmo.SysmoBts,
- 'osmotrx': bts_osmotrx.OsmoBtsTrx,
+ 'osmo-bts-sysmo': bts_sysmo.SysmoBts,
+ 'osmo-bts-trx': bts_osmotrx.OsmoBtsTrx,
+ 'osmo-bts-octphy': bts_octphy.OsmoBtsOctphy,
}
def register_bts_type(name, clazz):
diff --git a/src/osmo_gsm_tester/suite.py b/src/osmo_gsm_tester/suite.py
index 08965b5..74c8b28 100644
--- a/src/osmo_gsm_tester/suite.py
+++ b/src/osmo_gsm_tester/suite.py
@@ -20,6 +20,7 @@
import os
import sys
import time
+import copy
from . import config, log, template, util, resource, schema, ofono_client, osmo_nitb
from . import test
@@ -56,7 +57,6 @@
SuiteDefinition.CONF_SCHEMA)
self.load_tests()
-
def load_tests(self):
with self:
self.tests = []
@@ -122,22 +122,27 @@
_config = None
_processes = None
- def __init__(self, current_trial, suite_definition, scenarios=[]):
+ def __init__(self, current_trial, suite_scenario_str, suite_definition, scenarios=[]):
self.trial = current_trial
self.definition = suite_definition
self.scenarios = scenarios
- self.set_name(suite_definition.name())
+ self.set_name(suite_scenario_str)
self.set_log_category(log.C_TST)
self.resources_pool = resource.ResourcesPool()
def combined(self, conf_name):
- combination = self.definition.conf.get(conf_name) or {}
- for scenario in self.scenarios:
- c = scenario.get(conf_name)
- if c is None:
- continue
- config.combine(combination, c)
- return combination
+ self.dbg(combining=conf_name)
+ with log.Origin(combining_scenarios=conf_name):
+ combination = copy.deepcopy(self.definition.conf.get(conf_name) or {})
+ self.dbg(definition_conf=combination)
+ for scenario in self.scenarios:
+ with scenario:
+ c = scenario.get(conf_name)
+ self.dbg(scenario=scenario.name(), conf=c)
+ if c is None:
+ continue
+ config.combine(combination, c)
+ return combination
def resource_requirements(self):
if self._resource_requirements is None:
@@ -183,6 +188,7 @@
self.reserved_resources = self.resources_pool.reserve(self, self.resource_requirements())
def run_tests(self, names=None):
+ self.log('Suite run start')
if not self.reserved_resources:
self.reserve_resources()
results = SuiteRun.Results()
@@ -281,7 +287,6 @@
self.log('prompt entered:', entered)
return entered
-
loaded_suite_definitions = {}
def load(suite_name):
@@ -319,7 +324,7 @@
suite_name, scenario_names = parse_suite_scenario_str(suite_scenario_str)
suite = load(suite_name)
scenarios = [config.get_scenario(scenario_name) for scenario_name in scenario_names]
- return (suite, scenarios)
+ return (suite_scenario_str, suite, scenarios)
def bts_obj(suite_run, conf):
bts_type = conf.get('type')
diff --git a/src/osmo_gsm_tester/templates/osmo-bts-octphy.cfg.tmpl b/src/osmo_gsm_tester/templates/osmo-bts-octphy.cfg.tmpl
index 90d6092..bf6adf9 100644
--- a/src/osmo_gsm_tester/templates/osmo-bts-octphy.cfg.tmpl
+++ b/src/osmo_gsm_tester/templates/osmo-bts-octphy.cfg.tmpl
@@ -20,13 +20,17 @@
line vty
no login
!
-phy 0
- octphy hw-addr ${osmo_bts_octphy.hw_addr}
- octphy net-device ${osmo_bts_octphy.net_device}
+%for trx in osmo_bts_octphy.trx_list:
+phy ${loop.index}
+ octphy hw-addr ${trx.hw_addr}
+ octphy net-device ${trx.net_device}
instance 0
+%endfor
bts 0
band ${osmo_bts_octphy.band}
ipa unit-id ${osmo_bts_octphy.ipa_unit_id} 0
oml remote-ip ${osmo_bts_octphy.oml_remote_ip}
- trx 0
- phy 0 instance 0
+%for trx in osmo_bts_octphy.trx_list:
+ trx ${loop.index}
+ phy ${loop.index} instance 0
+%endfor
diff --git a/src/osmo_gsm_tester/templates/osmo-nitb.cfg.tmpl b/src/osmo_gsm_tester/templates/osmo-nitb.cfg.tmpl
index e7dc119..28cf61c 100644
--- a/src/osmo_gsm_tester/templates/osmo-nitb.cfg.tmpl
+++ b/src/osmo_gsm_tester/templates/osmo-nitb.cfg.tmpl
@@ -46,7 +46,7 @@
timer t3141 0
%for bts in nitb.net.bts_list:
bts ${loop.index}
- type ${bts.type}
+ type ${bts.osmobsc_bts_type}
band ${bts.band}
cell_identity 0
location_area_code ${bts.location_area_code}
diff --git a/src/osmo_gsm_tester/util.py b/src/osmo_gsm_tester/util.py
index 61d0f6e..e132e21 100644
--- a/src/osmo_gsm_tester/util.py
+++ b/src/osmo_gsm_tester/util.py
@@ -74,6 +74,7 @@
return dict2obj(self.obj[key])
def __getattr__(self, key):
+ 'provide error information to know which template item was missing'
try:
return dict2obj(getattr(self.obj, key))
except AttributeError:
@@ -82,19 +83,9 @@
except KeyError:
raise AttributeError(key)
-class ListProxy:
- 'allow nesting for DictProxy'
- def __init__(self, obj):
- self.obj = obj
-
- def __getitem__(self, key):
- return dict2obj(self.obj[key])
-
def dict2obj(value):
- if isinstance(value, dict):
+ if is_list(value) or is_dict(value):
return DictProxy(value)
- if isinstance(value, (tuple, list)):
- return ListProxy(value)
return value