Blame test/test-service.py

Packit 130fc8
#!/usr/bin/env python
Packit 130fc8
Packit 130fc8
# Copyright (C) 2004 Red Hat Inc. <http://www.redhat.com/>
Packit 130fc8
# Copyright (C) 2005-2007 Collabora Ltd. <http://www.collabora.co.uk/>
Packit 130fc8
#
Packit 130fc8
# Permission is hereby granted, free of charge, to any person
Packit 130fc8
# obtaining a copy of this software and associated documentation
Packit 130fc8
# files (the "Software"), to deal in the Software without
Packit 130fc8
# restriction, including without limitation the rights to use, copy,
Packit 130fc8
# modify, merge, publish, distribute, sublicense, and/or sell copies
Packit 130fc8
# of the Software, and to permit persons to whom the Software is
Packit 130fc8
# furnished to do so, subject to the following conditions:
Packit 130fc8
#
Packit 130fc8
# The above copyright notice and this permission notice shall be
Packit 130fc8
# included in all copies or substantial portions of the Software.
Packit 130fc8
#
Packit 130fc8
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
Packit 130fc8
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Packit 130fc8
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Packit 130fc8
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
Packit 130fc8
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
Packit 130fc8
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
Packit 130fc8
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
Packit 130fc8
# DEALINGS IN THE SOFTWARE.
Packit 130fc8
Packit 130fc8
import os
Packit 130fc8
import logging
Packit 130fc8
from time import sleep
Packit 130fc8
Packit 130fc8
import dbus
Packit 130fc8
Packit 130fc8
if 'DBUS_TEST_UNINSTALLED' in os.environ:
Packit 130fc8
    import _dbus_bindings
Packit 130fc8
Packit 130fc8
    builddir = os.path.normpath(os.environ["DBUS_TOP_BUILDDIR"])
Packit 130fc8
    pydir = os.path.normpath(os.environ["DBUS_TOP_SRCDIR"])
Packit 130fc8
    pkg = dbus.__file__
Packit 130fc8
Packit 130fc8
    if not pkg.startswith(pydir):
Packit 130fc8
        raise Exception("DBus modules (%s) are not being picked up from the "
Packit 130fc8
                "package" % pkg)
Packit 130fc8
Packit 130fc8
    if not _dbus_bindings.__file__.startswith(builddir):
Packit 130fc8
        raise Exception("DBus modules (%s) are not being picked up from the "
Packit 130fc8
                "package" % _dbus_bindings.__file__)
Packit 130fc8
Packit 130fc8
import dbus.service
Packit 130fc8
import dbus.glib
Packit 130fc8
import random
Packit 130fc8
Packit 130fc8
from dbus.gi_service import ExportedGObject
Packit 130fc8
from gi.repository import GObject
Packit 130fc8
from dbus._compat import is_py2, is_py3
Packit 130fc8
Packit 130fc8
Packit 130fc8
if 'DBUS_TEST_TMPDIR' in os.environ:
Packit 130fc8
    logging.basicConfig(
Packit 130fc8
            filename=os.environ['DBUS_TEST_TMPDIR'] + '/test-service.log',
Packit 130fc8
            filemode='a')
Packit 130fc8
else:
Packit 130fc8
    logging.basicConfig()
Packit 130fc8
Packit 130fc8
logging.getLogger().setLevel(1)
Packit 130fc8
logger = logging.getLogger('test-service')
Packit 130fc8
Packit 130fc8
NAME = "org.freedesktop.DBus.TestSuitePythonService"
Packit 130fc8
IFACE = "org.freedesktop.DBus.TestSuiteInterface"
Packit 130fc8
OBJECT = "/org/freedesktop/DBus/TestSuitePythonObject"
Packit 130fc8
Packit 130fc8
class RemovableObject(dbus.service.Object):
Packit 130fc8
    # Part of test for https://bugs.freedesktop.org/show_bug.cgi?id=10457
Packit 130fc8
    @dbus.service.method(IFACE, in_signature='', out_signature='b')
Packit 130fc8
    def IsThere(self):
Packit 130fc8
        return True
Packit 130fc8
Packit 130fc8
    @dbus.service.method(IFACE, in_signature='', out_signature='b')
Packit 130fc8
    def RemoveSelf(self):
Packit 130fc8
        self.remove_from_connection()
Packit 130fc8
        return True
Packit 130fc8
Packit 130fc8
class TestGObject(ExportedGObject):
Packit 130fc8
    def __init__(self, bus_name, object_path=OBJECT + '/GObject'):
