def make_caps_disco_reply(stream, req, identities, features, dataforms={}): iq = make_result_iq(stream, req) query = iq.firstChildElement() for identity in identities: category, type_, lang, name = identity.split('/') el = query.addElement('identity') el['category'] = category el['type'] = type_ el['name'] = name for f in features: el = domish.Element((None, 'feature')) el['var'] = f query.addChild(el) for type, fields in dataforms.iteritems(): x = query.addElement((ns.X_DATA, 'x')) x['type'] = 'result' field = x.addElement('field') field['var'] = 'FORM_TYPE' field['type'] = 'hidden' field.addElement('value', content=type) for var, values in fields.iteritems(): field = x.addElement('field') field['var'] = var for value in values: field.addElement('value', content=value) return iq
def receive_caps(q, bus, conn, service, contact, contact_handle, features, expected_caps, expect_disco=True, expect_ccc=True): ver = compute_caps_hash([], features, {}) txt_record = { "txtvers": "1", "status": "avail", "node": client, "ver": ver, "hash": "sha-1"} listener, port = setup_stream_listener(q, contact) AvahiAnnouncer(contact, "_presence._tcp", port, txt_record) if expect_disco: # Salut looks up our capabilities e = q.expect('incoming-connection', listener=listener) stream = e.connection event = q.expect('stream-iq', to=contact, query_ns=ns.DISCO_INFO, connection=stream) query_node = xpath.queryForNodes('/iq/query', event.stanza)[0] assert query_node.attributes['node'] == \ client + '#' + ver # send good reply result = make_result_iq(event.stanza) query = result.firstChildElement() query['node'] = client + '#' + ver for f in features: feature = query.addElement('feature') feature['var'] = f stream.send(result) if expect_ccc: event = q.expect('dbus-signal', signal='ContactCapabilitiesChanged') announced_ccs, = event.args assertSameElements(expected_caps, announced_ccs[contact_handle]) else: if expect_disco: # Make sure Salut's got the caps sync_stream(q, stream) # check the Contacts interface give the same caps caps_via_contacts_iface = conn.Contacts.GetContactAttributes( [contact_handle], [cs.CONN_IFACE_CONTACT_CAPS], False) \ [contact_handle][cs.ATTR_CONTACT_CAPABILITIES] assertSameElements(expected_caps, caps_via_contacts_iface) # close the connection and expect a new one to be opened by Salut # the next time we need some discoing doing if expect_disco: stream.send('</stream:stream>') stream.transport.loseConnection() # pass some time so Salut knows the connection is lost and # won't try and send stuff down a closed connection on the # next test. sync_dbus(bus, q, conn)
def outgoing_reply(q, bus, conn): path, incoming, stanza = setup_outgoing_tests(q, bus, conn) # reply with nothing reply = make_result_iq(stanza) incoming.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 make_caps_disco_reply(stream, req, identities, features, dataforms={}): iq = make_result_iq(req) query = iq.firstChildElement() for identity in identities: category, type_, lang, name = identity.split('/') el = query.addElement('identity') el['category'] = category el['type'] = type_ el['name'] = name for f in features: el = domish.Element((None, 'feature')) el['var'] = f query.addChild(el) add_dataforms(query, dataforms) return iq
def test(q, bus, conn): # 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 ver = compute_caps_hash([], [CAP_NAME + '+notify'], {}) txt_record = { "txtvers": "1", "status": "avail", "node": CLIENT_NAME, "ver": ver, "hash": "sha-1"} contact_name = "test-status@" + get_host_name() listener, port = setup_stream_listener(q, contact_name) announcer = AvahiAnnouncer(contact_name, "_presence._tcp", port, txt_record) handle = wait_for_contact_in_publish(q, bus, conn, contact_name) # this is the first presence, Salut connects to the contact e = q.expect('incoming-connection', listener=listener) incoming = e.connection # Salut looks up its capabilities event = q.expect('stream-iq', connection=incoming, query_ns=ns.DISCO_INFO) query_node = xpath.queryForNodes('/iq/query', event.stanza)[0] assertEquals(CLIENT_NAME + '#' + ver, query_node.attributes['node']) contact_handle = conn.RequestHandles(cs.HT_CONTACT, [contact_name])[0] # send good reply result = make_result_iq(event.stanza) query = result.firstChildElement() query['node'] = CLIENT_NAME + '#' + ver feature = query.addElement('feature') feature['var'] = CAP_NAME + '+notify' incoming.send(result) # 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, _, sig = q.expect_many(EventPattern('stream-message', connection=incoming), EventPattern('dbus-return', method='AdvertiseStatus'), EventPattern('dbus-signal', signal='StatusChanged', interface=ycs.STATUS_IFACE)) # check message message = e.stanza event = message.children[0] items = event.children[0] item = items.children[0] status_el = item.children[0] assertEquals('status', status_el.name) assertEquals('messing-with-your-stuff', status_el['activity']) assertEquals('ants.in.their.pants', status_el['from-service']) assertEquals(CAP_NAME, status_el['capability']) # 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({'testsuite@testsuite': {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, _, sig = q.expect_many(EventPattern('stream-message', connection=incoming), EventPattern('dbus-return', method='AdvertiseStatus'), EventPattern('dbus-signal', signal='StatusChanged', interface=ycs.STATUS_IFACE)) # check message message = e.stanza event = message.children[0] items = event.children[0] item = items.children[0] status_el = item.children[0] assertEquals('status', status_el.name) assertEquals('rofling', status_el['activity']) assertEquals('bananaman.on.holiday', status_el['from-service']) assertEquals(CAP_NAME, status_el['capability']) # 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({'testsuite@testsuite': {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, _, sig = q.expect_many(EventPattern('stream-message', connection=incoming), EventPattern('dbus-return', method='AdvertiseStatus'), EventPattern('dbus-signal', signal='StatusChanged', interface=ycs.STATUS_IFACE)) # check message message = e.stanza event = message.children[0] items = event.children[0] item = items.children[0] status_el = item.children[0] assertEquals('status', status_el.name) 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) # 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({'testsuite@testsuite': {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, _, sig = q.expect_many(EventPattern('stream-message', connection=incoming), EventPattern('dbus-return', method='AdvertiseStatus'), EventPattern('dbus-signal', signal='StatusChanged', interface=ycs.STATUS_IFACE)) # check message message = e.stanza event = message.children[0] items = event.children[0] item = items.children[0] status_el = item.children[0] assertEquals('status', status_el.name) 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) # 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)
def test(q, bus, conn): # 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 ver = compute_caps_hash([], [CAP_NAME + '+notify'], {}) txt_record = { "txtvers": "1", "status": "avail", "node": CLIENT_NAME, "ver": ver, "hash": "sha-1" } contact_name = "test-status@" + get_host_name() listener, port = setup_stream_listener(q, contact_name) announcer = AvahiAnnouncer(contact_name, "_presence._tcp", port, txt_record) handle = wait_for_contact_in_publish(q, bus, conn, contact_name) # this is the first presence, Salut connects to the contact e = q.expect('incoming-connection', listener=listener) incoming = e.connection # Salut looks up its capabilities event = q.expect('stream-iq', connection=incoming, query_ns=ns.DISCO_INFO) query_node = xpath.queryForNodes('/iq/query', event.stanza)[0] assertEquals(CLIENT_NAME + '#' + ver, query_node.attributes['node']) contact_handle = conn.RequestHandles(cs.HT_CONTACT, [contact_name])[0] # send good reply result = make_result_iq(event.stanza) query = result.firstChildElement() query['node'] = CLIENT_NAME + '#' + ver feature = query.addElement('feature') feature['var'] = CAP_NAME + '+notify' incoming.send(result) # 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, _, sig = q.expect_many( EventPattern('stream-message', connection=incoming), EventPattern('dbus-return', method='AdvertiseStatus'), EventPattern('dbus-signal', signal='StatusChanged', interface=ycs.STATUS_IFACE)) # check message message = e.stanza event = message.children[0] items = event.children[0] item = items.children[0] status_el = item.children[0] assertEquals('status', status_el.name) assertEquals('messing-with-your-stuff', status_el['activity']) assertEquals('ants.in.their.pants', status_el['from-service']) assertEquals(CAP_NAME, status_el['capability']) # 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( { 'testsuite@testsuite': { 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, _, sig = q.expect_many( EventPattern('stream-message', connection=incoming), EventPattern('dbus-return', method='AdvertiseStatus'), EventPattern('dbus-signal', signal='StatusChanged', interface=ycs.STATUS_IFACE)) # check message message = e.stanza event = message.children[0] items = event.children[0] item = items.children[0] status_el = item.children[0] assertEquals('status', status_el.name) assertEquals('rofling', status_el['activity']) assertEquals('bananaman.on.holiday', status_el['from-service']) assertEquals(CAP_NAME, status_el['capability']) # 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( { 'testsuite@testsuite': { 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, _, sig = q.expect_many( EventPattern('stream-message', connection=incoming), EventPattern('dbus-return', method='AdvertiseStatus'), EventPattern('dbus-signal', signal='StatusChanged', interface=ycs.STATUS_IFACE)) # check message message = e.stanza event = message.children[0] items = event.children[0] item = items.children[0] status_el = item.children[0] assertEquals('status', status_el.name) 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) # 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( { 'testsuite@testsuite': { 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, _, sig = q.expect_many( EventPattern('stream-message', connection=incoming), EventPattern('dbus-return', method='AdvertiseStatus'), EventPattern('dbus-signal', signal='StatusChanged', interface=ycs.STATUS_IFACE)) # check message message = e.stanza event = message.children[0] items = event.children[0] item = items.children[0] status_el = item.children[0] assertEquals('status', status_el.name) 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) # 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)
def test(q, bus, conn): forbidden = [EventPattern('dbus-signal', signal='ServiceAdded'), EventPattern('dbus-signal', signal='ServiceRemoved')] q.forbid_events(forbidden) conn.Connect() q.expect('dbus-signal', signal='StatusChanged', args=[0, 0]) # announce a contact with the right caps ver = compute_caps_hash([], [], banshee) txt_record = { "txtvers": "1", "status": "avail", "node": CLIENT_NAME, "ver": ver, "hash": "sha-1"} contact_name = "test-service@" + get_host_name() listener, port = setup_stream_listener(q, contact_name) announcer = AvahiAnnouncer(contact_name, "_presence._tcp", port, txt_record) handle = wait_for_contact_in_publish(q, bus, conn, contact_name) # this is the first presence, Salut connects to the contact e = q.expect('incoming-connection', listener=listener) incoming = e.connection # Salut looks up its capabilities event = q.expect('stream-iq', connection=incoming, query_ns=ns.DISCO_INFO) query_node = xpath.queryForNodes('/iq/query', event.stanza)[0] assertEquals(CLIENT_NAME + '#' + ver, query_node.attributes['node']) contact_handle = conn.RequestHandles(cs.HT_CONTACT, [contact_name])[0] # send good reply result = make_result_iq(event.stanza) query = result.firstChildElement() query['node'] = CLIENT_NAME + '#' + ver x = query.addElement((ns.X_DATA, 'x')) x['type'] = 'result' # FORM_TYPE field = x.addElement((None, 'field')) field['var'] = 'FORM_TYPE' field['type'] = 'hidden' field.addElement((None, 'value'), content='urn:ytstenut:capabilities#org.gnome.Banshee') # type field = x.addElement((None, 'field')) field['var'] = 'type' field.addElement((None, 'value'), content='application') # name field = x.addElement((None, 'field')) field['var'] = 'name' field.addElement((None, 'value'), content='en_GB/Banshee Media Player') field.addElement((None, 'value'), content='fr/Banshee Lecteur de Musique') # capabilities field = x.addElement((None, 'field')) field['var'] = 'capabilities' field.addElement((None, 'value'), content='urn:ytstenut:capabilities:yts-caps-audio') field.addElement((None, 'value'), content='urn:ytstenut:data:jingle:rtp') incoming.send(result) # 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]) # add evince tmp = banshee.copy() tmp.update(evince) ver = compute_caps_hash([], [], tmp) txt_record['ver'] = ver announcer.update(txt_record) # Salut looks up our capabilities event = q.expect('stream-iq', connection=incoming, query_ns='http://jabber.org/protocol/disco#info') query_node = xpath.queryForNodes('/iq/query', event.stanza)[0] assert query_node.attributes['node'] == \ CLIENT_NAME + '#' + txt_record['ver'] # send good reply result['id'] = event.stanza['id'] query['node'] = CLIENT_NAME + '#' + ver x = query.addElement((ns.X_DATA, 'x')) x['type'] = 'result' # FORM_TYPE field = x.addElement((None, 'field')) field['var'] = 'FORM_TYPE' field['type'] = 'hidden' field.addElement((None, 'value'), content='urn:ytstenut:capabilities#org.gnome.Evince') # type field = x.addElement((None, 'field')) field['var'] = 'type' field.addElement((None, 'value'), content='application') # name field = x.addElement((None, 'field')) field['var'] = 'name' field.addElement((None, 'value'), content='en_GB/Evince Picture Viewer') field.addElement((None, 'value'), content='fr/Evince uh, ow do you say') # capabilities field = x.addElement((None, 'field')) field['var'] = 'capabilities' field.addElement((None, 'value'), content='urn:ytstenut:capabilities:pics') incoming.send(result) # 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]) # now finally ensure the sidecar path, props = conn.Future.EnsureSidecar(ycs.STATUS_IFACE) 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({contact_name: { '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)
def test_ft_caps_from_contact(q, bus, conn, client): conn_caps_iface = dbus.Interface(conn, cs.CONN_IFACE_CONTACT_CAPS) conn_contacts_iface = dbus.Interface(conn, cs.CONN_IFACE_CONTACTS) # send presence with FT capa ver = compute_caps_hash([], [ns.IQ_OOB], {}) txt_record = { "txtvers": "1", "status": "avail", "node": client, "ver": ver, "hash": "sha-1" } contact_name = "test-caps-ft@" + get_host_name() listener, port = setup_stream_listener(q, contact_name) announcer = AvahiAnnouncer(contact_name, "_presence._tcp", port, txt_record) # this is the first presence, Salut connects to the contact e = q.expect('incoming-connection', listener=listener) incoming = e.connection # Salut looks up our capabilities event = q.expect('stream-iq', connection=incoming, query_ns='http://jabber.org/protocol/disco#info') query_node = xpath.queryForNodes('/iq/query', event.stanza)[0] assert query_node.attributes['node'] == \ client + '#' + ver, (query_node.attributes['node'], client, ver) contact_handle = conn_contacts_iface.GetContactByID(contact_name, [])[0] # send good reply result = make_result_iq(event.stanza) query = result.firstChildElement() query['node'] = client + '#' + ver feature = query.addElement('feature') feature['var'] = ns.IQ_OOB incoming.send(result) # FT capa is announced e = q.expect('dbus-signal', signal='ContactCapabilitiesChanged', predicate=lambda e: contact_handle in e.args[0]) caps = e.args[0][contact_handle] assertContains(ft_caps, caps) # check the Contacts interface give the same caps caps_via_contacts_iface = conn_contacts_iface.GetContactAttributes( [contact_handle], [cs.CONN_IFACE_CONTACT_CAPS], False) \ [contact_handle][cs.CONN_IFACE_CONTACT_CAPS + '/capabilities'] assert caps_via_contacts_iface == caps, caps_via_contacts_iface # check if Salut announces the OOB capa self_handle = conn.Properties.Get(cs.CONN, "SelfHandle") self_handle_name = conn.Properties.Get(cs.CONN, "SelfID") AvahiListener(q).listen_for_service("_presence._tcp") e = q.expect('service-added', name=self_handle_name, protocol=avahi.PROTO_INET) service = e.service service.resolve() receive_presence_and_ask_caps(q, incoming, service, contact_name) # capa announced without FT ver = compute_caps_hash([], ["http://telepathy.freedesktop.org/xmpp/pony"], {}) txt_record = { "txtvers": "1", "status": "avail", "node": client, "ver": ver, "hash": "sha-1" } contact_name = "test-caps-ft2@" + get_host_name() listener, port = setup_stream_listener(q, contact_name) announcer = AvahiAnnouncer(contact_name, "_presence._tcp", port, txt_record) # this is the first presence, Salut connects to the contact e = q.expect('incoming-connection', listener=listener) incoming = e.connection # Salut looks up our capabilities event = q.expect('stream-iq', connection=incoming, query_ns='http://jabber.org/protocol/disco#info') query_node = xpath.queryForNodes('/iq/query', event.stanza)[0] assert query_node.attributes['node'] == \ client + '#' + ver, (query_node.attributes['node'], client, ver) contact_handle = conn_contacts_iface.GetContactByID(contact_name, [])[0] # send good reply result = make_result_iq(event.stanza) query = result.firstChildElement() query['node'] = client + '#' + ver feature = query.addElement('feature') feature['var'] = "http://telepathy.freedesktop.org/xmpp/pony" incoming.send(result) # the FT capability is not announced e = q.expect('dbus-signal', signal='ContactCapabilitiesChanged') caps = e.args[0][contact_handle] assertDoesNotContain(ft_caps, caps) # check the Contacts interface give the same caps caps_via_contacts_iface = conn_contacts_iface.GetContactAttributes( [contact_handle], [cs.CONN_IFACE_CONTACT_CAPS], False) \ [contact_handle][cs.CONN_IFACE_CONTACT_CAPS + '/capabilities'] assert caps_via_contacts_iface == caps, caps_via_contacts_iface # no capabilites announced (assume FT is supported to insure interop) txt_record = {"txtvers": "1", "status": "avail"} contact_name = "test-caps-ft-no-capa2@" + get_host_name() contact_handle = conn_contacts_iface.GetContactByID(contact_name, [])[0] listener, port = setup_stream_listener(q, contact_name) announcer = AvahiAnnouncer(contact_name, "_presence._tcp", port, txt_record) # FT capa is announced e = q.expect('dbus-signal', signal='ContactCapabilitiesChanged', predicate=lambda e: contact_handle in e.args[0].keys()) caps = e.args[0][contact_handle] assertContains(ft_caps, caps) # check the Contacts interface give the same caps caps_via_contacts_iface = conn_contacts_iface.GetContactAttributes( [contact_handle], [cs.CONN_IFACE_CONTACT_CAPS], False) \ [contact_handle][cs.CONN_IFACE_CONTACT_CAPS + '/capabilities'] assert caps_via_contacts_iface == caps, caps_via_contacts_iface
def test(q, bus, conn): 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 ver = compute_caps_hash([], [], banshee) txt_record = { "txtvers": "1", "status": "avail", "node": CLIENT_NAME, "ver": ver, "hash": "sha-1" } contact_name = "test-service@" + get_host_name() listener, port = setup_stream_listener(q, contact_name) announcer = AvahiAnnouncer(contact_name, "_presence._tcp", port, txt_record) handle = wait_for_contact_in_publish(q, bus, conn, contact_name) # this is the first presence, Salut connects to the contact e = q.expect('incoming-connection', listener=listener) incoming = e.connection # Salut looks up its capabilities event = q.expect('stream-iq', connection=incoming, query_ns=ns.DISCO_INFO) query_node = xpath.queryForNodes('/iq/query', event.stanza)[0] assertEquals(CLIENT_NAME + '#' + ver, query_node.attributes['node']) contact_handle = conn.RequestHandles(cs.HT_CONTACT, [contact_name])[0] # send good reply result = make_result_iq(event.stanza) query = result.firstChildElement() query['node'] = CLIENT_NAME + '#' + ver x = query.addElement((ns.X_DATA, 'x')) x['type'] = 'result' # FORM_TYPE field = x.addElement((None, 'field')) field['var'] = 'FORM_TYPE' field['type'] = 'hidden' field.addElement((None, 'value'), content='urn:ytstenut:capabilities#org.gnome.Banshee') # type field = x.addElement((None, 'field')) field['var'] = 'type' field.addElement((None, 'value'), content='application') # name field = x.addElement((None, 'field')) field['var'] = 'name' field.addElement((None, 'value'), content='en_GB/Banshee Media Player') field.addElement((None, 'value'), content='fr/Banshee Lecteur de Musique') # capabilities field = x.addElement((None, 'field')) field['var'] = 'capabilities' field.addElement((None, 'value'), content='urn:ytstenut:capabilities:yts-caps-audio') field.addElement((None, 'value'), content='urn:ytstenut:data:jingle:rtp') incoming.send(result) # 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(contact_name, 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( { contact_name: { '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) ver = compute_caps_hash([], [], tmp) txt_record['ver'] = ver announcer.update(txt_record) # Salut looks up our capabilities event = q.expect('stream-iq', connection=incoming, query_ns='http://jabber.org/protocol/disco#info') query_node = xpath.queryForNodes('/iq/query', event.stanza)[0] assert query_node.attributes['node'] == \ CLIENT_NAME + '#' + txt_record['ver'] # send good reply result['id'] = event.stanza['id'] query['node'] = CLIENT_NAME + '#' + ver x = query.addElement((ns.X_DATA, 'x')) x['type'] = 'result' # FORM_TYPE field = x.addElement((None, 'field')) field['var'] = 'FORM_TYPE' field['type'] = 'hidden' field.addElement((None, 'value'), content='urn:ytstenut:capabilities#org.gnome.Evince') # type field = x.addElement((None, 'field')) field['var'] = 'type' field.addElement((None, 'value'), content='application') # name field = x.addElement((None, 'field')) field['var'] = 'name' field.addElement((None, 'value'), content='en_GB/Evince Picture Viewer') field.addElement((None, 'value'), content='fr/Evince uh, ow do you say') # capabilities field = x.addElement((None, 'field')) field['var'] = 'capabilities' field.addElement((None, 'value'), content='urn:ytstenut:capabilities:pics') incoming.send(result) e = q.expect('dbus-signal', signal='ServiceAdded') contact_id, service_name, details = e.args assertEquals(contact_name, 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( { contact_name: { '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 ver = compute_caps_hash([], [], banshee) txt_record['ver'] = ver forbidden = [ EventPattern('dbus-signal', signal='stream-iq', connection=incoming) ] q.forbid_events(forbidden) announcer.update(txt_record) e = q.expect('dbus-signal', signal='ServiceRemoved') contact_id, service_name = e.args assertEquals(contact_name, contact_id) assertEquals('org.gnome.Evince', service_name) discovered = status.Get(ycs.STATUS_IFACE, 'DiscoveredServices', dbus_interface=dbus.PROPERTIES_IFACE) assertEquals( { contact_name: { '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, incoming) q.unforbid_events(forbidden) # now just evince ver = compute_caps_hash([], [], evince) txt_record['ver'] = ver announcer.update(txt_record) # Salut looks up our capabilities event = q.expect('stream-iq', connection=incoming, query_ns='http://jabber.org/protocol/disco#info') query_node = xpath.queryForNodes('/iq/query', event.stanza)[0] assert query_node.attributes['node'] == \ CLIENT_NAME + '#' + txt_record['ver'] # send good reply result = make_result_iq(event.stanza) query = result.firstChildElement() query['node'] = CLIENT_NAME + '#' + ver x = query.addElement((ns.X_DATA, 'x')) x['type'] = 'result' # FORM_TYPE field = x.addElement((None, 'field')) field['var'] = 'FORM_TYPE' field['type'] = 'hidden' field.addElement((None, 'value'), content='urn:ytstenut:capabilities#org.gnome.Evince') # type field = x.addElement((None, 'field')) field['var'] = 'type' field.addElement((None, 'value'), content='application') # name field = x.addElement((None, 'field')) field['var'] = 'name' field.addElement((None, 'value'), content='en_GB/Evince Picture Viewer') field.addElement((None, 'value'), content='fr/Evince uh, ow do you say') # capabilities field = x.addElement((None, 'field')) field['var'] = 'capabilities' field.addElement((None, 'value'), content='urn:ytstenut:capabilities:pics') incoming.send(result) sa, sr = q.expect_many( EventPattern('dbus-signal', signal='ServiceAdded'), EventPattern('dbus-signal', signal='ServiceRemoved')) contact_id, service_name, details = sa.args assertEquals(contact_name, 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(contact_name, contact_id) assertEquals('org.gnome.Banshee', service_name) discovered = status.Get(ycs.STATUS_IFACE, 'DiscoveredServices', dbus_interface=dbus.PROPERTIES_IFACE) assertEquals( { contact_name: { 'org.gnome.Evince': ('application', { 'en_GB': 'Evince Picture Viewer', 'fr': 'Evince uh, ow do you say' }, ['urn:ytstenut:capabilities:pics']) } }, discovered) # just banshee again ver = compute_caps_hash([], [], banshee) txt_record['ver'] = ver forbidden = [ EventPattern('dbus-signal', signal='stream-iq', connection=incoming) ] q.forbid_events(forbidden) announcer.update(txt_record) sr, sa = q.expect_many( EventPattern('dbus-signal', signal='ServiceRemoved'), EventPattern('dbus-signal', signal='ServiceAdded')) contact_id, service_name = sr.args assertEquals(contact_name, contact_id) assertEquals('org.gnome.Evince', service_name) contact_id, service_name, details = sa.args assertEquals(contact_name, 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( { contact_name: { '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, incoming) q.unforbid_events(forbidden) # both again ver = compute_caps_hash([], [], tmp) txt_record['ver'] = ver announcer.update(txt_record) sa = q.expect('dbus-signal', signal='ServiceAdded') contact_id, service_name, details = sa.args assertEquals(contact_name, 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( { contact_name: { '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, incoming) # and finally, nothing ver = compute_caps_hash([], [], {}) txt_record['ver'] = ver announcer.update(txt_record) # Salut looks up our capabilities event = q.expect('stream-iq', connection=incoming, query_ns='http://jabber.org/protocol/disco#info') query_node = xpath.queryForNodes('/iq/query', event.stanza)[0] assert query_node.attributes['node'] == \ CLIENT_NAME + '#' + txt_record['ver'] # send good reply result = make_result_iq(event.stanza) query = result.firstChildElement() query['node'] = CLIENT_NAME + '#' + ver incoming.send(result) q.expect_many( EventPattern('dbus-signal', signal='ServiceRemoved', args=[contact_name, 'org.gnome.Banshee']), EventPattern('dbus-signal', signal='ServiceRemoved', args=[contact_name, 'org.gnome.Evince'])) discovered = status.Get(ycs.STATUS_IFACE, 'DiscoveredServices', dbus_interface=dbus.PROPERTIES_IFACE) assertEquals({}, discovered)
def test_ft_caps_from_contact(q, bus, conn, client): conn_caps_iface = dbus.Interface(conn, cs.CONN_IFACE_CONTACT_CAPS) conn_contacts_iface = dbus.Interface(conn, cs.CONN_IFACE_CONTACTS) # send presence with FT capa ver = compute_caps_hash([], [ns.IQ_OOB], {}) txt_record = { "txtvers": "1", "status": "avail", "node": client, "ver": ver, "hash": "sha-1"} contact_name = "test-caps-ft@" + get_host_name() listener, port = setup_stream_listener(q, contact_name) announcer = AvahiAnnouncer(contact_name, "_presence._tcp", port, txt_record) # this is the first presence, Salut connects to the contact e = q.expect('incoming-connection', listener = listener) incoming = e.connection # Salut looks up our capabilities event = q.expect('stream-iq', connection = incoming, query_ns='http://jabber.org/protocol/disco#info') query_node = xpath.queryForNodes('/iq/query', event.stanza)[0] assert query_node.attributes['node'] == \ client + '#' + ver, (query_node.attributes['node'], client, ver) contact_handle = conn_contacts_iface.GetContactByID(contact_name, [])[0] # send good reply result = make_result_iq(event.stanza) query = result.firstChildElement() query['node'] = client + '#' + ver feature = query.addElement('feature') feature['var'] = ns.IQ_OOB incoming.send(result) # FT capa is announced e = q.expect('dbus-signal', signal='ContactCapabilitiesChanged', predicate=lambda e: contact_handle in e.args[0]) caps = e.args[0][contact_handle] assertContains(ft_caps, caps) # check the Contacts interface give the same caps caps_via_contacts_iface = conn_contacts_iface.GetContactAttributes( [contact_handle], [cs.CONN_IFACE_CONTACT_CAPS], False) \ [contact_handle][cs.CONN_IFACE_CONTACT_CAPS + '/capabilities'] assert caps_via_contacts_iface == caps, caps_via_contacts_iface # check if Salut announces the OOB capa self_handle = conn.Properties.Get(cs.CONN, "SelfHandle") self_handle_name = conn.Properties.Get(cs.CONN, "SelfID") AvahiListener(q).listen_for_service("_presence._tcp") e = q.expect('service-added', name = self_handle_name, protocol = avahi.PROTO_INET) service = e.service service.resolve() receive_presence_and_ask_caps(q, incoming, service, contact_name) # capa announced without FT ver = compute_caps_hash([], ["http://telepathy.freedesktop.org/xmpp/pony"], {}) txt_record = { "txtvers": "1", "status": "avail", "node": client, "ver": ver, "hash": "sha-1"} contact_name = "test-caps-ft2@" + get_host_name() listener, port = setup_stream_listener(q, contact_name) announcer = AvahiAnnouncer(contact_name, "_presence._tcp", port, txt_record) # this is the first presence, Salut connects to the contact e = q.expect('incoming-connection', listener = listener) incoming = e.connection # Salut looks up our capabilities event = q.expect('stream-iq', connection = incoming, query_ns='http://jabber.org/protocol/disco#info') query_node = xpath.queryForNodes('/iq/query', event.stanza)[0] assert query_node.attributes['node'] == \ client + '#' + ver, (query_node.attributes['node'], client, ver) contact_handle = conn_contacts_iface.GetContactByID(contact_name, [])[0] # send good reply result = make_result_iq(event.stanza) query = result.firstChildElement() query['node'] = client + '#' + ver feature = query.addElement('feature') feature['var'] = "http://telepathy.freedesktop.org/xmpp/pony" incoming.send(result) # the FT capability is not announced e = q.expect('dbus-signal', signal='ContactCapabilitiesChanged') caps = e.args[0][contact_handle] assertDoesNotContain(ft_caps, caps) # check the Contacts interface give the same caps caps_via_contacts_iface = conn_contacts_iface.GetContactAttributes( [contact_handle], [cs.CONN_IFACE_CONTACT_CAPS], False) \ [contact_handle][cs.CONN_IFACE_CONTACT_CAPS + '/capabilities'] assert caps_via_contacts_iface == caps, caps_via_contacts_iface # no capabilites announced (assume FT is supported to insure interop) txt_record = { "txtvers": "1", "status": "avail"} contact_name = "test-caps-ft-no-capa2@" + get_host_name() contact_handle = conn_contacts_iface.GetContactByID(contact_name, [])[0] listener, port = setup_stream_listener(q, contact_name) announcer = AvahiAnnouncer(contact_name, "_presence._tcp", port, txt_record) # FT capa is announced e = q.expect('dbus-signal', signal='ContactCapabilitiesChanged', predicate=lambda e: contact_handle in e.args[0].keys()) caps = e.args[0][contact_handle] assertContains(ft_caps, caps) # check the Contacts interface give the same caps caps_via_contacts_iface = conn_contacts_iface.GetContactAttributes( [contact_handle], [cs.CONN_IFACE_CONTACT_CAPS], False) \ [contact_handle][cs.CONN_IFACE_CONTACT_CAPS + '/capabilities'] assert caps_via_contacts_iface == caps, caps_via_contacts_iface
def receive_caps(q, bus, conn, service, contact, contact_handle, features, expected_caps, expect_disco=True, expect_ccc=True): ver = compute_caps_hash([], features, {}) txt_record = { "txtvers": "1", "status": "avail", "node": client, "ver": ver, "hash": "sha-1" } listener, port = setup_stream_listener(q, contact) AvahiAnnouncer(contact, "_presence._tcp", port, txt_record) if expect_disco: # Salut looks up our capabilities e = q.expect('incoming-connection', listener=listener) stream = e.connection event = q.expect('stream-iq', to=contact, query_ns=ns.DISCO_INFO, connection=stream) query_node = xpath.queryForNodes('/iq/query', event.stanza)[0] assert query_node.attributes['node'] == \ client + '#' + ver # send good reply result = make_result_iq(event.stanza) query = result.firstChildElement() query['node'] = client + '#' + ver for f in features: feature = query.addElement('feature') feature['var'] = f stream.send(result) if expect_ccc: event = q.expect('dbus-signal', signal='ContactCapabilitiesChanged') announced_ccs, = event.args assertSameElements(expected_caps, announced_ccs[contact_handle]) else: if expect_disco: # Make sure Salut's got the caps sync_stream(q, stream) # check the Contacts interface give the same caps caps_via_contacts_iface = conn.Contacts.GetContactAttributes( [contact_handle], [cs.CONN_IFACE_CONTACT_CAPS], False) \ [contact_handle][cs.ATTR_CONTACT_CAPABILITIES] assertSameElements(expected_caps, caps_via_contacts_iface) # close the connection and expect a new one to be opened by Salut # the next time we need some discoing doing if expect_disco: stream.send('</stream:stream>') stream.transport.loseConnection() # pass some time so Salut knows the connection is lost and # won't try and send stuff down a closed connection on the # next test. sync_dbus(bus, q, conn)