summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2014-02-07 13:05:28 +0000
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2014-02-07 14:15:52 +0000
commitc349b4aa5c4cd7f5c36b0952b8b6caef799379b8 (patch)
tree0bb903299a7bff45a0ae87e630fb97ec27e3d74c
parent47e3dde5eae51b83a379f97aa93cafcf1179870d (diff)
constants, servicetest: sync from Gabble
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=70382 Reviewed-by: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk>
-rw-r--r--tests/twisted/constants.py111
-rw-r--r--tests/twisted/servicetest.py276
2 files changed, 357 insertions, 30 deletions
diff --git a/tests/twisted/constants.py b/tests/twisted/constants.py
index 8c601678..e21bc134 100644
--- a/tests/twisted/constants.py
+++ b/tests/twisted/constants.py
@@ -1,10 +1,32 @@
+# Copyright (C) 2009 Nokia Corporation
+# Copyright (C) 2009-2013 Collabora Ltd.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
"""
Some handy constants for other tests to share and enjoy.
"""
-from dbus import PROPERTIES_IFACE
+from dbus import PROPERTIES_IFACE, INTROSPECTABLE_IFACE
PREFIX = "org.freedesktop.Telepathy"
+PATH_PREFIX = '/' + PREFIX.replace('.', '/')
+
+tp_name_prefix = PREFIX
+tp_path_prefix = PATH_PREFIX
CM = PREFIX + ".ConnectionManager"
@@ -32,6 +54,7 @@ CHANNEL_IFACE_ROOM = CHANNEL + '.Interface.Room2'
CHANNEL_IFACE_ROOM_CONFIG = CHANNEL + '.Interface.RoomConfig1'
CHANNEL_IFACE_SUBJECT = CHANNEL + '.Interface.Subject2'
CHANNEL_IFACE_FILE_TRANSFER_METADATA = CHANNEL + '.Interface.FileTransfer.Metadata'
+CHANNEL_IFACE_SMS = CHANNEL + '.Interface.SMS'
CHANNEL_TYPE_CALL = CHANNEL + ".Type.Call1"
CHANNEL_TYPE_CONTACT_LIST = CHANNEL + ".Type.ContactList"
@@ -62,6 +85,15 @@ INITIATOR_HANDLE = CHANNEL + '.InitiatorHandle'
INITIATOR_ID = CHANNEL + '.InitiatorID'
INTERFACES = CHANNEL + '.Interfaces'
+CALL_CONTENTS = CHANNEL_TYPE_CALL + '.Contents'
+CALL_CALL_STATE_DETAILS = CHANNEL_TYPE_CALL + '.CallStateDetails'
+CALL_CALL_STATE = CHANNEL_TYPE_CALL + '.CallState'
+CALL_CALL_FLAGS = CHANNEL_TYPE_CALL + '.CallFlags'
+CALL_CALL_STATE_REASON = CHANNEL_TYPE_CALL + '.CallStateReason'
+CALL_HARDWARE_STREAMING = CHANNEL_TYPE_CALL + '.HardwareStreaming'
+CALL_CALL_MEMBERS = CHANNEL_TYPE_CALL + '.CallMembers'
+CALL_MEMBER_IDENTIFIERS = CHANNEL_TYPE_CALL + '.MemberIdentifiers'
+CALL_INITIAL_TRANSPORT = CHANNEL_TYPE_CALL + '.InitialTransport'
CALL_INITIAL_AUDIO = CHANNEL_TYPE_CALL + '.InitialAudio'
CALL_INITIAL_AUDIO_NAME = CHANNEL_TYPE_CALL + '.InitialAudioName'
CALL_INITIAL_VIDEO = CHANNEL_TYPE_CALL + '.InitialVideo'
@@ -72,7 +104,7 @@ CALL_CONTENT = PREFIX + '.Call1.Content'
CALL_CONTENT_IFACE_MEDIA = CALL_CONTENT + '.Interface.Media'
CALL_CONTENT_IFACE_DTMF = CALL_CONTENT + '.Interface.DTMF'
-CALL_CONTENT_MEDIADESCRIPTION = CALL_CONTENT + '.MediaDescription'
+CALL_CONTENT_MEDIA_DESCRIPTION = CALL_CONTENT + '.MediaDescription'
CALL_STREAM = PREFIX + '.Call1.Stream'
CALL_STREAM_IFACE_MEDIA = CALL_STREAM + '.Interface.Media'
@@ -172,6 +204,8 @@ CONN_IFACE_CONTACTS = CONN + '.Interface.Contacts'
CONN_IFACE_CONTACT_CAPS = CONN + '.Interface.ContactCapabilities'
CONN_IFACE_CONTACT_INFO = CONN + ".Interface.ContactInfo"
CONN_IFACE_PRESENCE = CONN + '.Interface.Presence'
+CONN_IFACE_RENAMING = CONN + '.Interface.Renaming'
+CONN_IFACE_SIDECARS1 = CONN + '.Interface.Sidecars1'
CONN_IFACE_SIMPLE_PRESENCE = CONN + '.Interface.SimplePresence'
CONN_IFACE_REQUESTS = CONN + '.Interface.Requests'
CONN_IFACE_LOCATION = CONN + '.Interface.Location'
@@ -183,10 +217,19 @@ CONN_IFACE_CLIENT_TYPES = CONN + '.Interface.ClientTypes'
CONN_IFACE_POWER_SAVING = CONN + '.Interface.PowerSaving'
CONN_IFACE_CONTACT_BLOCKING = CONN + '.Interface.ContactBlocking'
CONN_IFACE_ADDRESSING = CONN + '.Interface.Addressing1'
+CONN_IFACE_SERVICE_POINT = CONN + '.Interface.ServicePoint'
-ATTR_CONTACT_ID = CONN + '/contact-id'
+ATTR_ALIAS = CONN_IFACE_ALIASING + '/alias'
+ATTR_AVATAR_TOKEN = CONN_IFACE_AVATARS + '/token'
+ATTR_CLIENT_TYPES = CONN_IFACE_CLIENT_TYPES + '/client-types'
ATTR_CONTACT_CAPABILITIES = CONN_IFACE_CONTACT_CAPS + '/capabilities'
+ATTR_CONTACT_ID = CONN + '/contact-id'
+ATTR_CONTACT_INFO = CONN_IFACE_CONTACT_INFO + '/info'
+ATTR_GROUPS = CONN_IFACE_CONTACT_GROUPS + '/groups'
+ATTR_LOCATION = CONN_IFACE_LOCATION + '/location'
ATTR_PRESENCE = CONN_IFACE_SIMPLE_PRESENCE + '/presence'
+ATTR_PUBLISH = CONN_IFACE_CONTACT_LIST + '/publish'
+ATTR_SUBSCRIBE = CONN_IFACE_CONTACT_LIST + '/subscribe'
STREAM_HANDLER = PREFIX + '.Media.StreamHandler'
@@ -201,6 +244,7 @@ CONNECTION_REFUSED = ERROR + '.ConnectionRefused'
CONNECTION_FAILED = ERROR + '.ConnectionFailed'
CONNECTION_LOST = ERROR + '.ConnectionLost'
CANCELLED = ERROR + '.Cancelled'
+NOT_YOURS = ERROR + '.NotYours'
DISCONNECTED = ERROR + '.Disconnected'
REGISTRATION_EXISTS = ERROR + '.RegistrationExists'
AUTHENTICATION_FAILED = ERROR + '.AuthenticationFailed'
@@ -212,10 +256,12 @@ INVALID_HANDLE = ERROR + '.InvalidHandle'
CERT_UNTRUSTED = ERROR + '.Cert.Untrusted'
SERVICE_BUSY = ERROR + '.ServiceBusy'
SERVICE_CONFUSED = ERROR + '.ServiceConfused'
+SOFTWARE_UPGRADE_REQUIRED = ERROR + '.SoftwareUpgradeRequired'
BANNED = ERROR + '.Channel.Banned'
-UNKNOWN_METHOD = 'org.freedesktop.DBus.Error.UnknownMethod'
+DBUS_ERROR_UNKNOWN_METHOD = 'org.freedesktop.DBus.Error.UnknownMethod'
+DBUS_ERROR_NO_REPLY = 'org.freedesktop.DBus.Error.NoReply'
TUBE_PARAMETERS = CHANNEL_IFACE_TUBE + '.Parameters'
TUBE_STATE = CHANNEL_IFACE_TUBE + '.State'
@@ -322,7 +368,7 @@ FT_DATE = CHANNEL_TYPE_FILE_TRANSFER + '.Date'
FT_AVAILABLE_SOCKET_TYPES = CHANNEL_TYPE_FILE_TRANSFER + '.AvailableSocketTypes'
FT_TRANSFERRED_BYTES = CHANNEL_TYPE_FILE_TRANSFER + '.TransferredBytes'
FT_INITIAL_OFFSET = CHANNEL_TYPE_FILE_TRANSFER + '.InitialOffset'
-FT_FILE_COLLECTION = CHANNEL_TYPE_FILE_TRANSFER + '.FUTURE.FileCollection'
+FT_FILE_COLLECTION = CHANNEL_TYPE_FILE_TRANSFER + '.FileCollection'
FT_URI = CHANNEL_TYPE_FILE_TRANSFER + '.URI'
FT_SERVICE_NAME = CHANNEL_IFACE_FILE_TRANSFER_METADATA + '.ServiceName'
FT_METADATA = CHANNEL_IFACE_FILE_TRANSFER_METADATA + '.Metadata'
@@ -401,6 +447,7 @@ MEDIA_CAP_IMMUTABLE_STREAMS = 32
CLIENT = PREFIX + '.Client'
+PRESENCE_UNSET = 0
PRESENCE_OFFLINE = 1
PRESENCE_AVAILABLE = 2
PRESENCE_AWAY = 3
@@ -534,4 +581,56 @@ SUBJECT_PRESENT = 1
SUBJECT_CAN_SET = 2
DEBUG_IFACE = PREFIX + '.Debug'
-DEBUG_PATH = '/' + PREFIX.replace('.', '/') + '/debug'
+DEBUG_PATH = PATH_PREFIX + '/debug'
+
+SERVICE_POINT_TYPE_NONE = 0
+SERVICE_POINT_TYPE_EMERGENCY = 1
+SERVICE_POINT_TYPE_COUNSELING = 2
+
+CLIENT = PREFIX + '.Client'
+CLIENT_PATH = PATH_PREFIX + '/Client'
+OBSERVER = PREFIX + '.Client.Observer'
+APPROVER = PREFIX + '.Client.Approver'
+HANDLER = PREFIX + '.Client.Handler'
+CLIENT_IFACE_REQUESTS = CLIENT + '.Interface.Requests'
+
+ACCOUNT = PREFIX + '.Account'
+ACCOUNT_IFACE_AVATAR = ACCOUNT + '.Interface.Avatar'
+ACCOUNT_IFACE_ADDRESSING = ACCOUNT + '.Interface.Addressing'
+ACCOUNT_IFACE_HIDDEN = ACCOUNT + '.Interface.Hidden.DRAFT1'
+ACCOUNT_IFACE_NOKIA_CONDITIONS = 'com.nokia.Account.Interface.Conditions'
+ACCOUNT_PATH_PREFIX = PATH_PREFIX + '/Account/'
+
+AM = PREFIX + '.AccountManager'
+AM_IFACE_HIDDEN = AM + '.Interface.Hidden.DRAFT1'
+AM_PATH = PATH_PREFIX + '/AccountManager'
+
+CR = PREFIX + '.ChannelRequest'
+CDO = PREFIX + '.ChannelDispatchOperation'
+
+CD = PREFIX + '.ChannelDispatcher'
+CD_IFACE_MESSAGES1 = PREFIX + '.ChannelDispatcher.Interface.Messages1'
+CD_IFACE_OP_LIST = PREFIX + '.ChannelDispatcher.Interface.OperationList'
+CD_PATH = PATH_PREFIX + '/ChannelDispatcher'
+CD_REDISPATCH = CD + '.Interface.Redispatch.DRAFT'
+
+MC = PREFIX + '.MissionControl5'
+MC_PATH = PATH_PREFIX + '/MissionControl5'
+
+DTMF_CURRENTLY_SENDING_TONES = CHANNEL_IFACE_DTMF + '.CurrentlySendingTones'
+DTMF_INITIAL_TONES = CHANNEL_IFACE_DTMF + '.InitialTones'
+DTMF_DEFERRED_TONES = CHANNEL_IFACE_DTMF + '.DeferredTones'
+
+TESTDOT = PREFIX + ".Test."
+TESTSLASH = PATH_PREFIX + "/Test/"
+
+TEST_DBUS_ACCOUNT_SERVICE = TESTDOT + "DBusAccountService"
+TEST_DBUS_ACCOUNT_SERVICE_PATH = TESTSLASH + "DBusAccountService"
+TEST_DBUS_ACCOUNT_SERVICE_IFACE = TEST_DBUS_ACCOUNT_SERVICE
+
+TEST_DBUS_ACCOUNT_PLUGIN_PATH = TESTSLASH + "DBusAccountPlugin"
+TEST_DBUS_ACCOUNT_PLUGIN_IFACE = TESTDOT + "DBusAccountPlugin"
+
+# Channel.Interface.SMS
+SMS_FLASH = CHANNEL_IFACE_SMS + '.Flash'
+SMS_CHANNEL = CHANNEL_IFACE_SMS + '.SMSChannel'
diff --git a/tests/twisted/servicetest.py b/tests/twisted/servicetest.py
index bca3b13b..5ff61a46 100644
--- a/tests/twisted/servicetest.py
+++ b/tests/twisted/servicetest.py
@@ -1,6 +1,23 @@
+# Copyright (C) 2009 Nokia Corporation
+# Copyright (C) 2009-2013 Collabora Ltd.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
"""
-Infrastructure code for testing connection managers.
+Infrastructure code for testing Telepathy services.
"""
from twisted.internet import glib2reactor
@@ -8,18 +25,22 @@ from twisted.internet.protocol import Protocol, Factory, ClientFactory
glib2reactor.install()
import sys
import time
+import os
import pprint
import unittest
-import dbus.glib
+import dbus
+import dbus.lowlevel
+from dbus.mainloop.glib import DBusGMainLoop
+DBusGMainLoop(set_as_default=True)
from twisted.internet import reactor
import constants as cs
-tp_name_prefix = 'org.freedesktop.Telepathy'
-tp_path_prefix = '/org/freedesktop/Telepathy'
+tp_name_prefix = cs.PREFIX
+tp_path_prefix = cs.PATH_PREFIX
class DictionarySupersetOf (object):
"""Utility class for expecting "a dictionary with at least these keys"."""
@@ -40,16 +61,19 @@ class DictionarySupersetOf (object):
except TypeError: # other is not iterable
return False
-class Event:
+class Event(object):
def __init__(self, type, **kw):
self.__dict__.update(kw)
self.type = type
(self.subqueue, self.subtype) = type.split ("-", 1)
+ def __str__(self):
+ return '\n'.join([ str(type(self)) ] + format_event(self))
+
def format_event(event):
ret = ['- type %s' % event.type]
- for key in dir(event):
+ for key in sorted(dir(event)):
if key != 'type' and not key.startswith('_'):
ret.append('- %s: %s' % (
key, pprint.pformat(getattr(event, key))))
@@ -151,6 +175,12 @@ class BaseEventQueue:
"""
self.forbidden_events.difference_update(set(patterns))
+ def unforbid_all(self):
+ """
+ Remove all patterns from the set of forbidden events.
+ """
+ self.forbidden_events.clear()
+
def _check_forbidden(self, event):
for e in self.forbidden_events:
if e.match(event):
@@ -167,7 +197,14 @@ class BaseEventQueue:
t = time.time()
while True:
- event = self.wait([pattern.subqueue])
+ try:
+ event = self.wait([pattern.subqueue])
+ except TimeoutError:
+ self.log('timeout')
+ self.log('still expecting:')
+ self.log(' - %r' % pattern)
+ raise
+
self._check_forbidden(event)
if pattern.match(event):
@@ -279,6 +316,11 @@ class IteratingEventQueue(BaseEventQueue):
def __init__(self, timeout=None):
BaseEventQueue.__init__(self, timeout)
+ self._dbus_method_impls = []
+ self._buses = []
+ # a message filter which will claim we handled everything
+ self._dbus_dev_null = \
+ lambda bus, message: dbus.lowlevel.HANDLER_RESULT_HANDLED
def wait(self, queues=None):
stop = [False]
@@ -303,6 +345,127 @@ class IteratingEventQueue(BaseEventQueue):
else:
raise TimeoutError
+ def add_dbus_method_impl(self, cb, bus=None, **kwargs):
+ if bus is None:
+ bus = self._buses[0]
+
+ self._dbus_method_impls.append(
+ (EventPattern('dbus-method-call', **kwargs), cb))
+
+ def dbus_emit(self, path, iface, name, *a, **k):
+ bus = k.pop('bus', self._buses[0])
+ assert 'signature' in k, k
+ message = dbus.lowlevel.SignalMessage(path, iface, name)
+ message.append(*a, **k)
+ bus.send_message(message)
+
+ def dbus_return(self, in_reply_to, *a, **k):
+ bus = k.pop('bus', self._buses[0])
+ assert 'signature' in k, k
+ reply = dbus.lowlevel.MethodReturnMessage(in_reply_to)
+ reply.append(*a, **k)
+ bus.send_message(reply)
+
+ def dbus_raise(self, in_reply_to, name, message=None, bus=None):
+ if bus is None:
+ bus = self._buses[0]
+
+ reply = dbus.lowlevel.ErrorMessage(in_reply_to, name, message)
+ bus.send_message(reply)
+
+ def attach_to_bus(self, bus):
+ if not self._buses:
+ # first-time setup
+ self._dbus_filter_bound_method = self._dbus_filter
+
+ self._buses.append(bus)
+
+ # Only subscribe to messages on the first bus connection (assumed to
+ # be the shared session bus connection used by the simulated connection
+ # manager and most of the test suite), not on subsequent bus
+ # connections (assumed to represent extra clients).
+ #
+ # When we receive a method call on the other bus connections, ignore
+ # it - the eavesdropping filter installed on the first bus connection
+ # will see it too.
+ #
+ # This is highly counter-intuitive, but it means our messages are in
+ # a guaranteed order (we don't have races between messages arriving on
+ # various connections).
+ if len(self._buses) > 1:
+ bus.add_message_filter(self._dbus_dev_null)
+ return
+
+ try:
+ # for dbus > 1.5
+ bus.add_match_string("eavesdrop=true,type='signal'")
+ except dbus.DBusException:
+ bus.add_match_string("type='signal'")
+ bus.add_match_string("type='method_call'")
+ else:
+ bus.add_match_string("eavesdrop=true,type='method_call'")
+
+ bus.add_message_filter(self._dbus_filter_bound_method)
+
+ bus.add_signal_receiver(
+ lambda *args, **kw:
+ self.append(
+ Event('dbus-signal',
+ path=unwrap(kw['path']),
+ signal=kw['member'],
+ args=map(unwrap, args),
+ interface=kw['interface'])),
+ None,
+ None,
+ None,
+ path_keyword='path',
+ member_keyword='member',
+ interface_keyword='interface',
+ byte_arrays=True,
+ )
+
+ def cleanup(self):
+ if self._buses:
+ self._buses[0].remove_message_filter(self._dbus_filter_bound_method)
+ for bus in self._buses[1:]:
+ bus.remove_message_filter(self._dbus_dev_null)
+
+ self._buses = []
+ self._dbus_method_impls = []
+
+ def _dbus_filter(self, bus, message):
+ if isinstance(message, dbus.lowlevel.MethodCallMessage):
+
+ destination = message.get_destination()
+ sender = message.get_sender()
+
+ if (destination == 'org.freedesktop.DBus' or
+ sender == self._buses[0].get_unique_name()):
+ # suppress reply and don't make an Event
+ return dbus.lowlevel.HANDLER_RESULT_HANDLED
+
+ e = Event('dbus-method-call', message=message,
+ interface=message.get_interface(), path=message.get_path(),
+ raw_args=message.get_args_list(byte_arrays=True),
+ args=map(unwrap, message.get_args_list(byte_arrays=True)),
+ destination=str(destination),
+ method=message.get_member(),
+ sender=message.get_sender(),
+ handled=False)
+
+ for pair in self._dbus_method_impls:
+ pattern, cb = pair
+ if pattern.match(e):
+ cb(e)
+ e.handled = True
+ break
+
+ self.append(e)
+
+ return dbus.lowlevel.HANDLER_RESULT_HANDLED
+
+ return dbus.lowlevel.HANDLER_RESULT_NOT_YET_HANDLED
+
class TestEventQueue(BaseEventQueue):
def __init__(self, events):
BaseEventQueue.__init__(self)
@@ -413,20 +576,23 @@ def call_async(test, proxy, method, *args, **kw):
kw.update({'reply_handler': reply_func, 'error_handler': error_func})
method_proxy(*args, **kw)
-def sync_dbus(bus, q, conn):
- # Dummy D-Bus method call
- # This won't do the right thing unless the proxy has a unique name.
- assert conn.object.bus_name.startswith(':')
- root_object = bus.get_object(conn.object.bus_name, '/')
- call_async(
- q, dbus.Interface(root_object, 'org.freedesktop.Telepathy.Tests'), 'DummySyncDBus')
+def sync_dbus(bus, q, proxy):
+ # Dummy D-Bus method call. We can't use DBus.Peer.Ping() because libdbus
+ # replies to that message immediately, rather than handing it up to
+ # dbus-glib and thence the application, which means that Ping()ing the
+ # application doesn't ensure that it's processed all D-Bus messages prior
+ # to our ping.
+ call_async(q, dbus.Interface(proxy, 'org.freedesktop.Telepathy.Tests'),
+ 'DummySyncDBus')
q.expect('dbus-error', method='DummySyncDBus')
class ProxyWrapper:
- def __init__(self, object, default, others):
+ def __init__(self, object, default, others={}):
self.object = object
self.default_interface = dbus.Interface(object, default)
self.Properties = dbus.Interface(object, dbus.PROPERTIES_IFACE)
+ self.TpProperties = \
+ dbus.Interface(object, tp_name_prefix + '.Properties')
self.interfaces = dict([
(name, dbus.Interface(object, iface))
for name, iface in others.iteritems()])
@@ -440,27 +606,64 @@ class ProxyWrapper:
return getattr(self.default_interface, name)
+class ConnWrapper(ProxyWrapper):
+ def inspect_contact_sync(self, handle):
+ return self.inspect_contacts_sync([handle])[0]
+
+ def inspect_contacts_sync(self, handles):
+ h2asv = self.Contacts.GetContactAttributes(handles, [], True)
+ ret = []
+ for h in handles:
+ ret.append(h2asv[h][cs.ATTR_CONTACT_ID])
+ return ret
+
+ def get_contact_handle_sync(self, identifier):
+ return self.Contacts.GetContactByID(identifier, [])[0]
+
+ def get_contact_handles_sync(self, ids):
+ return [self.get_contact_handle_sync(i) for i in ids]
+
def wrap_connection(conn):
- return ProxyWrapper(conn, tp_name_prefix + '.Connection',
+ return ConnWrapper(conn, tp_name_prefix + '.Connection',
dict([
(name, tp_name_prefix + '.Connection.Interface.' + name)
for name in ['Aliasing', 'Avatars', 'Capabilities', 'Contacts',
- 'Presence', 'SimplePresence', 'Requests']] +
+ 'SimplePresence', 'Requests']] +
[('Peer', 'org.freedesktop.DBus.Peer'),
('ContactCapabilities', cs.CONN_IFACE_CONTACT_CAPS),
('ContactInfo', cs.CONN_IFACE_CONTACT_INFO),
('Location', cs.CONN_IFACE_LOCATION),
- ('Future', tp_name_prefix + '.Connection.FUTURE'),
('MailNotification', cs.CONN_IFACE_MAIL_NOTIFICATION),
('ContactList', cs.CONN_IFACE_CONTACT_LIST),
('ContactGroups', cs.CONN_IFACE_CONTACT_GROUPS),
+ ('ContactBlocking', cs.CONN_IFACE_CONTACT_BLOCKING),
('PowerSaving', cs.CONN_IFACE_POWER_SAVING),
+ ('Addressing', cs.CONN_IFACE_ADDRESSING),
+ ('ClientTypes', cs.CONN_IFACE_CLIENT_TYPES),
+ ('Renaming', cs.CONN_IFACE_RENAMING),
+ ('Sidecars1', cs.CONN_IFACE_SIDECARS1),
]))
+class ChannelWrapper(ProxyWrapper):
+ def send_msg_sync(self, txt):
+ message = [
+ { 'message-type': cs.MT_NORMAL, },
+ { 'content-type': 'text/plain',
+ 'content': txt
+ }]
+ self.Messages.SendMessage(message, 0)
+
def wrap_channel(chan, type_, extra=None):
interfaces = {
type_: tp_name_prefix + '.Channel.Type.' + type_,
- 'Group': tp_name_prefix + '.Channel.Interface.Group',
+ 'Channel': cs.CHANNEL,
+ 'Group': cs.CHANNEL_IFACE_GROUP,
+ 'Hold': cs.CHANNEL_IFACE_HOLD,
+ 'Messages': cs.CHANNEL_IFACE_MESSAGES,
+ 'RoomConfig1': cs.CHANNEL_IFACE_ROOM_CONFIG,
+ 'ChatState': cs.CHANNEL_IFACE_CHAT_STATE,
+ 'Destroyable': cs.CHANNEL_IFACE_DESTROYABLE,
+ 'Password': cs.CHANNEL_IFACE_PASSWORD,
}
if extra:
@@ -468,16 +671,31 @@ def wrap_channel(chan, type_, extra=None):
(name, tp_name_prefix + '.Channel.Interface.' + name)
for name in extra]))
- return ProxyWrapper(chan, tp_name_prefix + '.Channel', interfaces)
+ return ChannelWrapper(chan, tp_name_prefix + '.Channel', interfaces)
+
+
+def wrap_content(chan, extra=None):
+ interfaces = {
+ 'DTMF': cs.CALL_CONTENT_IFACE_DTMF,
+ 'Media': cs.CALL_CONTENT_IFACE_MEDIA,
+ }
+
+ if extra:
+ interfaces.update(dict([
+ (name, tp_name_prefix + '.Call1.Content.Interface.' + name)
+ for name in extra]))
+
+ return ProxyWrapper(chan, tp_name_prefix + '.Call1.Content', interfaces)
def make_connection(bus, event_func, name, proto, params):
cm = bus.get_object(
tp_name_prefix + '.ConnectionManager.%s' % name,
- tp_path_prefix + '/ConnectionManager/%s' % name)
+ tp_path_prefix + '/ConnectionManager/%s' % name,
+ introspect=False)
cm_iface = dbus.Interface(cm, tp_name_prefix + '.ConnectionManager')
connection_name, connection_path = cm_iface.RequestConnection(
- proto, params)
+ proto, dbus.Dictionary(params, signature='sv'))
conn = wrap_connection(bus.get_object(connection_name, connection_path))
return conn
@@ -624,6 +842,16 @@ def install_colourer():
sys.stdout = Colourer(sys.stdout, patterns)
return sys.stdout
-if __name__ == '__main__':
- unittest.main()
+# this is just to shut up unittest.
+class DummyStream(object):
+ def write(self, s):
+ if 'CHECK_TWISTED_VERBOSE' in os.environ:
+ print s,
+ def flush(self):
+ pass
+
+if __name__ == '__main__':
+ stream = DummyStream()
+ runner = unittest.TextTestRunner(stream=stream)
+ unittest.main(testRunner=runner)