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
This commit is contained in:
Your Name 2017-04-13 03:11:59 +02:00 committed by Neels Hofmeyr
parent 17c139ef4c
commit 44af3415a5
16 changed files with 98 additions and 68 deletions

View File

@ -11,6 +11,7 @@ nitb_bts:
location_area_code: 23
base_station_id_code: 63
stream_id: 255
osmobsc_bts_type: sysmobts
trx_list:
- max_power_red: 22
arfcn: 868

View File

@ -7,22 +7,22 @@ nitb_iface:
bts:
- label: sysmoBTS 1002
type: sysmo
type: osmo-bts-sysmo
ipa_unit_id: 1
addr: 10.42.42.114
band: GSM-1800
- label: octBTS 3000
type: oct
type: osmo-bts-octphy
ipa_unit_id: 5
addr: 10.42.42.115
band: GSM-1800
trx:
trx_list:
- hw_addr: 00:0c:90:32:b5:8a
net_device: eth0.2342
- label: Ettus B210
type: osmotrx
type: osmo-bts-trx
ipa_unit_id: 6
addr: 10.42.42.116
band: GSM-1800
@ -32,7 +32,7 @@ bts:
ipa_unit_id: 1902
addr: 10.42.42.190
band: GSM-1900
trx:
trx_list:
- hw_addr: 00:02:95:00:41:b3
arfcn:

View File

@ -1,3 +1,3 @@
resources:
bts:
- type: octphy
- type: osmo-bts-octphy

View File

@ -1,3 +1,3 @@
resources:
bts:
- type: sysmo
- type: osmo-bts-sysmo

View File

@ -1,3 +1,3 @@
resources:
bts:
- type: osmotrx
- type: osmo-bts-trx

View File

@ -143,38 +143,50 @@ if __name__ == '__main__':
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

View File

@ -52,7 +52,7 @@ class OsmoBtsOctphy(log.Origin):
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 @@ class OsmoBtsOctphy(log.Origin):
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

View File

@ -92,8 +92,6 @@ class OsmoBtsTrx(log.Origin):
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

View File

@ -127,7 +127,6 @@ class SysmoBts(log.Origin):
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

View File

@ -177,6 +177,12 @@ def get_defaults(for_kind):
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 @@ def get_scenario(name, validation_schema=None):
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):

View File

@ -186,6 +186,14 @@ class LogTarget:
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 @@ def _log_all_targets(origin, category, level, src, messages, named_items=None):
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)

View File

@ -29,7 +29,7 @@ from . import util
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 @@ RESOURCES_SCHEMA = {
'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 @@ WANT_SCHEMA = util.dict_add(
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):

View File

@ -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 @@ class SuiteDefinition(log.Origin):
SuiteDefinition.CONF_SCHEMA)
self.load_tests()
def load_tests(self):
with self:
self.tests = []
@ -122,22 +122,27 @@ class SuiteRun(log.Origin):
_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 @@ class SuiteRun(log.Origin):
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 @@ class SuiteRun(log.Origin):
self.log('prompt entered:', entered)
return entered
loaded_suite_definitions = {}
def load(suite_name):
@ -319,7 +324,7 @@ def load_suite_scenario_str(suite_scenario_str):
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')

View File

@ -20,13 +20,17 @@ log stderr
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

View File

@ -46,7 +46,7 @@ network
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}

View File

@ -74,6 +74,7 @@ class DictProxy:
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 @@ class DictProxy:
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