Packit 130fc8
        super(TestGObject, self).__init__(bus_name, object_path)
Packit 130fc8
Packit 130fc8
    @dbus.service.method(IFACE)
Packit 130fc8
    def Echo(self, arg):
Packit 130fc8
        return arg
Packit 130fc8
Packit 130fc8
class TestInterface(dbus.service.Interface):
Packit 130fc8
    @dbus.service.method(IFACE, in_signature='', out_signature='b')
Packit 130fc8
    def CheckInheritance(self):
Packit 130fc8
        return False
Packit 130fc8
Packit 130fc8
class Fallback(dbus.service.FallbackObject):
Packit 130fc8
    def __init__(self, conn, object_path=OBJECT + '/Fallback'):
Packit 130fc8
        super(Fallback, self).__init__(conn, object_path)
Packit 130fc8
        self.add_to_connection(conn, object_path + '/Nested')
Packit 130fc8
Packit 130fc8
    @dbus.service.method(IFACE, in_signature='', out_signature='oos',
Packit 130fc8
                         path_keyword='path', rel_path_keyword='rel',
Packit 130fc8
                         connection_keyword='conn')
Packit 130fc8
    def TestPathAndConnKeywords(self, path=None, conn=None, rel=None):
Packit 130fc8
        return path, rel, conn.get_unique_name()
Packit 130fc8
Packit 130fc8
    @dbus.service.signal(IFACE, signature='s', rel_path_keyword='rel_path')
Packit 130fc8
    def SignalOneString(self, test, rel_path=None):
Packit 130fc8
        logger.info('SignalOneString(%r) @ %r', test, rel_path)
Packit 130fc8
Packit 130fc8
    # Deprecated usage
Packit 130fc8
    @dbus.service.signal(IFACE, signature='ss', path_keyword='path')
Packit 130fc8
    def SignalTwoStrings(self, test, test2, path=None):
Packit 130fc8
        logger.info('SignalTwoStrings(%r, %r) @ %r', test, test2, path)
Packit 130fc8
Packit 130fc8
    @dbus.service.method(IFACE, in_signature='su', out_signature='',
Packit 130fc8
                         path_keyword='path')
Packit 130fc8
    def EmitSignal(self, signal, value, path=None):
Packit 130fc8
        sig = getattr(self, str(signal), None)
Packit 130fc8
        assert sig is not None
Packit 130fc8
Packit 130fc8
        assert path.startswith(OBJECT + '/Fallback')
Packit 130fc8
        rel_path = path[len(OBJECT + '/Fallback'):]
Packit 130fc8
        if rel_path == '':
Packit 130fc8
            rel_path = '/'
Packit 130fc8
Packit 130fc8
        if signal == 'SignalOneString':
Packit 130fc8
            logger.info('Emitting %s from rel %r', signal, rel_path)
Packit 130fc8
            sig('I am a fallback', rel_path=rel_path)
Packit 130fc8
        else:
Packit 130fc8
            val = ('I am', 'a fallback')
Packit 130fc8
            logger.info('Emitting %s from abs %r', signal, path)
Packit 130fc8
            sig('I am', 'a deprecated fallback', path=path)
Packit 130fc8
Packit 130fc8
class MultiPathObject(dbus.service.Object):
Packit 130fc8
    SUPPORTS_MULTIPLE_OBJECT_PATHS = True
Packit 130fc8
Packit 130fc8
class TestObject(dbus.service.Object, TestInterface):
Packit 130fc8
    def __init__(self, bus_name, object_path=OBJECT):
Packit 130fc8
        dbus.service.Object.__init__(self, bus_name, object_path)
Packit 130fc8
        self._removable = RemovableObject()
Packit 130fc8
        self._multi = MultiPathObject(bus_name, object_path + '/Multi1')
Packit 130fc8
        self._multi.add_to_connection(bus_name.get_bus(),
Packit 130fc8
                                      object_path + '/Multi2')
Packit 130fc8
        self._multi.add_to_connection(bus_name.get_bus(),
Packit 130fc8
                                      object_path + '/Multi2/3')
Packit 130fc8
Packit 130fc8
    """ Echo whatever is sent
Packit 130fc8
    """
Packit 130fc8
    @dbus.service.method(IFACE)
Packit 130fc8
    def Echo(self, arg):
Packit 130fc8
        return arg
Packit 130fc8
Packit 130fc8
    @dbus.service.method(IFACE, in_signature='s', out_signature='s')
Packit 130fc8
    def AcceptUnicodeString(self, foo):
