From 5f8f093b7290f16bf5577a523ab5adfda1e526b1 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Mon, 30 Sep 2013 18:08:29 +0100 Subject: [PATCH 09/11] Implement Contacts properly on SimulatedConnection, and fix tests --- tests/twisted/account-manager/avatar-persist.py | 8 +-- tests/twisted/account-manager/avatar-refresh.py | 6 +- tests/twisted/account-manager/irc.py | 28 ++++++-- tests/twisted/account-manager/nickname.py | 6 +- tests/twisted/constants.py | 2 + tests/twisted/mctest.py | 92 +++++++++++++++++++++---- 6 files changed, 108 insertions(+), 34 deletions(-) diff --git a/tests/twisted/account-manager/avatar-persist.py b/tests/twisted/account-manager/avatar-persist.py index 195c80a..f7560e7 100644 --- a/tests/twisted/account-manager/avatar-persist.py +++ b/tests/twisted/account-manager/avatar-persist.py @@ -110,12 +110,8 @@ def test(q, bus, unused, **kwargs): # We haven't changed the avatar since we last signed in, so we don't set # it - on the contrary, we pick up the remote avatar (which has changed - # since we were last here) to store it in the Account - _, request_avatars_call, e = q.expect_many( - EventPattern('dbus-method-call', - interface=cs.CONN_IFACE_AVATARS, method='GetKnownAvatarTokens', - args=[[conn.self_handle]], - handled=True), + # since we were last here) to store it in the Account. + request_avatars_call, e = q.expect_many( EventPattern('dbus-method-call', interface=cs.CONN_IFACE_AVATARS, method='RequestAvatars', args=[[conn.self_handle]], diff --git a/tests/twisted/account-manager/avatar-refresh.py b/tests/twisted/account-manager/avatar-refresh.py index e044eb0..0c46636 100644 --- a/tests/twisted/account-manager/avatar-refresh.py +++ b/tests/twisted/account-manager/avatar-refresh.py @@ -102,11 +102,7 @@ def test(q, bus, unused, **kwargs): conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED) - _, _, e = q.expect_many( - EventPattern('dbus-method-call', - interface=cs.CONN_IFACE_AVATARS, method='GetKnownAvatarTokens', - args=[[conn.self_handle]], - handled=True), + _, e = q.expect_many( EventPattern('dbus-method-call', interface=cs.CONN_IFACE_AVATARS, method='SetAvatar', args=['Deus Ex', 'image/jpeg'], diff --git a/tests/twisted/account-manager/irc.py b/tests/twisted/account-manager/irc.py index 4c28e97..47612bd 100644 --- a/tests/twisted/account-manager/irc.py +++ b/tests/twisted/account-manager/irc.py @@ -51,7 +51,11 @@ def test(q, bus, mc): expect_after_connect = [ EventPattern('dbus-method-call', - interface=cs.CONN_IFACE_ALIASING, method='GetAliases', + interface=cs.CONN_IFACE_CONTACTS, + predicate=(lambda e: e.method in ( + 'GetContactAttributes', 'GetContactByID' + ) and + cs.CONN_IFACE_ALIASING in e.args[1]), handled=True), EventPattern('dbus-method-call', interface=cs.CONN_IFACE_ALIASING, method='SetAliases', @@ -83,14 +87,19 @@ def test(q, bus, mc): conn.change_self_alias('TheBatman') get_aliases, _ = q.expect_many( - EventPattern('dbus-method-call', interface=cs.CONN_IFACE_ALIASING, - method='GetAliases', handled=True), + EventPattern('dbus-method-call', + interface=cs.CONN_IFACE_CONTACTS, + predicate=(lambda e: e.method in ( + 'GetContactAttributes', 'GetContactByID' + ) and + cs.CONN_IFACE_ALIASING in e.args[1]), + handled=True), EventPattern('dbus-signal', path=account.object_path, signal='AccountPropertyChanged', interface=cs.ACCOUNT, predicate=(lambda e: e.args[0].get('NormalizedName') == 'thebatman')), ) - assert get_aliases.args[0] == [ conn.self_handle ] + assert get_aliases.args[0] in ([conn.self_handle], conn.self_id) q.expect('dbus-signal', path=account.object_path, signal='AccountPropertyChanged', interface=cs.ACCOUNT, args=[{'Nickname': 'TheBatman'}]) @@ -117,14 +126,19 @@ def test(q, bus, mc): # In response to the self-handle change, we check our nickname again get_aliases, _ = q.expect_many( - EventPattern('dbus-method-call', interface=cs.CONN_IFACE_ALIASING, - method='GetAliases', handled=True), + EventPattern('dbus-method-call', + interface=cs.CONN_IFACE_CONTACTS, + predicate=(lambda e: e.method in ( + 'GetContactAttributes', 'GetContactByID' + ) and + cs.CONN_IFACE_ALIASING in e.args[1]), + handled=True), EventPattern('dbus-signal', path=account.object_path, signal='AccountPropertyChanged', interface=cs.ACCOUNT, predicate=(lambda e: e.args[0].get('NormalizedName') == 'brucewayne')), ) - assert get_aliases.args[0] == [ conn.self_handle ] + assert get_aliases.args[0] in ([conn.self_handle], conn.self_id) forbidden = [EventPattern('dbus-signal', signal='AccountPropertyChanged', predicate=lambda e: 'Nickname' in e.args[0])] diff --git a/tests/twisted/account-manager/nickname.py b/tests/twisted/account-manager/nickname.py index f23f072..b128942 100644 --- a/tests/twisted/account-manager/nickname.py +++ b/tests/twisted/account-manager/nickname.py @@ -51,7 +51,11 @@ def test(q, bus, mc, nickname): # OK, let's go online expect_after_connect = [ EventPattern('dbus-method-call', - interface=cs.CONN_IFACE_ALIASING, method='GetAliases', + interface=cs.CONN_IFACE_CONTACTS, + predicate=(lambda e: e.method in ( + 'GetContactAttributes', 'GetContactByID' + ) and + cs.CONN_IFACE_ALIASING in e.args[1]), handled=True), ] forbidden = [] diff --git a/tests/twisted/constants.py b/tests/twisted/constants.py index 6bb50c7..137ea0d 100644 --- a/tests/twisted/constants.py +++ b/tests/twisted/constants.py @@ -208,6 +208,8 @@ 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_CONTACT_CAPABILITIES = CONN_IFACE_CONTACT_CAPS + '/capabilities' ATTR_PRESENCE = CONN_IFACE_SIMPLE_PRESENCE + '/presence' ATTR_SUBSCRIBE = CONN_IFACE_CONTACT_LIST + '/subscribe' diff --git a/tests/twisted/mctest.py b/tests/twisted/mctest.py index 7f6fef3..27ae204 100644 --- a/tests/twisted/mctest.py +++ b/tests/twisted/mctest.py @@ -254,6 +254,7 @@ class SimulatedConnection(object): self.extra_interfaces = extra_interfaces[:] self.interfaces = [] + self.interfaces.append(cs.CONN_IFACE_CONTACTS) if self.has_requests: self.interfaces.append(cs.CONN_IFACE_REQUESTS) @@ -312,6 +313,13 @@ class SimulatedConnection(object): q.add_dbus_method_impl(self.GetContactAttributes, path=self.object_path, interface=cs.CONN_IFACE_CONTACTS, method='GetContactAttributes') + q.add_dbus_method_impl(self.GetContactByID, + path=self.object_path, + interface=cs.CONN_IFACE_CONTACTS, method='GetContactByID') + q.add_dbus_method_impl(self.Get_ContactAttributeInterfaces, + path=self.object_path, + interface=cs.PROPERTIES_IFACE, method='Get', + args=[cs.CONN_IFACE_CONTACTS, 'ContactAttributeInterfaces']) q.add_dbus_method_impl(self.GetAll_Contacts, path=self.object_path, interface=cs.PROPERTIES_IFACE, method='GetAll', @@ -377,8 +385,10 @@ class SimulatedConnection(object): if has_hidden: self.statuses['hidden'] = (cs.PRESENCE_HIDDEN, True, True) - self.presence = dbus.Struct((cs.PRESENCE_OFFLINE, 'offline', ''), - signature='uss') + # "dbus.UInt32" to work around + # https://bugs.freedesktop.org/show_bug.cgi?id=69967 + self.presence = dbus.Struct((dbus.UInt32(cs.PRESENCE_OFFLINE), + 'offline', ''), signature='uss') def change_self_ident(self, ident): self.self_ident = ident @@ -470,7 +480,9 @@ class SimulatedConnection(object): def SetPresence(self, e): if e.args[0] in self.statuses: - presence = dbus.Struct((self.statuses[e.args[0]][0], + # "dbus.UInt32" to work around + # https://bugs.freedesktop.org/show_bug.cgi?id=69967 + presence = dbus.Struct((dbus.UInt32(self.statuses[e.args[0]][0]), e.args[0], e.args[1]), signature='uss') old_presence = self.presence @@ -478,11 +490,10 @@ class SimulatedConnection(object): if presence != old_presence: self.presence = presence - if self.status == cs.CONN_STATUS_CONNECTED: - self.q.dbus_emit(self.object_path, - cs.CONN_IFACE_SIMPLE_PRESENCE, 'PresencesChanged', - { self.self_handle : presence }, - signature='a{u(uss)}') + self.q.dbus_emit(self.object_path, + cs.CONN_IFACE_SIMPLE_PRESENCE, 'PresencesChanged', + { self.self_handle : presence }, + signature='a{u(uss)}') self.q.dbus_return(e.message, signature='') else: @@ -555,7 +566,9 @@ class SimulatedConnection(object): status, reason, signature='uu') if self.status == cs.CONN_STATUS_CONNECTED and self.has_presence: if self.presence[0] == cs.PRESENCE_OFFLINE: - self.presence = dbus.Struct((cs.PRESENCE_AVAILABLE, + # "dbus.UInt32" to work around + # https://bugs.freedesktop.org/show_bug.cgi?id=69967 + self.presence = dbus.Struct((dbus.UInt32(cs.PRESENCE_AVAILABLE), 'available', ''), signature='uss') self.q.dbus_emit(self.object_path, @@ -617,24 +630,73 @@ class SimulatedConnection(object): for channel in channels], signature='a(oa{sv})') + def get_contact_attributes(self, h, ifaces): + id = self.inspect_handles([h])[0] + ifaces = set(ifaces).intersection( + self.get_contact_attribute_interfaces()) + + ret = dbus.Dictionary({}, signature='sv') + ret[cs.ATTR_CONTACT_ID] = id + + if cs.CONN_IFACE_ALIASING in ifaces: + if h == self.self_handle: + ret[cs.ATTR_ALIAS] = self.self_alias + else: + ret[cs.ATTR_ALIAS] = id + + if cs.CONN_IFACE_AVATARS in ifaces: + if h == self.self_handle: + if self.avatar is not None: + # we just stringify the avatar as the token + # (also, empty avatar => no avatar => empty token) + ret[cs.ATTR_AVATAR_TOKEN] = str(self.avatar[0]) + + if cs.CONN_IFACE_SIMPLE_PRESENCE in ifaces: + if h == self.self_handle: + ret[cs.ATTR_PRESENCE] = self.presence + else: + # stub - MC doesn't care + # "dbus.UInt32" to work around + # https://bugs.freedesktop.org/show_bug.cgi?id=69967 + ret[cs.ATTR_PRESENCE] = (dbus.UInt32(cs.PRESENCE_UNKNOWN), + 'unknown', '') + + return ret + + def get_contact_attribute_interfaces(self): + return set(self.interfaces).intersection(set([ + cs.CONN_IFACE_ALIASING, + cs.CONN_IFACE_AVATARS, + cs.CONN_IFACE_SIMPLE_PRESENCE, + ])) + def GetContactAttributes(self, e): - ret = {} + ret = dbus.Dictionary({}, signature='ua{sv}') try: for h in e.args[0]: - id = self.inspect_handles(h)[0] - ret[dbus.UInt32(h)] = dbus.Dictionary({telepathy.CONN_IFACE + '/contact-id': id}, - signature='sv') + ret[dbus.UInt32(h)] = self.get_contact_attributes(h, e.args[1]) - q.dbus_return(e.message, ret, signature='a{ua{sv}}') + self.q.dbus_return(e.message, ret, signature='a{ua{sv}}') except e: self.q.dbus_raise(e.message, INVALID_HANDLE, str(e.args[0])) + def GetContactByID(self, e): + h = self.ensure_handle(e.args[0]) + self.q.dbus_return(e.message, h, + self.get_contact_attributes(h, e.args[1]), signature='ua{sv}') + def GetAll_Contacts(self, e): self.q.dbus_return(e.message, { - 'ContactAttributeInterfaces': [] + 'ContactAttributeInterfaces': + self.get_contact_attribute_interfaces(), }, signature='a{sv}') + def Get_ContactAttributeInterfaces(self, e): + self.q.dbus_return(e.message, + dbus.Array(self.get_contact_attribute_interfaces(), signature='s'), + signature='v') + class SimulatedChannel(object): def __init__(self, conn, immutable, mutable={}, destroyable=False, group=False): -- 1.8.4.rc3