From 4f55dc1b72f8399382d688ca88d1910ce60dd481 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Thu, 26 Sep 2013 19:20:55 +0100 Subject: [PATCH] Sync constants, servicetest with MC's 'next' version --- tests/twisted/constants.py | 120 +++++++++++++++++++---------- tests/twisted/servicetest.py | 174 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 240 insertions(+), 54 deletions(-) diff --git a/tests/twisted/constants.py b/tests/twisted/constants.py index 3028353..e72c592 100644 --- a/tests/twisted/constants.py +++ b/tests/twisted/constants.py @@ -1,16 +1,40 @@ +# 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 = "im.telepathy1" +PATH_PREFIX = '/' + PREFIX.replace('.', '/') + +tp_name_prefix = PREFIX +tp_path_prefix = PATH_PREFIX CM = PREFIX + ".ConnectionManager" HT_NONE = 0 HT_CONTACT = 1 HT_ROOM = 2 +HT_LIST = 3 +HT_GROUP = 4 CHANNEL = PREFIX + ".Channel" @@ -29,12 +53,10 @@ CHANNEL_IFACE_SUBJECT = CHANNEL + '.Interface.Subject1' CHANNEL_IFACE_FILE_TRANSFER_METADATA = CHANNEL + '.Interface.FileTransfer.Metadata1' CHANNEL_TYPE_CALL = CHANNEL + ".Type.Call1" -CHANNEL_TYPE_CONTACT_LIST = CHANNEL + ".Type.ContactList1" CHANNEL_TYPE_CONTACT_SEARCH = CHANNEL + ".Type.ContactSearch1" -CHANNEL_TYPE_TEXT = CHANNEL + ".Type.Text1" +CHANNEL_TYPE_TEXT = CHANNEL + ".Type.Text" CHANNEL_TYPE_STREAM_TUBE = CHANNEL + ".Type.StreamTube1" CHANNEL_TYPE_DBUS_TUBE = CHANNEL + ".Type.DBusTube1" -CHANNEL_TYPE_TEXT = CHANNEL + ".Type.Text" CHANNEL_TYPE_FILE_TRANSFER = CHANNEL + ".Type.FileTransfer1" CHANNEL_TYPE_ROOM_LIST = CHANNEL + ".Type.RoomList1" CHANNEL_TYPE_SERVER_AUTHENTICATION = \ @@ -59,7 +81,7 @@ CALL_MUTABLE_CONTENTS = CHANNEL_TYPE_CALL + '.MutableContents' CALL_CONTENT = PREFIX + '.Call1.Content' CALL_CONTENT_IFACE_MEDIA = CALL_CONTENT + '.Interface.Media' -CALL_CONTENT_IFACE_DTMF = CALL_CONTENT + '.Interface.DTMF' +CALL_CONTENT_IFACE_DTMF = CALL_CONTENT + '.Interface.DTMF1' CALL_CONTENT_MEDIADESCRIPTION = CALL_CONTENT + '.MediaDescription' @@ -170,10 +192,14 @@ CONN_IFACE_CLIENT_TYPES = CONN + '.Interface.ClientTypes1' CONN_IFACE_POWER_SAVING = CONN + '.Interface.PowerSaving1' CONN_IFACE_CONTACT_BLOCKING = CONN + '.Interface.ContactBlocking1' CONN_IFACE_ADDRESSING = CONN + '.Interface.Addressing1' +CONN_IFACE_SERVICE_POINT = CONN + '.Interface.ServicePoint1' ATTR_CONTACT_ID = CONN + '/contact-id' ATTR_CONTACT_CAPABILITIES = CONN_IFACE_CONTACT_CAPS + '/capabilities' ATTR_PRESENCE = CONN_IFACE_PRESENCE + '/presence' +ATTR_SUBSCRIBE = CONN_IFACE_CONTACT_LIST + '/subscribe' +ATTR_PUBLISH = CONN_IFACE_CONTACT_LIST + '/publish' +ATTR_GROUPS = CONN_IFACE_CONTACT_GROUPS + '/groups' STREAM_HANDLER = PREFIX + '.Media.StreamHandler' @@ -188,6 +214,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' @@ -199,10 +226,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' @@ -248,17 +277,13 @@ SOCKET_ADDRESS_TYPE_IPV6 = 3 SOCKET_ACCESS_CONTROL_LOCALHOST = 0 SOCKET_ACCESS_CONTROL_PORT = 1 -SOCKET_ACCESS_CONTROL_NETMASK = 2 -SOCKET_ACCESS_CONTROL_CREDENTIALS = 3 +SOCKET_ACCESS_CONTROL_CREDENTIALS = 2 TUBE_STATE_LOCAL_PENDING = 0 TUBE_STATE_REMOTE_PENDING = 1 TUBE_STATE_OPEN = 2 TUBE_STATE_NOT_OFFERED = 3 -TUBE_TYPE_DBUS = 0 -TUBE_TYPE_STREAM = 1 - MEDIA_STREAM_DIRECTION_NONE = 0 MEDIA_STREAM_DIRECTION_SEND = 1 MEDIA_STREAM_DIRECTION_RECEIVE = 2 @@ -270,15 +295,6 @@ MEDIA_STREAM_PENDING_REMOTE_SEND = 2 MEDIA_STREAM_TYPE_AUDIO = 0 MEDIA_STREAM_TYPE_VIDEO = 1 -MEDIA_STREAM_STATE_DISCONNECTED = 0 -MEDIA_STREAM_STATE_CONNECTING = 1 -MEDIA_STREAM_STATE_CONNECTED = 2 - -MEDIA_STREAM_DIRECTION_NONE = 0 -MEDIA_STREAM_DIRECTION_SEND = 1 -MEDIA_STREAM_DIRECTION_RECEIVE = 2 -MEDIA_STREAM_DIRECTION_BIDIRECTIONAL = 3 - FT_STATE_NONE = 0 FT_STATE_PENDING = 1 FT_STATE_ACCEPTED = 2 @@ -325,8 +341,7 @@ GF_MESSAGE_RESCIND = 128 GF_CHANNEL_SPECIFIC_HANDLES = 256 GF_ONLY_ONE_GROUP = 512 GF_HANDLE_OWNERS_NOT_AVAILABLE = 1024 -GF_PROPERTIES = 2048 -GF_MEMBERS_CHANGED_DETAILED = 4096 +GF_MESSAGE_DEPART = 2048 GC_REASON_NONE = 0 GC_REASON_OFFLINE = 1 @@ -388,6 +403,7 @@ MEDIA_CAP_IMMUTABLE_STREAMS = 32 CLIENT = PREFIX + '.Client' +PRESENCE_UNSET = 0 PRESENCE_OFFLINE = 1 PRESENCE_AVAILABLE = 2 PRESENCE_AWAY = 3 @@ -442,12 +458,6 @@ MT_NOTICE = 2 MT_AUTO_REPLY = 3 MT_DELIVERY_REPORT = 4 -class MessageFlag(object): - TRUNCATED = 1 - NON_TEXT_CONTENT = 2 - SCROLLBACK = 4 - RESCUED = 8 - class SendError(object): UNKNOWN = 0 OFFLINE = 1 @@ -500,15 +510,7 @@ DELIVERY_STATUS_ACCEPTED = 4 DELIVERY_STATUS_READ = 5 DELIVERY_STATUS_DELETED = 6 -MEDIA_STREAM_ERROR_UNKNOWN = 0 -MEDIA_STREAM_ERROR_EOS = 1 -MEDIA_STREAM_ERROR_CODEC_NEGOTIATION_FAILED = 2 -MEDIA_STREAM_ERROR_CONNECTION_FAILED = 3 -MEDIA_STREAM_ERROR_NETWORK_ERROR = 4 -MEDIA_STREAM_ERROR_NO_CODECS = 5 -MEDIA_STREAM_ERROR_INVALID_CM_BEHAVIOR = 6 -MEDIA_STREAM_ERROR_MEDIA_ERROR = 7 - +PASSWORD_FLAG_HINT = 4 PASSWORD_FLAG_PROVIDE = 8 # Channel.Interface.Room @@ -521,4 +523,46 @@ 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.Avatar1' +ACCOUNT_IFACE_ADDRESSING = ACCOUNT + '.Interface.Addressing1' +ACCOUNT_IFACE_HIDDEN = ACCOUNT + '.Interface.Hidden1' +ACCOUNT_IFACE_NOKIA_CONDITIONS = 'com.nokia.Account.Interface.Conditions' +ACCOUNT_PATH_PREFIX = PATH_PREFIX + '/Account/' + +AM = PREFIX + '.AccountManager' +AM_IFACE_HIDDEN = AM + '.Interface.Hidden1' +AM_PATH = PATH_PREFIX + '/AccountManager' + +CR = PREFIX + '.ChannelRequest' +CDO = PREFIX + '.ChannelDispatchOperation' + +CD = PREFIX + '.ChannelDispatcher' +CD_IFACE_OP_LIST = PREFIX + '.ChannelDispatcher.Interface.OperationList1' +CD_PATH = PATH_PREFIX + '/ChannelDispatcher' + +MC = PREFIX + '.MissionControl6' +MC_PATH = PATH_PREFIX + '/MissionControl6' + +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" diff --git a/tests/twisted/servicetest.py b/tests/twisted/servicetest.py index 0960be4..8a813f5 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 @@ -14,6 +31,7 @@ import pprint import unittest import dbus +import dbus.lowlevel from dbus.mainloop.glib import DBusGMainLoop DBusGMainLoop(set_as_default=True) @@ -22,7 +40,7 @@ from twisted.internet import reactor import constants as cs tp_name_prefix = cs.PREFIX -tp_path_prefix = '/' + cs.PREFIX.replace('.', '/') +tp_path_prefix = cs.PATH_PREFIX class DictionarySupersetOf (object): """Utility class for expecting "a dictionary with at least these keys".""" @@ -291,6 +309,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] @@ -315,6 +338,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) @@ -425,17 +569,13 @@ 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): +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 Gabble, which means that Ping()ing Gabble doesn't - # ensure that it's processed all D-Bus messages prior to our ping. - # - # 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, '/', introspect=False) - call_async(q, - dbus.Interface(root_object, cs.PREFIX + '.Tests'), + # 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') @@ -478,14 +618,16 @@ class ConnWrapper(ProxyWrapper): def wrap_connection(conn): return ConnWrapper(conn, tp_name_prefix + '.Connection', - dict([ - (name, tp_name_prefix + '.Connection.Interface.' + name) - for name in ['Aliasing', 'Avatars', 'Capabilities', 'Contacts', - 'SimplePresence', 'Requests']] + + dict( [('Peer', 'org.freedesktop.DBus.Peer'), + ('Aliasing', cs.CONN_IFACE_ALIASING), + ('Avatars', cs.CONN_IFACE_AVATARS), + ('Contacts', cs.CONN_IFACE_CONTACTS), ('ContactCapabilities', cs.CONN_IFACE_CONTACT_CAPS), ('ContactInfo', cs.CONN_IFACE_CONTACT_INFO), ('Location', cs.CONN_IFACE_LOCATION), + ('Presence', cs.CONN_IFACE_PRESENCE), + ('Requests', cs.CONN_IFACE_REQUESTS), ('Future', tp_name_prefix + '.Connection.FUTURE'), ('MailNotification', cs.CONN_IFACE_MAIL_NOTIFICATION), ('ContactList', cs.CONN_IFACE_CONTACT_LIST), @@ -497,7 +639,7 @@ def wrap_connection(conn): def wrap_channel(chan, type_, extra=None): interfaces = { type_: tp_name_prefix + '.Channel.Type.' + type_, - 'Group': tp_name_prefix + '.Channel.Interface.Group', + 'Group': cs.CHANNEL_IFACE_GROUP, } if extra: -- 1.8.4.rc3