Packit 130fc8
        unicode_type = (str if is_py3 else unicode)
Packit 130fc8
        assert isinstance(foo, unicode_type), (foo, foo.__class__.__mro__)
Packit 130fc8
        return foo
Packit 130fc8
Packit 130fc8
    kwargs = {}
Packit 130fc8
    if is_py2:
Packit 130fc8
        kwargs['utf8_strings'] = True
Packit 130fc8
    @dbus.service.method(IFACE, in_signature='s', out_signature='s', **kwargs)
Packit 130fc8
    def AcceptUTF8String(self, foo):
Packit 130fc8
        assert isinstance(foo, str), (foo, foo.__class__.__mro__)
Packit 130fc8
        return foo
Packit 130fc8
Packit 130fc8
    @dbus.service.method(IFACE, in_signature='', out_signature='soss',
Packit 130fc8
            sender_keyword='sender', path_keyword='path',
Packit 130fc8
            destination_keyword='dest', message_keyword='msg')
Packit 130fc8
    def MethodExtraInfoKeywords(self, sender=None, path=None, dest=None,
Packit 130fc8
            msg=None):
Packit 130fc8
        return (sender, path, dest,
Packit 130fc8
                msg.__class__.__module__ + '.' + msg.__class__.__name__)
Packit 130fc8
Packit 130fc8
    @dbus.service.method(IFACE, in_signature='ay', out_signature='ay')
Packit 130fc8
    def AcceptListOfByte(self, foo):
Packit 130fc8
        assert isinstance(foo, list), (foo, foo.__class__.__mro__)
Packit 130fc8
        return foo
Packit 130fc8
Packit 130fc8
    @dbus.service.method(IFACE, in_signature='ay', out_signature='ay', 
Packit 130fc8
                         byte_arrays=True)
Packit 130fc8
    def AcceptByteArray(self, foo):
Packit 130fc8
        assert isinstance(foo, bytes), (foo, foo.__class__.__mro__)
Packit 130fc8
        return foo
Packit 130fc8
Packit 130fc8
    @dbus.service.method(IFACE)
Packit 130fc8
    def GetComplexArray(self):
Packit 130fc8
        ret = []
Packit 130fc8
        for i in range(0,100):
Packit 130fc8
            ret.append((random.randint(0,100), random.randint(0,100), str(random.randint(0,100))))
Packit 130fc8
Packit 130fc8
        return dbus.Array(ret, signature="(uus)")
Packit 130fc8
Packit 130fc8
    def returnValue(self, test):
Packit 130fc8
        if test == 0:
Packit 130fc8
            return ""
Packit 130fc8
        elif test == 1:
Packit 130fc8
            return "",""
Packit 130fc8
        elif test == 2:
Packit 130fc8
            return "","",""
Packit 130fc8
        elif test == 3:
Packit 130fc8
            return []
Packit 130fc8
        elif test == 4:
Packit 130fc8
            return {}
Packit 130fc8
        elif test == 5:
Packit 130fc8
            return ["",""]
Packit 130fc8
        elif test == 6:
Packit 130fc8
            return ["","",""]
Packit 130fc8
Packit 130fc8
    @dbus.service.method(IFACE, in_signature='u', out_signature='s')
Packit 130fc8
    def ReturnOneString(self, test):
Packit 130fc8
        return self.returnValue(test)
Packit 130fc8
Packit 130fc8
    @dbus.service.method(IFACE, in_signature='u', out_signature='ss')
Packit 130fc8
    def ReturnTwoStrings(self, test):
Packit 130fc8
        return self.returnValue(test)
Packit 130fc8
Packit 130fc8
    @dbus.service.method(IFACE, in_signature='u', out_signature='(ss)')
Packit 130fc8
    def ReturnStruct(self, test):
Packit 130fc8
        logger.info('ReturnStruct(%r) -> %r', test, self.returnValue(test))
Packit 130fc8
        return self.returnValue(test)
Packit 130fc8
Packit 130fc8
    @dbus.service.method(IFACE, in_signature='u', out_signature='as')
Packit 130fc8
    def ReturnArray(self, test):
Packit 130fc8
        return self.returnValue(test)
Packit 130fc8
Packit 130fc8
    @dbus.service.method(IFACE, in_signature='u', out_signature='a{ss}')
Packit 130fc8
    def ReturnDict(self, test):
Packit 130fc8
        return self.returnValue(test)
Packit 130fc8
Packit 130fc8
    @dbus.service.signal(IFACE, signature='s')
