1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

dbus/testlib.py: Improve type checking

Leverage the introspection data to ensure that the service is returning
what is says it will be returning for methods and properties.
This commit is contained in:
Tony Asleson 2016-08-29 12:34:19 -05:00
parent 9241dbdf57
commit 313c40ed09

View File

@ -63,7 +63,7 @@ class DbusIntrospection(object):
if arg_dir == 'in':
n = arg.attrib['name']
else:
n = None
n = 'RETURN_VALUE'
arg_type = arg.attrib['type']
@ -91,15 +91,68 @@ class DbusIntrospection(object):
# for m, args in list(v['methods'].items()):
# print(' method: %s' % m)
# for a, aa in args.items():
# print(' method arg: %s' % (a))
# print(' method arg: %s type %s' %
# (a, aa['a_type']))
# if v['properties']:
# for p, d in list(v['properties'].items()):
# print(' Property: %s' % (p))
# print(' Property: %s type= %s' % (p, d['p_type']))
# print('End interfaces')
return interfaces
def btsr(value):
t = type(value)
if t == dbus.Boolean:
return 'b'
elif t == dbus.ObjectPath:
return 'o'
elif t == dbus.String:
return 's'
elif t == dbus.Byte:
return 'y'
elif t == dbus.Int16:
return 'n'
elif t == dbus.Int32:
return 'i'
elif t == dbus.Int64:
return 'x'
elif t == dbus.UInt16:
return 'q'
elif t == dbus.UInt32:
return 'u'
elif t == dbus.UInt64:
return 't'
elif t == dbus.Double:
return 'd'
elif t == dbus.Struct:
rc = '('
for vt in value:
rc += btsr(vt)
rc += ')'
return rc
elif t == dbus.Array:
rc = "a"
for i in value:
rc += btsr(i)
break
return rc
else:
raise RuntimeError("Unhandled type %s" % str(t))
def verify_type(value, dbus_str_rep):
actual_str_rep = btsr(value)
if dbus_str_rep != actual_str_rep:
# print("%s ~= %s" % (dbus_str_rep, actual_str_rep))
# Unless we have a full filled out type we won't match exactly
if not dbus_str_rep.startswith(actual_str_rep):
raise RuntimeError("Incorrect type, expected= %s actual "
"= %s object= %s" %
(dbus_str_rep, actual_str_rep,
str(type(value))))
class RemoteObject(object):
def _set_props(self, props=None):
# print 'Fetching properties'
@ -119,12 +172,16 @@ class RemoteObject(object):
raise dbe
if props:
for kl, vl in list(props.items()):
# Verify type is correct!
verify_type(vl,
self.introspect[self.interface]['properties'][kl]['p_type'])
setattr(self, kl, vl)
def __init__(self, specified_bus, object_path, interface, properties=None):
def __init__(self, specified_bus, object_path, interface, introspect, properties=None):
self.object_path = object_path
self.interface = interface
self.bus = specified_bus
self.introspect = introspect
self.dbus_method = dbus.Interface(specified_bus.get_object(
BUSNAME, self.object_path), self.interface)
@ -138,7 +195,18 @@ class RemoteObject(object):
return functools.partial(self, item)
def _wrapper(self, _method_name, *args, **kwargs):
return getattr(self.dbus_method, _method_name)(*args, **kwargs)
result = getattr(self.dbus_method, _method_name)(*args, **kwargs)
#print("DEBUG: %s.%s result %s" %
# (self.interface, _method_name, str(type(result))))
if 'RETURN_VALUE' in \
self.introspect[self.interface]['methods'][_method_name]:
r_type = self.introspect[self.interface]['methods'] \
[_method_name]['RETURN_VALUE']['a_type']
verify_type(result, r_type)
return result
def update(self):
self._set_props()
@ -152,16 +220,26 @@ class ClientProxy(object):
def __init__(self, specified_bus, object_path, interface=None, props=None):
i = dbus.Interface(specified_bus.get_object(
BUSNAME, object_path), 'org.freedesktop.DBus.Introspectable')
self.intro_spect = DbusIntrospection.introspect(i.Introspect())
introspection_xml = i.Introspect()
# import xml.dom.minidom
#
# xml = xml.dom.minidom.parseString(introspection_xml)
# print(xml.toprettyxml())
self.intro_spect = DbusIntrospection.introspect(introspection_xml)
for k in self.intro_spect.keys():
sn = ClientProxy._intf_short_name(k)
# print('Client proxy has interface: %s %s' % (k, sn))
if interface and interface == k and props is not None:
ro = RemoteObject(specified_bus, object_path, k, props)
ro = RemoteObject(specified_bus, object_path, k,
self.intro_spect, props)
else:
ro = RemoteObject(specified_bus, object_path, k)
ro = RemoteObject(specified_bus, object_path, k,
self.intro_spect)
setattr(self, sn, ro)