summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonny Lamb <jonny.lamb@collabora.co.uk>2011-09-07 14:53:16 +0100
committerJonny Lamb <jonny.lamb@collabora.co.uk>2011-09-07 14:56:56 +0100
commit5f1eab4f8b3fbb7af86ef4d98007a87852ce92f7 (patch)
tree39036cae0c021d7cc4f00a1fbd55b8b773cbfcab
parentbd59fb05311ccb0a4a6ed2bc5fb269b5d3afd860 (diff)
gabble tests: copy over salut tests and make them pass
These are all copies of the salut tests, but it's really not worth trying to make them work on both salut and gabble so here is some code duplication. Sorry. Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk>
-rw-r--r--tests/twisted/Makefile.am8
-rwxr-xr-xtests/twisted/gabble/hct.py185
-rw-r--r--tests/twisted/gabble/message.py390
-rw-r--r--tests/twisted/gabble/service.py307
-rwxr-xr-xtests/twisted/gabble/sidecar.py35
-rw-r--r--tests/twisted/gabble/status.py286
-rw-r--r--tests/twisted/gabble/success.py19
7 files changed, 1210 insertions, 20 deletions
diff --git a/tests/twisted/Makefile.am b/tests/twisted/Makefile.am
index a47cf59..19f9f78 100644
--- a/tests/twisted/Makefile.am
+++ b/tests/twisted/Makefile.am
@@ -9,7 +9,13 @@ TWISTED_BASIC_TESTS += \
salut/message.py \
salut/status.py \
salut/service.py \
- salut/hct.py
+ salut/hct.py \
+ gabble/sidecar.py \
+ gabble/message.py \
+ gabble/status.py \
+ gabble/service.py \
+ gabble/hct.py
+
endif
config.py: Makefile
diff --git a/tests/twisted/gabble/hct.py b/tests/twisted/gabble/hct.py
new file mode 100755
index 0000000..714afcc
--- /dev/null
+++ b/tests/twisted/gabble/hct.py
@@ -0,0 +1,185 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2011 Intel Corp.
+#
+# 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
+
+import dbus
+
+from gabbleservicetest import call_async, EventPattern, assertEquals, \
+ assertLength, assertContains, sync_dbus, ProxyWrapper
+from gabbletest import exec_test, elem_iq, elem
+from gabblecaps_helper import presence_and_disco, receive_presence_and_ask_caps, \
+ disco_caps
+
+import gabbleconstants as cs
+import ns
+import yconstants as ycs
+
+client = 'http://telepathy.im/fake'
+features = [
+ ns.JINGLE_015,
+ ns.JINGLE_015_AUDIO,
+ ns.JINGLE_015_VIDEO,
+ ns.GOOGLE_P2P,
+ ycs.SERVICE_NS + '#the.target.service'
+ ]
+identity = ['client/pc/en/Lolclient 0.L0L']
+
+def test(q, bus, conn, stream):
+ bare_jid = "test-hct@example.com"
+ full_jid = bare_jid + "/LikeLava"
+
+ call_async(q, conn.Future, 'EnsureSidecar', ycs.STATUS_IFACE)
+ conn.Connect()
+
+ q.expect('dbus-signal', signal='StatusChanged', args=[0, 1])
+
+ e = q.expect('dbus-return', method='EnsureSidecar')
+ path, props = e.value
+ assertEquals({}, props)
+
+ status = ProxyWrapper(bus.get_object(conn.bus_name, path),
+ ycs.STATUS_IFACE, {})
+
+ discovered = status.Get(ycs.STATUS_IFACE, 'DiscoveredServices',
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ assertEquals({}, discovered)
+
+ self_handle = conn.GetSelfHandle()
+ self_handle_name = conn.InspectHandles(cs.HT_CONTACT, [self_handle])[0]
+
+ caps = {'ver': '0.1', 'node': client}
+ presence_and_disco(q, conn, stream, full_jid, True, client, caps,
+ features, identity, {}, True, None)
+
+ # now update the caps
+ conn.ContactCapabilities.UpdateCapabilities([
+ ('well.gnome.name', [],
+ ['com.meego.xpmn.ytstenut.Channel/uid/org.gnome.Banshee',
+ 'com.meego.xpmn.ytstenut.Channel/type/application',
+ 'com.meego.xpmn.ytstenut.Channel/name/en_GB/Banshee Media Player',
+ 'com.meego.xpmn.ytstenut.Channel/name/fr/Banshee Lecteur de Musique',
+ 'com.meego.xpmn.ytstenut.Channel/caps/urn:ytstenut:capabilities:yts-caps-audio',
+ 'com.meego.xpmn.ytstenut.Channel/caps/urn:ytstenut:data:jingle:rtp'])])
+
+
+ _, e = q.expect_many(EventPattern('dbus-signal', signal='ServiceAdded'),
+ EventPattern('stream-presence'))
+
+ e, _, _ = disco_caps(q, stream, e)
+
+ iq = e.stanza
+ query = iq.children[0]
+
+ x = None
+ for child in query.children:
+ if child.name == 'x' and child.uri == ns.X_DATA:
+ # we should only have one child
+ assert x is None
+ x = child
+ # don't break here as we can waste time to make sure x
+ # isn't assigned twice
+
+ assert x is not None
+
+ for field in x.children:
+ if field['var'] == 'FORM_TYPE':
+ assertEquals('hidden', field['type'])
+ assertEquals('urn:ytstenut:capabilities#org.gnome.Banshee',
+ field.children[0].children[0])
+ elif field['var'] == 'type':
+ assertEquals('application', field.children[0].children[0])
+ elif field['var'] == 'name':
+ names = [a.children[0] for a in field.children]
+ assertLength(2, names)
+ assertContains('en_GB/Banshee Media Player', names)
+ assertContains('fr/Banshee Lecteur de Musique', names)
+ elif field['var'] == 'capabilities':
+ caps = [a.children[0] for a in field.children]
+ assertLength(2, caps)
+ assertContains('urn:ytstenut:capabilities:yts-caps-audio', caps)
+ assertContains('urn:ytstenut:data:jingle:rtp', caps)
+ else:
+ assert False
+
+ # now add another service
+ forbidden = [EventPattern('dbus-signal', signal='ServiceRemoved')]
+ q.forbid_events(forbidden)
+
+ conn.ContactCapabilities.UpdateCapabilities([
+ ('another.nice.gname', [],
+ ['com.meego.xpmn.ytstenut.Channel/uid/org.gnome.Eog',
+ 'com.meego.xpmn.ytstenut.Channel/type/application',
+ 'com.meego.xpmn.ytstenut.Channel/name/en_GB/Eye Of Gnome',
+ 'com.meego.xpmn.ytstenut.Channel/name/it/Occhio Di uno Gnomo',
+ 'com.meego.xpmn.ytstenut.Channel/caps/urn:ytstenut:capabilities:yts-picz'])])
+
+ e = q.expect('dbus-signal', signal='ServiceAdded')
+
+ sync_dbus(bus, q, conn)
+
+ discovered = status.Get(ycs.STATUS_IFACE, 'DiscoveredServices',
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ assertEquals({'test@localhost':
+ {'org.gnome.Banshee': ('application',
+ {'en_GB': 'Banshee Media Player',
+ 'fr': 'Banshee Lecteur de Musique'},
+ ['urn:ytstenut:capabilities:yts-caps-audio',
+ 'urn:ytstenut:data:jingle:rtp']),
+ 'org.gnome.Eog': ('application',
+ {'en_GB': 'Eye Of Gnome',
+ 'it': 'Occhio Di uno Gnomo'},
+ ['urn:ytstenut:capabilities:yts-picz'])}},
+ discovered)
+
+ q.unforbid_events(forbidden)
+
+ forbidden = [EventPattern('dbus-signal', signal='ServiceRemoved',
+ args=[self_handle_name, 'org.gnome.Eog'])]
+ q.forbid_events(forbidden)
+
+ conn.ContactCapabilities.UpdateCapabilities([
+ ('well.gnome.name', [], [])])
+
+ e = q.expect('dbus-signal', signal='ServiceRemoved',
+ args=[self_handle_name, 'org.gnome.Banshee'])
+
+ sync_dbus(bus, q, conn)
+
+ discovered = status.Get(ycs.STATUS_IFACE, 'DiscoveredServices',
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ assertEquals({'test@localhost':
+ {'org.gnome.Eog': ('application',
+ {'en_GB': 'Eye Of Gnome',
+ 'it': 'Occhio Di uno Gnomo'},
+ ['urn:ytstenut:capabilities:yts-picz'])}},
+ discovered)
+
+ q.unforbid_events(forbidden)
+
+ conn.ContactCapabilities.UpdateCapabilities([
+ ('another.nice.gname', [], [])])
+
+ e = q.expect('dbus-signal', signal='ServiceRemoved',
+ args=[self_handle_name, 'org.gnome.Eog'])
+
+ discovered = status.Get(ycs.STATUS_IFACE, 'DiscoveredServices',
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ assertEquals({}, discovered)
+
+if __name__ == '__main__':
+ exec_test(test, do_connect=False)
diff --git a/tests/twisted/gabble/message.py b/tests/twisted/gabble/message.py
new file mode 100644
index 0000000..43e941f
--- /dev/null
+++ b/tests/twisted/gabble/message.py
@@ -0,0 +1,390 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2011 Intel Corp.
+#
+# 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
+
+from gabbleservicetest import call_async, EventPattern, assertEquals, ProxyWrapper
+from gabbletest import exec_test, make_result_iq, sync_stream
+from gabblecaps_helper import presence_and_disco
+
+from twisted.words.protocols.jabber.client import IQ
+from twisted.words.xish.domish import Element
+
+import gabbleconstants as cs
+import yconstants as ycs
+import ns
+
+client = 'http://telepathy.im/fake'
+caps = {'ver': '0.1', 'node': client}
+features = [
+ ns.JINGLE_015,
+ ns.JINGLE_015_AUDIO,
+ ns.JINGLE_015_VIDEO,
+ ns.GOOGLE_P2P,
+ ycs.SERVICE_NS + '#the.target.service'
+ ]
+identity = ['client/pc/en/Lolclient 0.L0L']
+
+def wrap_channel(bus, conn, path):
+ return ProxyWrapper(bus.get_object(conn.bus_name, path),
+ ycs.CHANNEL_IFACE, {})
+
+def setup_tests(q, bus, conn, stream, announce=False):
+ bare_jid = "test-yst-message@example.com"
+ full_jid = bare_jid + "/HotHotResource"
+
+ if announce:
+ presence_and_disco(q, conn, stream, full_jid,
+ True, client, caps,
+ features, identity, {},
+ True, None)
+
+ sync_stream(q, stream)
+
+ handle = conn.RequestHandles(cs.HT_CONTACT, [full_jid])[0]
+
+ return handle, bare_jid, full_jid
+
+def setup_outgoing_tests(q, bus, conn, stream, announce=True):
+ handle, _, _ = setup_tests(q, bus, conn, stream, announce)
+
+ # okay we got our contact, let's go
+ request_props = {
+ cs.CHANNEL_TYPE: ycs.CHANNEL_IFACE,
+ cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT,
+ cs.TARGET_HANDLE: handle,
+ ycs.REQUEST_TYPE: ycs.REQUEST_TYPE_GET,
+ ycs.REQUEST_ATTRIBUTES: {'hi': 'mom'},
+ ycs.TARGET_SERVICE: 'the.target.service',
+ ycs.INITIATOR_SERVICE: 'the.initiator.service'
+ }
+
+ call_async(q, conn.Requests, 'CreateChannel', request_props)
+
+ e, _ = q.expect_many(EventPattern('dbus-return', method='CreateChannel'),
+ EventPattern('dbus-signal', signal='NewChannels'))
+ path, props = e.value
+
+ for k, v in request_props.items():
+ assertEquals(v, props[k])
+
+ # finally we have our channel
+ chan = wrap_channel(bus, conn, path)
+
+ # let's check we can't call Fail()/Reply()
+ call_async(q, chan, 'Fail', ycs.ERROR_TYPE_CANCEL, 'lol', 'whut', 'pear')
+ q.expect('dbus-error', method='Fail')
+
+ call_async(q, chan, 'Reply', {'lol':'whut'}, '')
+ q.expect('dbus-error', method='Reply')
+
+ # okay enough, let's move on.
+ call_async(q, chan, 'Request')
+
+ e, _ = q.expect_many(EventPattern('stream-iq'),
+ EventPattern('dbus-return', method='Request'))
+
+ assertEquals('get', e.iq_type)
+ assertEquals('message', e.query_name)
+ assertEquals('urn:ytstenut:message', e.query_ns)
+
+ # we shouldn't be able to call this again
+ call_async(q, chan, 'Request')
+ q.expect('dbus-error', method='Request')
+
+ return path, e.stanza
+
+def outgoing_reply(q, bus, conn, stream):
+ path, stanza = setup_outgoing_tests(q, bus, conn, stream)
+
+ # reply with nothing
+ reply = make_result_iq(stream, stanza)
+ stream.send(reply)
+
+ e = q.expect('dbus-signal', signal='Replied', path=path)
+ args, xml = e.args
+ assertEquals({}, args)
+ assertEquals('<?xml version="1.0" encoding="UTF-8"?>\n' \
+ + '<message xmlns="urn:ytstenut:message"/>\n', xml)
+
+def outgoing_fail(q, bus, conn, stream):
+ path, stanza = setup_outgoing_tests(q, bus, conn, stream)
+
+ # construct a nice error reply
+ reply = IQ(None, 'error')
+ reply['id'] = stanza['id']
+ reply['from'] = stanza['to']
+ error = reply.addElement('error')
+ error['type'] = 'cancel'
+ error['code'] = '409'
+ error.addElement((ns.STANZA, 'conflict'))
+ error.addElement((ycs.MESSAGE_NS, 'yodawg'))
+ text = error.addElement((ns.STANZA, 'text'),
+ content='imma let you finish')
+
+ stream.send(reply)
+
+ e = q.expect('dbus-signal', signal='Failed', path=path)
+ error_type, stanza_error_name, yst_error_name, text = e.args
+ assertEquals(ycs.ERROR_TYPE_CANCEL, error_type)
+ assertEquals('conflict', stanza_error_name)
+ assertEquals('yodawg', yst_error_name)
+ assertEquals('imma let you finish', text)
+
+def bad_requests(q, bus, conn, stream):
+ handle, _, _ = setup_tests(q, bus, conn, stream)
+
+ props = {
+ cs.CHANNEL_TYPE: ycs.CHANNEL_IFACE,
+ cs.TARGET_HANDLE_TYPE: cs.HT_CONTACT,
+ }
+
+ def ensure_error(extra={}):
+ copy = props.copy()
+ copy.update(extra)
+
+ call_async(q, conn.Requests, 'CreateChannel', copy)
+ q.expect('dbus-error', method='CreateChannel')
+
+ # bad handle
+ ensure_error({cs.TARGET_HANDLE: 42})
+
+ # offline
+ ensure_error({cs.TARGET_ID: 'lolbags@dingdong'})
+
+ props.update({cs.TARGET_HANDLE: handle})
+
+ # RequestType
+ ensure_error()
+ ensure_error({ycs.REQUEST_TYPE: 99})
+ props.update({ycs.REQUEST_TYPE: ycs.REQUEST_TYPE_GET})
+
+ # TargetService
+ ensure_error()
+ ensure_error({ycs.TARGET_SERVICE: 'lol/bags/what\'s this?!!!!'})
+ props.update({ycs.TARGET_SERVICE: 'the.target.service'})
+
+ # InitiatorService
+ ensure_error()
+ ensure_error({ycs.INITIATOR_SERVICE: 'lol/bags/what\'s this?!!!!'})
+ props.update({ycs.INITIATOR_SERVICE: 'the.initiator.service'})
+
+ # RequestAttributes: a{ss}, not a{si}
+ ensure_error({ycs.REQUEST_ATTRIBUTES: {'lol': 2}})
+
+ # RequestBody
+ ensure_error({ycs.REQUEST_BODY: 'no way is this real XML'})
+
+def setup_incoming_tests(q, bus, conn, stream):
+ handle, bare_jid, full_jid = setup_tests(q, bus, conn, stream)
+
+ self_handle = conn.GetSelfHandle()
+ self_handle_name = conn.InspectHandles(cs.HT_CONTACT, [self_handle])[0]
+
+ iq = IQ(None, 'get')
+ iq['id'] = 'le-loldongs'
+ iq['from'] = full_jid
+ iq['to'] = self_handle_name
+ msg = iq.addElement((ycs.MESSAGE_NS, 'message'))
+ msg['from-service'] = 'the.from.service'
+ msg['to-service'] = 'the.to.service'
+ msg['owl-companions'] = 'the pussy cat'
+ msg['destination'] = 'sea'
+ msg['seacraft'] = 'beautiful pea green boat'
+
+ lol = msg.addElement((None, 'lol'))
+ lol['some'] = 'stuff'
+ lol['to'] = 'fill'
+ lol['the'] = 'time'
+ lol.addElement((None, 'look-into-my-eyes'),
+ content='and tell me how boring writing these tests is')
+
+ stream.send(iq)
+
+ e = q.expect('dbus-signal', signal='NewChannels', predicate=lambda e:
+ e.args[0][0][1][cs.CHANNEL_TYPE] == ycs.CHANNEL_IFACE)
+ path, props = e.args[0][0]
+
+ assertEquals(handle, props[cs.INITIATOR_HANDLE])
+ assertEquals(bare_jid, props[cs.INITIATOR_ID])
+ assertEquals(False, props[cs.REQUESTED])
+ assertEquals(handle, props[cs.TARGET_HANDLE])
+ assertEquals(cs.HT_CONTACT, props[cs.TARGET_HANDLE_TYPE])
+ assertEquals(bare_jid, props[cs.TARGET_ID])
+
+ assertEquals('the.from.service', props[ycs.INITIATOR_SERVICE])
+ assertEquals('the.to.service', props[ycs.TARGET_SERVICE])
+ assertEquals(ycs.REQUEST_TYPE_GET, props[ycs.REQUEST_TYPE])
+ assertEquals({'destination': 'sea',
+ 'owl-companions': 'the pussy cat',
+ 'seacraft': 'beautiful pea green boat'},
+ props[ycs.REQUEST_ATTRIBUTES])
+
+ assertEquals('<?xml version="1.0" encoding="UTF-8"?>\n' \
+ '<message seacraft="beautiful pea green boat" ' \
+ 'from-service="the.from.service" destination="sea" ' \
+ 'owl-companions="the pussy cat" to-service="the.to.service" ' \
+ 'xmlns="urn:ytstenut:message">' \
+ '<lol to="fill" the="time" some="stuff">' \
+ '<look-into-my-eyes>and tell me how boring ' \
+ 'writing these tests is</look-into-my-eyes>' \
+ '</lol></message>\n', props[ycs.REQUEST_BODY])
+
+ # finally we have our channel
+ chan = wrap_channel(bus, conn, path)
+
+ # let's check we can't call Request()
+ call_async(q, chan, 'Request')
+ q.expect('dbus-error', method='Request')
+
+ return chan, bare_jid, full_jid, self_handle_name
+
+def incoming_reply(q, bus, conn, stream):
+ chan, bare_jid, full_jid, self_handle_name = \
+ setup_incoming_tests(q, bus, conn, stream)
+
+ moar = Element((ycs.MESSAGE_NS, 'message'))
+ moar['ninety-nine-problems'] = 'but a sauvignon blanc aint one'
+ moar['also'] = 'my mum said hi'
+ trollface = moar.addElement('trollface', content='problem?')
+
+ call_async(q, chan, 'Reply',
+ {'ninety-nine-problems': 'but a sauvignon blanc aint one',
+ 'also': 'my mum said hi'},
+ moar.toXml())
+
+ _, e = q.expect_many(EventPattern('dbus-return', method='Reply'),
+ EventPattern('stream-message'))
+
+ iq = e.stanza
+ assertEquals('le-loldongs', iq['id'])
+ assertEquals('result', iq['type'])
+ assertEquals(self_handle_name, iq['from'])
+ assertEquals(full_jid, iq['to'])
+ assertEquals(1, len(iq.children))
+
+ message = iq.children[0]
+
+ assertEquals('message', message.name)
+ assertEquals(ycs.MESSAGE_NS, message.uri)
+ assertEquals('my mum said hi', message['also'])
+ assertEquals('but a sauvignon blanc aint one', message['ninety-nine-problems'])
+ assertEquals('the.from.service', message['to-service'])
+ assertEquals('the.to.service', message['from-service'])
+ assertEquals(1, len(message.children))
+
+ trollface = message.children[0]
+
+ assertEquals('trollface', trollface.name)
+ assertEquals(1, len(trollface.children))
+
+ assertEquals('problem?', trollface.children[0])
+
+ # check we can't call anything any more
+ call_async(q, chan, 'Fail', ycs.ERROR_TYPE_CANCEL, 'lol', 'whut', 'pear')
+ q.expect('dbus-error', method='Fail')
+
+ call_async(q, chan, 'Reply', {'lol':'whut'}, '')
+ q.expect('dbus-error', method='Reply')
+
+ call_async(q, chan, 'Request')
+ q.expect('dbus-error', method='Request')
+
+def incoming_fail(q, bus, conn, stream):
+ chan, bare_jid, full_jid, self_handle_name = \
+ setup_incoming_tests(q, bus, conn, stream)
+
+ call_async(q, chan, 'Fail',
+ ycs.ERROR_TYPE_AUTH, 'auth', 'omgwtfbbq',
+ 'I most certainly dont feel like dancing')
+
+ _, e = q.expect_many(EventPattern('dbus-return', method='Fail'),
+ EventPattern('stream-message'))
+
+ iq = e.stanza
+ assertEquals('le-loldongs', iq['id'])
+ assertEquals('error', iq['type'])
+ assertEquals(self_handle_name, iq['from'])
+ assertEquals(full_jid, iq['to'])
+ assertEquals(2, len(iq.children))
+
+ def check_message(message):
+ assertEquals('message', message.name)
+ assertEquals(ycs.MESSAGE_NS, message.uri)
+ assertEquals('beautiful pea green boat', message['seacraft'])
+ assertEquals('sea', message['destination'])
+ assertEquals('the pussy cat', message['owl-companions'])
+ assertEquals('the.from.service', message['from-service'])
+ assertEquals('the.to.service', message['to-service'])
+ assertEquals(1, len(message.children))
+
+ lol = message.children[0]
+
+ assertEquals('lol', lol.name)
+ assertEquals('fill', lol['to'])
+ assertEquals('time', lol['the'])
+ assertEquals('stuff', lol['some'])
+ assertEquals(1, len(lol.children))
+
+ look = lol.children[0]
+
+ assertEquals('look-into-my-eyes', look.name)
+ assertEquals(1, len(look.children))
+ assertEquals('and tell me how boring writing these tests is', look.children[0])
+
+ def check_error(error):
+ assertEquals('error', error.name)
+ assertEquals('auth', error['type'])
+ assertEquals(3, len(error.children))
+
+ for c in error.children:
+ if c.name == 'auth':
+ assertEquals(ns.STANZA, c.uri)
+ elif c.name == 'omgwtfbbq':
+ assertEquals(ycs.MESSAGE_NS, c.uri)
+ elif c.name == 'text':
+ assertEquals(ns.STANZA, c.uri)
+ assertEquals(1, len(c.children))
+ assertEquals('I most certainly dont feel like dancing',
+ c.children[0])
+ else:
+ raise
+
+ for child in iq.children:
+ if child.name == 'message':
+ check_message(child)
+ elif child.name == 'error':
+ check_error(child)
+ else:
+ raise
+
+ # check we can't call anything any more
+ call_async(q, chan, 'Fail', ycs.ERROR_TYPE_CANCEL, 'lol', 'whut', 'pear')
+ q.expect('dbus-error', method='Fail')
+
+ call_async(q, chan, 'Reply', {'lol':'whut'}, '')
+ q.expect('dbus-error', method='Reply')
+
+ call_async(q, chan, 'Request')
+ q.expect('dbus-error', method='Request')
+
+if __name__ == '__main__':
+ exec_test(outgoing_reply)
+ exec_test(outgoing_fail)
+ exec_test(bad_requests)
+ exec_test(incoming_reply)
+ exec_test(incoming_fail)
diff --git a/tests/twisted/gabble/service.py b/tests/twisted/gabble/service.py
new file mode 100644
index 0000000..6ee49f4
--- /dev/null
+++ b/tests/twisted/gabble/service.py
@@ -0,0 +1,307 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2011 Intel Corp.
+#
+# 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
+
+import dbus
+
+from gabbleservicetest import call_async, EventPattern, assertEquals, \
+ ProxyWrapper, assertNotEquals, assertSameSets
+from gabbletest import exec_test, make_result_iq, sync_stream
+import gabbleconstants as cs
+import yconstants as ycs
+from gabblecaps_helper import *
+
+from twisted.words.xish import xpath
+from twisted.words.xish.domish import Element
+from twisted.words.xish import domish
+
+CLIENT_NAME = 'il-cliente-del-futuro'
+
+client = 'http://telepathy.im/fake'
+client_caps = {'ver': '0.1', 'node': client}
+features = [
+ ns.JINGLE_015,
+ ns.JINGLE_015_AUDIO,
+ ns.JINGLE_015_VIDEO,
+ ns.GOOGLE_P2P,
+ ]
+identity = ['client/pc/en/Lolclient 0.L0L']
+
+banshee = {
+ 'urn:ytstenut:capabilities#org.gnome.Banshee':
+ {'type': ['application'],
+ 'name': ['en_GB/Banshee Media Player',
+ 'fr/Banshee Lecteur de Musique'],
+ 'capabilities': ['urn:ytstenut:capabilities:yts-caps-audio',
+ 'urn:ytstenut:data:jingle:rtp']
+ }
+}
+
+evince = {
+ 'urn:ytstenut:capabilities#org.gnome.Evince':
+ {'type': ['application'],
+ 'name': ['en_GB/Evince Picture Viewer',
+ 'fr/Evince uh, ow do you say'],
+ 'capabilities': ['urn:ytstenut:capabilities:pics'],
+ }
+}
+
+# TODO: move more of the common parts of this test into different
+# functions to cut out the duplication!
+
+def test(q, bus, conn, stream):
+ call_async(q, conn.Future, 'EnsureSidecar', ycs.STATUS_IFACE)
+
+ conn.Connect()
+
+ # Now we're connected, the call we made earlier should return.
+ e = q.expect('dbus-return', method='EnsureSidecar')
+ path, props = e.value
+ assertEquals({}, props)
+
+ status = ProxyWrapper(bus.get_object(conn.bus_name, path),
+ ycs.STATUS_IFACE, {})
+
+ discovered = status.Get(ycs.STATUS_IFACE, 'DiscoveredServices',
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ assertEquals({}, discovered)
+
+ # announce a contact with the right caps
+ bare_jid = "test-service@example.com"
+ full_jid = bare_jid + "/NeeNawNeeNawIAmAnAmbulance"
+
+ contact_handle = conn.RequestHandles(cs.HT_CONTACT, [bare_jid])[0]
+
+ client_caps['ver'] = compute_caps_hash(identity, features, banshee)
+ presence_and_disco(q, conn, stream, full_jid, True, client, client_caps,
+ features, identity, banshee, True, None)
+
+ # this will be fired as text channel caps will be fired
+ _, e = q.expect_many(EventPattern('dbus-signal', signal='ContactCapabilitiesChanged',
+ predicate=lambda e: contact_handle in e.args[0]),
+ EventPattern('dbus-signal', signal='ServiceAdded'))
+
+ contact_id, service_name, details = e.args
+ assertEquals(bare_jid, contact_id)
+ assertEquals('org.gnome.Banshee', service_name)
+
+ type, name_map, caps = details
+ assertEquals('application', type)
+ assertEquals({'en_GB': 'Banshee Media Player',
+ 'fr': 'Banshee Lecteur de Musique'}, name_map)
+ assertSameSets(['urn:ytstenut:capabilities:yts-caps-audio',
+ 'urn:ytstenut:data:jingle:rtp'], caps)
+
+ discovered = status.Get(ycs.STATUS_IFACE, 'DiscoveredServices',
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ assertEquals({bare_jid: {
+ 'org.gnome.Banshee':
+ ('application',
+ {'en_GB': 'Banshee Media Player',
+ 'fr': 'Banshee Lecteur de Musique'},
+ ['urn:ytstenut:capabilities:yts-caps-audio',
+ 'urn:ytstenut:data:jingle:rtp'])},
+ }, discovered)
+
+ # add evince
+ tmp = banshee.copy()
+ tmp.update(evince)
+ client_caps['ver'] = compute_caps_hash(identity, features, tmp)
+ presence_and_disco(q, conn, stream, full_jid, True, client, client_caps,
+ features, identity, tmp, False)
+
+ e = q.expect('dbus-signal', signal='ServiceAdded')
+
+ contact_id, service_name, details = e.args
+ assertEquals(bare_jid, contact_id)
+ assertEquals('org.gnome.Evince', service_name)
+
+ type, name_map, caps = details
+ assertEquals('application', type)
+ assertEquals({'en_GB': 'Evince Picture Viewer',
+ 'fr': 'Evince uh, ow do you say'}, name_map)
+ assertSameSets(['urn:ytstenut:capabilities:pics'], caps)
+
+ discovered = status.Get(ycs.STATUS_IFACE, 'DiscoveredServices',
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ assertEquals({bare_jid: {
+ 'org.gnome.Banshee':
+ ('application',
+ {'en_GB': 'Banshee Media Player',
+ 'fr': 'Banshee Lecteur de Musique'},
+ ['urn:ytstenut:capabilities:yts-caps-audio',
+ 'urn:ytstenut:data:jingle:rtp']),
+ 'org.gnome.Evince':
+ ('application',
+ {'en_GB': 'Evince Picture Viewer',
+ 'fr': 'Evince uh, ow do you say'},
+ ['urn:ytstenut:capabilities:pics'])}
+ }, discovered)
+
+ # remove evince
+ forbidden = [EventPattern('dbus-signal', signal='stream-iq')]
+ q.forbid_events(forbidden)
+
+ client_caps['ver'] = compute_caps_hash(identity, features, banshee)
+ send_presence(q, conn, stream, full_jid, client_caps, initial=False)
+
+ e = q.expect('dbus-signal', signal='ServiceRemoved')
+
+ contact_id, service_name = e.args
+ assertEquals(bare_jid, contact_id)
+ assertEquals('org.gnome.Evince', service_name)
+
+ discovered = status.Get(ycs.STATUS_IFACE, 'DiscoveredServices',
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ assertEquals({bare_jid: {
+ 'org.gnome.Banshee':
+ ('application',
+ {'en_GB': 'Banshee Media Player',
+ 'fr': 'Banshee Lecteur de Musique'},
+ ['urn:ytstenut:capabilities:yts-caps-audio',
+ 'urn:ytstenut:data:jingle:rtp'])},
+ }, discovered)
+
+ sync_stream(q, stream)
+
+ q.unforbid_events(forbidden)
+
+ # now just evince
+ client_caps['ver'] = compute_caps_hash(identity, features, evince)
+ presence_and_disco(q, conn, stream, full_jid, True, client, client_caps,
+ features, identity, evince, False)
+
+ sa, sr = q.expect_many(EventPattern('dbus-signal', signal='ServiceAdded'),
+ EventPattern('dbus-signal', signal='ServiceRemoved'))
+
+ contact_id, service_name, details = sa.args
+ assertEquals(bare_jid, contact_id)
+ assertEquals('org.gnome.Evince', service_name)
+
+ type, name_map, caps = details
+ assertEquals('application', type)
+ assertEquals({'en_GB': 'Evince Picture Viewer',
+ 'fr': 'Evince uh, ow do you say'}, name_map)
+ assertSameSets(['urn:ytstenut:capabilities:pics'], caps)
+
+ contact_id, service_name = sr.args
+ assertEquals(bare_jid, contact_id)
+ assertEquals('org.gnome.Banshee', service_name)
+
+ discovered = status.Get(ycs.STATUS_IFACE, 'DiscoveredServices',
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ assertEquals({bare_jid: {
+ 'org.gnome.Evince':
+ ('application',
+ {'en_GB': 'Evince Picture Viewer',
+ 'fr': 'Evince uh, ow do you say'},
+ ['urn:ytstenut:capabilities:pics'])}
+ }, discovered)
+
+ # just banshee again
+ forbidden = [EventPattern('dbus-signal', signal='stream-iq')]
+ q.forbid_events(forbidden)
+
+ client_caps['ver'] = compute_caps_hash(identity, features, banshee)
+ send_presence(q, conn, stream, full_jid, client_caps, initial=False)
+
+ sr, sa = q.expect_many(EventPattern('dbus-signal', signal='ServiceRemoved'),
+ EventPattern('dbus-signal', signal='ServiceAdded'))
+
+ contact_id, service_name = sr.args
+ assertEquals(bare_jid, contact_id)
+ assertEquals('org.gnome.Evince', service_name)
+
+ contact_id, service_name, details = sa.args
+ assertEquals(bare_jid, contact_id)
+ assertEquals('org.gnome.Banshee', service_name)
+
+ type, name_map, caps = details
+ assertEquals('application', type)
+ assertEquals({'en_GB': 'Banshee Media Player',
+ 'fr': 'Banshee Lecteur de Musique'}, name_map)
+ assertSameSets(['urn:ytstenut:capabilities:yts-caps-audio',
+ 'urn:ytstenut:data:jingle:rtp'], caps)
+
+ discovered = status.Get(ycs.STATUS_IFACE, 'DiscoveredServices',
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ assertEquals({bare_jid: {
+ 'org.gnome.Banshee':
+ ('application',
+ {'en_GB': 'Banshee Media Player',
+ 'fr': 'Banshee Lecteur de Musique'},
+ ['urn:ytstenut:capabilities:yts-caps-audio',
+ 'urn:ytstenut:data:jingle:rtp'])}
+ }, discovered)
+
+ sync_stream(q, stream)
+
+ # both again
+ client_caps['ver'] = compute_caps_hash(identity, features, tmp)
+ send_presence(q, conn, stream, full_jid, client_caps, initial=False)
+
+ sa = q.expect('dbus-signal', signal='ServiceAdded')
+
+ contact_id, service_name, details = sa.args
+ assertEquals(bare_jid, contact_id)
+ assertEquals('org.gnome.Evince', service_name)
+
+ type, name_map, caps = details
+ assertEquals('application', type)
+ assertEquals({'en_GB': 'Evince Picture Viewer',
+ 'fr': 'Evince uh, ow do you say'}, name_map)
+ assertSameSets(['urn:ytstenut:capabilities:pics'], caps)
+
+ discovered = status.Get(ycs.STATUS_IFACE, 'DiscoveredServices',
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ assertEquals({bare_jid: {
+ 'org.gnome.Banshee':
+ ('application',
+ {'en_GB': 'Banshee Media Player',
+ 'fr': 'Banshee Lecteur de Musique'},
+ ['urn:ytstenut:capabilities:yts-caps-audio',
+ 'urn:ytstenut:data:jingle:rtp']),
+ 'org.gnome.Evince':
+ ('application',
+ {'en_GB': 'Evince Picture Viewer',
+ 'fr': 'Evince uh, ow do you say'},
+ ['urn:ytstenut:capabilities:pics'])}
+ }, discovered)
+
+ sync_stream(q, stream)
+
+ q.unforbid_events(forbidden)
+
+ # and finally, nothing
+ client_caps['ver'] = compute_caps_hash(identity, features, {})
+ presence_and_disco(q, conn, stream, full_jid, True, client, client_caps,
+ features, identity, {}, False)
+
+ q.expect_many(EventPattern('dbus-signal', signal='ServiceRemoved',
+ args=[bare_jid, 'org.gnome.Banshee']),
+ EventPattern('dbus-signal', signal='ServiceRemoved',
+ args=[bare_jid, 'org.gnome.Evince']))
+
+ discovered = status.Get(ycs.STATUS_IFACE, 'DiscoveredServices',
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ assertEquals({}, discovered)
+
+ # super.
+
+if __name__ == '__main__':
+ exec_test(test, do_connect=False)
diff --git a/tests/twisted/gabble/sidecar.py b/tests/twisted/gabble/sidecar.py
new file mode 100755
index 0000000..92e16b7
--- /dev/null
+++ b/tests/twisted/gabble/sidecar.py
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2011 Intel Corp.
+#
+# 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
+
+from gabbleservicetest import call_async, EventPattern, assertEquals
+from gabbletest import exec_test
+from yconstants import STATUS_IFACE
+
+def test(q, bus, conn, stream):
+ call_async(q, conn.Future, 'EnsureSidecar', STATUS_IFACE)
+
+ conn.Connect()
+
+ # Now we're connected, the call we made earlier should return.
+ e = q.expect('dbus-return', method='EnsureSidecar')
+ path, props = e.value
+ assertEquals({}, props)
+
+if __name__ == '__main__':
+ exec_test(test, do_connect=False)
diff --git a/tests/twisted/gabble/status.py b/tests/twisted/gabble/status.py
new file mode 100644
index 0000000..8917575
--- /dev/null
+++ b/tests/twisted/gabble/status.py
@@ -0,0 +1,286 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2011 Intel Corp.
+#
+# 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
+
+import dbus
+
+from gabbleservicetest import call_async, EventPattern, assertEquals, \
+ ProxyWrapper, assertNotEquals
+from gabbletest import exec_test, make_result_iq, acknowledge_iq
+import gabbleconstants as cs
+import yconstants as ycs
+from gabblecaps_helper import *
+
+from twisted.words.xish import xpath
+from twisted.words.xish.domish import Element
+from twisted.words.xish import domish
+
+CAP_NAME = 'urn:ytstenut:capabilities:h264-over-ants'
+CLIENT_NAME = 'fake-client'
+
+client = 'http://telepathy.im/fake'
+caps = {'ver': '0.1', 'node': client}
+features = [
+ ns.JINGLE_015,
+ ns.JINGLE_015_AUDIO,
+ ns.JINGLE_015_VIDEO,
+ ns.GOOGLE_P2P,
+ ycs.SERVICE_NS + '#the.target.service',
+ CAP_NAME + '+notify'
+ ]
+identity = ['client/pc/en/Lolclient 0.L0L']
+
+def check_pep_set(iq):
+ pubsub = iq.children[0]
+ publish = pubsub.children[0]
+ item = publish.children[0]
+ status_el = item.children[0]
+
+ desc = None
+ if status_el.children:
+ desc = status_el.children[0]
+
+ assertEquals('set', iq['type'])
+ assertEquals(1, len(iq.children))
+
+ assertEquals('pubsub', pubsub.name)
+ assertEquals(ns.PUBSUB, pubsub.uri)
+ assertEquals(1, len(pubsub.children))
+
+ assertEquals('publish', publish.name)
+ assertEquals(CAP_NAME, publish['node'])
+ assertEquals(1, len(publish.children))
+
+ assertEquals('item', item.name)
+ assertEquals(1, len(item.children))
+
+ assertEquals('status', status_el.name)
+
+ if desc:
+ assertEquals(1, len(status_el.children))
+
+ assertEquals('description', desc.name)
+ assertEquals(1, len(desc.children))
+
+ return status_el, desc
+
+def send_back_pep_event(stream, status_el):
+ msg = Element((None, 'message'))
+ msg['type'] = 'headline'
+ msg['from'] = 'test@localhost'
+ msg['to'] = 'test@localhost/Resource'
+ msg['id'] = 'le-headline'
+ event = msg.addElement('event')
+ event['xmlns'] = ns.PUBSUB_EVENT
+ items = event.addElement('items')
+ items['node'] = CAP_NAME
+ item = items.addElement('item')
+
+ # just steal this
+ item.addChild(status_el)
+
+ # and go
+ stream.send(msg)
+
+def test(q, bus, conn, stream):
+ # we won't be using any data forms, so these two shouldn't ever be
+ # fired.
+ q.forbid_events([EventPattern('dbus-signal', signal='ServiceAdded'),
+ EventPattern('dbus-signal', signal='ServiceRemoved')])
+
+ call_async(q, conn.Future, 'EnsureSidecar', ycs.STATUS_IFACE)
+
+ conn.Connect()
+
+ # Now we're connected, the call we made earlier should return.
+ e = q.expect('dbus-return', method='EnsureSidecar')
+ path, props = e.value
+ assertEquals({}, props)
+
+ status = ProxyWrapper(bus.get_object(conn.bus_name, path),
+ ycs.STATUS_IFACE, {})
+
+ # bad capability argument
+ call_async(q, status, 'AdvertiseStatus', '', 'service.name', '')
+ q.expect('dbus-error', method='AdvertiseStatus')
+
+ # bad service name
+ call_async(q, status, 'AdvertiseStatus', CAP_NAME, '', '')
+ q.expect('dbus-error', method='AdvertiseStatus')
+
+ # we can't test that the message type="headline" stanza is
+ # actually received because it's thrown into the loopback stream
+ # immediately.
+
+ # announce a contact with the right caps
+ bare_jid = "test-status@example.com"
+ full_jid = bare_jid + "/BIGGESTRESOURCEEVAAAAHHH"
+
+ contact_handle = conn.RequestHandles(cs.HT_CONTACT, [bare_jid])[0]
+
+ presence_and_disco(q, conn, stream, full_jid, True, client, caps,
+ features, identity, {}, True, None)
+
+ # this will be fired as text channel caps will be fired
+ q.expect('dbus-signal', signal='ContactCapabilitiesChanged',
+ predicate=lambda e: contact_handle in e.args[0])
+
+ # okay now we know about the contact's caps, we can go ahead
+
+ discovered = status.Get(ycs.STATUS_IFACE, 'DiscoveredStatuses',
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ assertEquals({}, discovered)
+
+ el = Element(('urn:ytstenut:status', 'status'))
+ el['activity'] = 'messing-with-your-stuff'
+ desc = el.addElement('ytstenut:description', content='Yeah sorry about that')
+ desc['xml:lang'] = 'en-GB'
+
+ call_async(q, status, 'AdvertiseStatus', CAP_NAME,
+ 'ants.in.their.pants', el.toXml())
+
+ e, _ = q.expect_many(EventPattern('stream-iq'),
+ EventPattern('dbus-return', method='AdvertiseStatus'))
+
+ status_el, desc = check_pep_set(e.stanza)
+ assertEquals('messing-with-your-stuff', status_el['activity'])
+ assertEquals('ants.in.their.pants', status_el['from-service'])
+ assertEquals(CAP_NAME, status_el['capability'])
+ assertEquals('Yeah sorry about that', desc.children[0])
+
+ acknowledge_iq(stream, e.stanza)
+ send_back_pep_event(stream, status_el)
+
+ sig = q.expect('dbus-signal', signal='StatusChanged',
+ interface=ycs.STATUS_IFACE)
+
+ # check signal
+ contact_id, capability, service_name, status_str = sig.args
+ assertEquals(CAP_NAME, capability)
+ assertEquals('ants.in.their.pants', service_name)
+ assertNotEquals('', status_str)
+
+ # check property
+ discovered = status.Get(ycs.STATUS_IFACE, 'DiscoveredStatuses',
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ assertEquals({'test@localhost': {CAP_NAME: {'ants.in.their.pants': status_str}}},
+ discovered)
+
+ # set another
+ el = Element(('urn:ytstenut:status', 'status'))
+ el['activity'] = 'rofling'
+ desc = el.addElement('ytstenut:description', content='U MAD?')
+ desc['xml:lang'] = 'en-GB'
+
+ call_async(q, status, 'AdvertiseStatus', CAP_NAME,
+ 'bananaman.on.holiday', el.toXml())
+
+ e, _ = q.expect_many(EventPattern('stream-iq'),
+ EventPattern('dbus-return', method='AdvertiseStatus'))
+
+ status_el, desc = check_pep_set(e.stanza)
+ assertEquals('rofling', status_el['activity'])
+ assertEquals('bananaman.on.holiday', status_el['from-service'])
+ assertEquals(CAP_NAME, status_el['capability'])
+ assertEquals('U MAD?', desc.children[0])
+
+ acknowledge_iq(stream, e.stanza)
+ send_back_pep_event(stream, status_el)
+
+ sig = q.expect('dbus-signal', signal='StatusChanged',
+ interface=ycs.STATUS_IFACE)
+
+ # check signal
+ contact_id, capability, service_name, bananaman_status_str = sig.args
+ assertEquals(CAP_NAME, capability)
+ assertEquals('bananaman.on.holiday', service_name)
+ assertNotEquals('', bananaman_status_str)
+
+ # check property
+ discovered = status.Get(ycs.STATUS_IFACE, 'DiscoveredStatuses',
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ assertEquals({'test@localhost': {CAP_NAME: {
+ 'ants.in.their.pants': status_str,
+ 'bananaman.on.holiday': bananaman_status_str}}},
+ discovered)
+
+ # unset the status from one service
+ call_async(q, status, 'AdvertiseStatus', CAP_NAME,
+ 'ants.in.their.pants', '')
+
+ e, _, = q.expect_many(EventPattern('stream-iq'),
+ EventPattern('dbus-return', method='AdvertiseStatus'))
+
+ status_el, desc = check_pep_set(e.stanza)
+ assertEquals('ants.in.their.pants', status_el['from-service'])
+ assertEquals(CAP_NAME, status_el['capability'])
+ assert 'activity' not in status_el.attributes
+ assertEquals([], status_el.children)
+
+ acknowledge_iq(stream, e.stanza)
+ send_back_pep_event(stream, status_el)
+
+ sig = q.expect('dbus-signal', signal='StatusChanged',
+ interface=ycs.STATUS_IFACE)
+
+ # check signal
+ contact_id, capability, service_name, status_str = sig.args
+ assertEquals(CAP_NAME, capability)
+ assertEquals('ants.in.their.pants', service_name)
+ assertEquals('', status_str)
+
+ # check property
+ discovered = status.Get(ycs.STATUS_IFACE, 'DiscoveredStatuses',
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ assertEquals({'test@localhost': {CAP_NAME: {
+ 'bananaman.on.holiday': bananaman_status_str}}},
+ discovered)
+
+ # unset the status from the other service
+ call_async(q, status, 'AdvertiseStatus', CAP_NAME,
+ 'bananaman.on.holiday', '')
+
+ e, _ = q.expect_many(EventPattern('stream-iq'),
+ EventPattern('dbus-return', method='AdvertiseStatus'))
+
+ # check message
+ status_el, desc = check_pep_set(e.stanza)
+ assertEquals('bananaman.on.holiday', status_el['from-service'])
+ assertEquals(CAP_NAME, status_el['capability'])
+ assert 'activity' not in status_el.attributes
+ assertEquals([], status_el.children)
+
+ acknowledge_iq(stream, e.stanza)
+ send_back_pep_event(stream, status_el)
+
+ sig = q.expect('dbus-signal', signal='StatusChanged',
+ interface=ycs.STATUS_IFACE)
+
+ # check signal
+ contact_id, capability, service_name, status_str = sig.args
+ assertEquals(CAP_NAME, capability)
+ assertEquals('bananaman.on.holiday', service_name)
+ assertEquals('', status_str)
+
+ # check property
+ discovered = status.Get(ycs.STATUS_IFACE, 'DiscoveredStatuses',
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ assertEquals({}, discovered)
+
+if __name__ == '__main__':
+ exec_test(test, do_connect=False)
diff --git a/tests/twisted/gabble/success.py b/tests/twisted/gabble/success.py
deleted file mode 100644
index 13ff34c..0000000
--- a/tests/twisted/gabble/success.py
+++ /dev/null
@@ -1,19 +0,0 @@
-
-"""
-Test connecting to a server.
-"""
-
-from gabbletest import exec_test
-import gabbleconstants as cs
-
-def test(q, bus, conn, stream):
- conn.Connect()
- q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTING, cs.CSR_REQUESTED])
- q.expect('stream-authenticated')
- q.expect('dbus-signal', signal='PresenceUpdate',
- args=[{1L: (0L, {u'available': {}})}])
- q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])
-
-if __name__ == '__main__':
- exec_test(test, do_connect=False)
-