Packit 130fc8
    def SignalOneString(self, test):
Packit 130fc8
        logger.info('SignalOneString(%r)', test)
Packit 130fc8
Packit 130fc8
    @dbus.service.signal(IFACE, signature='ss')
Packit 130fc8
    def SignalTwoStrings(self, test, test2):
Packit 130fc8
        logger.info('SignalTwoStrings(%r, %r)', test, test2)
Packit 130fc8
Packit 130fc8
    @dbus.service.signal(IFACE, signature='(ss)')
Packit 130fc8
    def SignalStruct(self, test):
Packit 130fc8
        logger.info('SignalStruct(%r)', test)
Packit 130fc8
Packit 130fc8
    @dbus.service.signal(IFACE, signature='as')
Packit 130fc8
    def SignalArray(self, test):
Packit 130fc8
        pass
Packit 130fc8
Packit 130fc8
    @dbus.service.signal(IFACE, signature='a{ss}')
Packit 130fc8
    def SignalDict(self, test):
Packit 130fc8
        pass
Packit 130fc8
Packit 130fc8
    @dbus.service.method(IFACE, in_signature='su', out_signature='')
Packit 130fc8
    def EmitSignal(self, signal, value):
Packit 130fc8
        sig = getattr(self, str(signal), None)
Packit 130fc8
        assert(sig != None)
Packit 130fc8
Packit 130fc8
        val = self.returnValue(value)
Packit 130fc8
        # make two string case work by passing arguments in by tuple
Packit 130fc8
        if (signal == 'SignalTwoStrings' and (value == 1 or value == 5)):
Packit 130fc8
            val = tuple(val)
Packit 130fc8
        else:
Packit 130fc8
            val = tuple([val])
Packit 130fc8
Packit 130fc8
        logger.info('Emitting %s with %r', signal, val)
Packit 130fc8
        sig(*val)
Packit 130fc8
Packit 130fc8
    def CheckInheritance(self):
Packit 130fc8
        return True
Packit 130fc8
Packit 130fc8
    @dbus.service.method(IFACE, in_signature='', out_signature='b')
Packit 130fc8
    def TestListExportedChildObjects(self):
Packit 130fc8
        objs_root = session_bus.list_exported_child_objects('/')
Packit 130fc8
        assert objs_root == ['org'], objs_root
Packit 130fc8
        objs_org = session_bus.list_exported_child_objects('/org')
Packit 130fc8
        assert objs_org == ['freedesktop'], objs_org
Packit 130fc8
        return True
Packit 130fc8
Packit 130fc8
    @dbus.service.method(IFACE, in_signature='bbv', out_signature='v', 
Packit 130fc8
                         async_callbacks=('return_cb', 'error_cb'))
Packit 130fc8
    def AsynchronousMethod(self, async, fail, variant, return_cb, error_cb):
Packit 130fc8
        try:
Packit 130fc8
            if async:
Packit 130fc8
                GObject.timeout_add(500, self.AsynchronousMethod, False, fail,
Packit 130fc8
                                    variant, return_cb, error_cb)
Packit 130fc8
                return
Packit 130fc8
            else:
Packit 130fc8
                if fail:
Packit 130fc8
                    raise RuntimeError
Packit 130fc8
                else:
Packit 130fc8
                    return_cb(variant)
Packit 130fc8
Packit 130fc8
                return False # do not run again
Packit 130fc8
        except Exception as e:
Packit 130fc8
            error_cb(e)
Packit 130fc8
Packit 130fc8
    @dbus.service.method(IFACE, in_signature='', out_signature='s', 
Packit 130fc8
                         sender_keyword='sender')
Packit 130fc8
    def WhoAmI(self, sender):
Packit 130fc8
        return sender
Packit 130fc8
Packit 130fc8
    @dbus.service.method(IFACE, in_signature='', out_signature='b')
Packit 130fc8
    def AddRemovableObject(self):
Packit 130fc8
        # Part of test for https://bugs.freedesktop.org/show_bug.cgi?id=10457
Packit 130fc8
        # Keep the removable object reffed, since that's the use case for this
Packit 130fc8
        self._removable.add_to_connection(self._connection,
Packit 130fc8
                                          OBJECT + '/RemovableObject')
Packit 130fc8
        return True
Packit 130fc8
Packit 130fc8
    @dbus.service.method(IFACE, in_signature='', out_signature='b')
Packit 130fc8
    def HasRemovableObject(self):
Packit 130fc8
        # Part of test for https://bugs.freedesktop.org/show_bug.cgi?id=10457
Packit 130fc8
        objs = session_bus.list_exported_child_objects(OBJECT)
Packit 130fc8
        return ('RemovableObject' in objs)
Packit 130fc8
Packit 130fc8
    @dbus.service.method(IFACE)
Packit 130fc8
    def MultipleReturnWithoutSignature(self):
Packit 130fc8
        # https://bugs.freedesktop.org/show_bug.cgi?id=10174
Packit 130fc8
        return dbus.String('abc'), dbus.Int32(123)
Packit 130fc8
Packit 130fc8
    @dbus.service.method(IFACE, in_signature='', out_signature='')
Packit 130fc8
    def BlockFor500ms(self):
Packit 130fc8
        sleep(0.5)
Packit 130fc8
Packit 130fc8
    @dbus.service.method(IFACE, in_signature='', out_signature='',
Packit 130fc8
                         async_callbacks=('return_cb', 'raise_cb'))
Packit 130fc8
    def AsyncWait500ms(self, return_cb, raise_cb):
Packit 130fc8
        def return_from_async_wait():
Packit 130fc8
            return_cb()
Packit 130fc8
            return False
Packit 130fc8
        GObject.timeout_add(500, return_from_async_wait)
Packit 130fc8
Packit 130fc8
    @dbus.service.method(IFACE, in_signature='', out_signature='')
Packit 130fc8
    def RaiseValueError(self):
Packit 130fc8
        raise ValueError('Wrong!')
Packit 130fc8
Packit 130fc8
    @dbus.service.method(IFACE, in_signature='', out_signature='')
Packit 130fc8
    def RaiseDBusExceptionNoTraceback(self):
Packit 130fc8
        class ServerError(dbus.DBusException):
Packit 130fc8
            """Exception representing a normal "environmental" error"""
Packit 130fc8
            include_traceback = False
Packit 130fc8
            _dbus_error_name = 'com.example.Networking.ServerError'
Packit 130fc8
Packit 130fc8
        raise ServerError('Server not responding')
Packit 130fc8
Packit 130fc8
    @dbus.service.method(IFACE, in_signature='', out_signature='')
Packit 130fc8
    def RaiseDBusExceptionWithTraceback(self):
Packit 130fc8
        class RealityFailure(dbus.DBusException):
Packit 130fc8
            """Exception representing a programming error"""
Packit 130fc8
            include_traceback = True
Packit 130fc8
            _dbus_error_name = 'com.example.Misc.RealityFailure'
Packit 130fc8
Packit 130fc8
        raise RealityFailure('Botched invariant')
Packit 130fc8
Packit 130fc8
    @dbus.service.method(IFACE, in_signature='', out_signature='',
Packit 130fc8
                         async_callbacks=('return_cb', 'raise_cb'))
Packit 130fc8
    def AsyncRaise(self, return_cb, raise_cb):
Packit 130fc8
        class Fdo12403Error(dbus.DBusException):
Packit 130fc8
            _dbus_error_name = 'org.freedesktop.bugzilla.bug12403'
Packit 130fc8
Packit 130fc8
        raise_cb(Fdo12403Error())
Packit 130fc8
Packit 130fc8
Packit 130fc8
def main():
Packit 130fc8
    global session_bus
Packit 130fc8
    logger.info('getting session bus')
Packit 130fc8
    session_bus = dbus.SessionBus()
Packit 130fc8
    logger.info('getting bus name %s', NAME)
Packit 130fc8
    global_name = dbus.service.BusName(NAME, bus=session_bus)
Packit 130fc8
    logger.info('making TestObject')
Packit 130fc8
    object = TestObject(global_name)
Packit 130fc8
    logger.info('making TestGObject')
Packit 130fc8
    g_object = TestGObject(global_name)
Packit 130fc8
    logger.info('making Fallback')
Packit 130fc8
    fallback_object = Fallback(session_bus)
Packit 130fc8
    logger.info('creating mainloop')
Packit 130fc8
    loop = GObject.MainLoop()
Packit 130fc8
    logger.info('running')
Packit 130fc8
    loop.run()
Packit 130fc8
    logger.info('done')
Packit 130fc8
Packit 130fc8
Packit 130fc8
if __name__ == '__main__':
Packit 130fc8
    session_bus = None
Packit 130fc8
    try:
Packit 130fc8
        logger.info('entering main')
Packit 130fc8
        main()
Packit 130fc8
    except:
Packit 130fc8
        logger.exception('test-service main failure')
Packit 130fc8
        raise