def test_invisible_on_connect(q, bus, conn, stream): props = conn.Properties.GetAll(cs.CONN_IFACE_SIMPLE_PRESENCE) assertNotEquals({}, props['Statuses']) presence_event_pattern = EventPattern('stream-presence') q.forbid_events([presence_event_pattern]) conn.SimplePresence.SetPresence("hidden", "") conn.Connect() stream.handle_get_all_privacy_lists(q, bus, conn, ['invisible']) get_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='get') list_node = xpath.queryForNodes('//list', get_list.query)[0] assertEquals('invisible', list_node['name']) stream.send_privacy_list( get_list.stanza, [elem('item', action='deny', order='1')(elem('presence-out'))]) set_active = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set') active = xpath.queryForNodes('//active', set_active.query)[0] assertEquals('invisible', active['name']) acknowledge_iq(stream, set_active.stanza) q.unforbid_events([presence_event_pattern]) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])
def test_success(q, bus, conn, stream): iq = connect_and_send_form(q, conn, stream) acknowledge_iq(stream, iq) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])
def test(q, bus, conn, stream): event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, event.stanza) handle = conn.get_contact_handle_sync('*****@*****.**') call_async(q, conn.Aliasing, 'RequestAliases', [handle]) # Nack PEP query. event = q.expect('stream-iq', to='*****@*****.**', iq_type='get', query_ns='http://jabber.org/protocol/pubsub', query_name='pubsub') items = event.query.firstChildElement() assert items.name == 'items' assert items['node'] == "http://jabber.org/protocol/nick" result = make_result_iq(stream, event.stanza) result['type'] = 'error' error = result.addElement('error') error['type'] = 'auth' error.addElement('forbidden', 'urn:ietf:params:xml:ns:xmpp-stanzas') stream.send(result) event = q.expect('stream-iq', to='*****@*****.**', query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, event.stanza) q.expect('dbus-return', method='RequestAliases', value=([u'*****@*****.**'],)) # A second request should be satisfied from the cache. assert conn.Aliasing.RequestAliases([handle]) == ['*****@*****.**']
def test(q, bus, conn, stream): conn.Connect() _, iq_event = q.expect_many( EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]), EventPattern('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard')) acknowledge_iq(stream, iq_event.stanza) handle = conn.RequestHandles(1, ['*****@*****.**'])[0] conn.Avatars.RequestAvatars([handle]) conn.Avatars.RequestAvatars([handle]) conn.Avatars.RequestAvatars([handle]) conn.Avatars.RequestAvatars([handle]) iq_event = q.expect('stream-iq', to='*****@*****.**', query_ns='vcard-temp', query_name='vCard') iq = make_result_iq(stream, iq_event.stanza) vcard = iq.firstChildElement() photo = vcard.addElement('PHOTO') photo.addElement('TYPE', content='image/png') photo.addElement('BINVAL', content=base64.b64encode('hello')) stream.send(iq) event = q.expect('dbus-signal', signal='AvatarRetrieved') q.forbid_events([EventPattern('dbus-signal', signal='AvatarRetrieved')])
def test_create_invisible_list(q, bus, conn, stream): conn.SimplePresence.SetPresence("away", "") conn.Connect() stream.handle_get_all_privacy_lists(q, bus, conn) get_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='get') list_node = xpath.queryForNodes('//list', get_list.query)[0] assertEquals('invisible', list_node['name']) error = domish.Element((None, 'error')) error['type'] = 'cancel' error.addElement((ns.STANZA, 'item-not-found')) send_error_reply(stream, get_list.stanza, error) create_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set') list_node = xpath.queryForNodes('//list', create_list.query)[0] assertEquals('invisible', list_node['name']) assertNotEquals([], xpath.queryForNodes('/query/list/item/presence-out', create_list.query)) acknowledge_iq(stream, create_list.stanza) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) assertContains( "hidden", conn.Properties.Get(cs.CONN_IFACE_SIMPLE_PRESENCE, "Statuses"))
def test(q, bus, conn, stream): self_handle = conn.GetSelfHandle() conn.Aliasing.SetAliases({self_handle: 'lala'}) expect_and_handle_get_vcard(q, stream) pep_update = q.expect('stream-iq', iq_type='set', query_ns=ns.PUBSUB, query_name='pubsub') validate_pep_update(pep_update, 'lala') acknowledge_iq(stream, pep_update.stanza) def check(vCard): nickname = vCard.elements(uri=ns.VCARD_TEMP, name='NICKNAME').next() assertEquals('lala', nickname.children[0]) expect_and_handle_set_vcard(q, stream, check=check) event = q.expect('dbus-signal', signal='AliasesChanged', args=[[(self_handle, u'lala')]]) conn.Aliasing.SetAliases({self_handle: ''}) pep_update = q.expect('stream-iq', iq_type='set', query_ns=ns.PUBSUB, query_name='pubsub') validate_pep_update(pep_update, None) expect_and_handle_get_vcard(q, stream) def check(vCard): # The vCard should be empty, rather than having an empty <NICKNAME/> # element. assertLength(0, vCard.children) expect_and_handle_set_vcard(q, stream, check=check) event = q.expect('dbus-signal', signal='AliasesChanged', args=[[(self_handle, u'test@localhost')]])
def test_privacy_list_push_conflict(q, bus, conn, stream): test_invisible_on_connect(q, bus, conn, stream) set_id = stream.send_privacy_list_push_iq("invisible") _, req_list = q.expect_many( EventPattern('stream-iq', iq_type='result', iq_id=set_id), EventPattern('stream-iq', query_ns=ns.PRIVACY, iq_type="get")) stream.send_privacy_list(req_list.stanza, [ elem('item', type='jid', value='*****@*****.**', action='allow', order='1')(elem('presence-out')), elem('item', action='deny', order='2')(elem('presence-out')) ]) create_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set') created = xpath.queryForNodes('//list', create_list.stanza)[0] assertEquals(created["name"], 'invisible-gabble') acknowledge_iq(stream, create_list.stanza) set_active = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set') active = xpath.queryForNodes('//active', set_active.query)[0] assertEquals('invisible-gabble', active['name']) acknowledge_iq(stream, set_active.stanza)
def test(q, bus, conn, stream): # This sidecar sends a stanza, and waits for a reply, before being # created. pattern = EventPattern('stream-iq', to='sidecar.example.com', query_ns='http://example.com/sidecar') call_async(q, conn.Sidecars1, 'EnsureSidecar', TEST_PLUGIN_IFACE + ".IQ") e = q.expect_many(pattern)[0] # The server said yes, so we should get a sidecar back! acknowledge_iq(stream, e.stanza) q.expect('dbus-return', method='EnsureSidecar') identities = ["test/app-list//Test"] features = ["com.example.test1", "com.example.test2"] ver = compute_caps_hash(identities, features, {}) iq = IQ(stream, "get") query = iq.addElement((ns.DISCO_INFO, 'query')) query['node'] = ns.GABBLE_CAPS + '#' + ver stream.send(iq) e = q.expect('stream-iq', query_ns='http://jabber.org/protocol/disco#info') returned_features = [feature['var'] for feature in xpath.queryForNodes('/iq/query/feature', e.stanza)] assertEquals(features, returned_features) returned_identities = [identity['category'] + "/" + identity['type']+"//" + identity['name'] for identity in xpath.queryForNodes('/iq/query/identity', e.stanza)] assertEquals(identities, returned_identities) new_ver = compute_caps_hash(returned_identities, returned_features, {}) assertEquals(new_ver, ver)
def test_with_xep0186(q, bus, conn, stream): statuses = conn.Properties.Get(cs.CONN_IFACE_SIMPLE_PRESENCE, 'Statuses') # testbusy and testaway are provided by test plugin assertContains('testbusy', statuses) assertContains('testaway', statuses) assertEquals(statuses['testbusy'][0], cs.PRESENCE_BUSY) assertEquals(statuses['testaway'][0], cs.PRESENCE_AWAY) conn.SimplePresence.SetPresence('testbusy', '') conn.Connect() # ... gabble asks for all the available lists on the server ... stream.handle_get_all_privacy_lists( q, bus, conn, lists=["foo-list", "test-busy-list", "bar-list"]) get_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set') list_node = xpath.queryForNodes('//active', get_list.query)[0] # ... and then activates the one linked with the requested status # Note: testbusy status is linked to test-busy-list by test plugin assertEquals('test-busy-list', list_node['name']) acknowledge_iq(stream, get_list.stanza) q.expect('dbus-signal', signal='PresencesChanged', args=[{ 1L: (cs.PRESENCE_BUSY, u'testbusy', '') }])
def test(q, bus, conn, stream): event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, event.stanza) handle = conn.get_contact_handle_sync('*****@*****.**') call_async(q, conn.Aliasing, 'RequestAliases', [handle]) # First, Gabble sends a PEP query event = q.expect('stream-iq', to='*****@*****.**', iq_type='get', query_ns='http://jabber.org/protocol/pubsub', query_name='pubsub') # We disconnect too soon to get a reply disconnect_conn(q, conn, stream) # fd.o #31412 was that while the request pipeline was shutting down, # it would give the PEP query an error; the aliasing code would # respond by falling back to vCard via the request pipeline, which # was no longer there, *crash*. # check that Gabble hasn't crashed sync_dbus(bus, q, conn)
def test(q, bus, conn, stream): event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, event.stanza) # Force Gabble to process the vCard before calling any methods. sync_stream(q, stream) # Request our alias and avatar, expect them to be resolved from cache. handle = conn.Properties.Get(cs.CONN, "SelfHandle") call_async(q, conn.Avatars, 'RequestAvatars', [handle]) call_async(q, conn.Aliasing, 'RequestAliases', [handle]) # FIXME - find out why RequestAliases returns before RequestAvatar even # though everything's cached. Probably due to queueing, which means # conn-avatars don't look into the cache before making a request. Prolly # should make vcard_request look into the cache itself, and return # immediately. Or not, if it's g_idle()'d. So it's better if conn-aliasing # look into the cache itself. r1, r2 = q.expect_many( EventPattern('dbus-return', method='RequestAliases'), EventPattern('dbus-return', method='RequestAvatars')) # Default alias is our jid assert r1.value[0] == ['test@localhost']
def test(q, bus, conn, stream): conn.Connect() def send_roster_iq(stream, jid, subscription): iq = IQ(stream, "set") iq['id'] = 'push' query = iq.addElement('query') query['xmlns'] = ns.ROSTER item = query.addElement('item') item['jid'] = jid item['subscription'] = subscription stream.send(iq) event = q.expect('stream-iq', query_ns=ns.ROSTER) event.stanza['type'] = 'result' item = event.query.addElement('item') item['jid'] = '*****@*****.**' item['subscription'] = 'none' stream.send(event.stanza) # FIXME: this is somewhat fragile - it's asserting the exact order that # things currently happen in roster.c. In reality the order is not # significant publish = expect_list_channel(q, bus, conn, 'publish', []) subscribe = expect_list_channel(q, bus, conn, 'subscribe', []) stored = expect_list_channel(q, bus, conn, 'stored', ['*****@*****.**']) stored.Group.RemoveMembers([dbus.UInt32(2)], '') send_roster_iq(stream, '*****@*****.**', 'remove') acknowledge_iq(stream, q.expect('stream-iq').stanza)
def test_create_invisible_list(q, bus, conn, stream): conn.SimplePresence.SetPresence("away", "") conn.Connect() stream.handle_get_all_privacy_lists(q, bus, conn) get_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='get') list_node = xpath.queryForNodes('//list', get_list.query)[0] assertEquals('invisible', list_node['name']) error = domish.Element((None, 'error')) error['type'] = 'cancel' error.addElement((ns.STANZA, 'item-not-found')) send_error_reply (stream, get_list.stanza, error) create_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set') list_node = xpath.queryForNodes('//list', create_list.query)[0] assertEquals('invisible', list_node['name']) assertNotEquals([], xpath.queryForNodes('/query/list/item/presence-out', create_list.query)) acknowledge_iq(stream, create_list.stanza) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) assertContains("hidden", conn.Properties.Get(cs.CONN_IFACE_SIMPLE_PRESENCE, "Statuses"))
def test_invisible_on_connect(q, bus, conn, stream): props = conn.Properties.GetAll(cs.CONN_IFACE_SIMPLE_PRESENCE) assertNotEquals({}, props['Statuses']) presence_event_pattern = EventPattern('stream-presence') q.forbid_events([presence_event_pattern]) conn.SimplePresence.SetPresence("hidden", "") conn.Connect() stream.handle_get_all_privacy_lists(q, bus, conn, ['invisible']) get_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='get') list_node = xpath.queryForNodes('//list', get_list.query)[0] assertEquals('invisible', list_node['name']) stream.send_privacy_list(get_list.stanza, [elem('item', action='deny', order='1')(elem('presence-out'))]) set_active = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set') active = xpath.queryForNodes('//active', set_active.query)[0] assertEquals('invisible', active['name']) acknowledge_iq(stream, set_active.stanza) q.unforbid_events([presence_event_pattern]) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])
def test_privacy_list_push_conflict(q, bus, conn, stream): test_invisible_on_connect(q, bus, conn, stream) set_id = stream.send_privacy_list_push_iq("invisible") _, req_list = q.expect_many( EventPattern('stream-iq', iq_type='result', predicate=lambda event: \ event.stanza['id'] == set_id), EventPattern('stream-iq', query_ns=ns.PRIVACY, iq_type="get")) stream.send_privacy_list(req_list.stanza, [elem('item', type='jid', value='*****@*****.**', action='allow', order='1')(elem('presence-out')), elem('item', action='deny', order='2')(elem('presence-out'))]) create_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set') created = xpath.queryForNodes('//list', create_list.stanza)[0] assertEquals(created["name"], 'invisible-gabble') acknowledge_iq(stream, create_list.stanza) set_active = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set') active = xpath.queryForNodes('//active', set_active.query)[0] assertEquals('invisible-gabble', active['name']) acknowledge_iq(stream, set_active.stanza)
def wait_bytestream_closed(self, expected=[]): events, close_event = wait_events(self.q, expected, EventPattern('stream-iq', iq_type='set', query_name='close', query_ns=ns.IBB)) # sender finish to send the file and so close the bytestream acknowledge_iq(self.stream, close_event.stanza) return events
def test(q, bus, conn, stream): conn.Connect() _, iq_event, disco_event = q.expect_many( EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]), EventPattern('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard'), EventPattern('stream-iq', to='localhost', query_ns=ns.DISCO_ITEMS)) acknowledge_iq(stream, iq_event.stanza) props = conn.GetAll( 'org.laptop.Telepathy.Gadget', dbus_interface=dbus.PROPERTIES_IFACE) assert props['GadgetAvailable'] == False announce_gadget(q, stream, disco_event.stanza) q.expect('dbus-signal', signal='GadgetDiscovered') props = conn.GetAll( 'org.laptop.Telepathy.Gadget', dbus_interface=dbus.PROPERTIES_IFACE) assert props['GadgetAvailable'] == True gadget_iface = dbus.Interface(conn, 'org.laptop.Telepathy.Gadget') # All the code has been moved to util.py:gadget_publish gadget_publish(q, stream, conn, True) gadget_publish(q, stream, conn, False) q.expect('stream-presence', presence_type='unsubscribed'),
def test(q, bus, conn, stream): conn.Connect() _, event = q.expect_many( EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]), EventPattern('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard')) acknowledge_iq(stream, event.stanza) # Force Gabble to process the vCard before calling any methods. sync_stream(q, stream) handle = conn.GetSelfHandle() call_async(q, conn.Avatars, 'SetAvatar', 'william shatner', 'image/x-actor-name') event = q.expect('stream-iq', iq_type='get', to=None, query_ns='vcard-temp', query_name='vCard') reply = make_result_iq(stream, event.stanza) reply['type'] = 'error' reply.addChild(elem('error')( elem(ns.STANZA, 'forbidden')(), elem(ns.STANZA, 'text')(u'zomg whoops'))) stream.send(reply) event = q.expect('dbus-error', method='SetAvatar', name=cs.NOT_AVAILABLE)
def no_server_discovered(q, bus, conn, stream, server=None): iq_event, disco_event = q.expect_many( EventPattern('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard'), EventPattern('stream-iq', to='localhost', query_ns=ns.DISCO_ITEMS)) acknowledge_iq(stream, iq_event.stanza) # no search server has been discovered yet. The CreateChannel operation # will fail once the disco process is finished. call_create(q, conn, server=server) # reply to IQ query. No search server is present reply = make_result_iq(stream, disco_event.stanza) stream.send(reply) # creation of the channel failed e = q.expect('dbus-error', method='CreateChannel', name=cs.INVALID_ARGUMENT) # This server doesn't have a search server. We can't create Search channel # without specifying a Server property call_create(q, conn, server=server) e = q.expect('dbus-error', method='CreateChannel') assertEquals(cs.INVALID_ARGUMENT, e.error.get_dbus_name())
def test(q, bus, conn, stream): event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, event.stanza) handle = conn.RequestHandles(1, ['*****@*****.**'])[0] call_async(q, conn.Aliasing, 'RequestAliases', [handle]) # Nack PEP query. event = q.expect('stream-iq', to='*****@*****.**', iq_type='get', query_ns='http://jabber.org/protocol/pubsub', query_name='pubsub') items = event.query.firstChildElement() assert items.name == 'items' assert items['node'] == "http://jabber.org/protocol/nick" result = make_result_iq(stream, event.stanza) result['type'] = 'error' error = result.addElement('error') error['type'] = 'auth' error.addElement('forbidden', 'urn:ietf:params:xml:ns:xmpp-stanzas') stream.send(result) event = q.expect('stream-iq', to='*****@*****.**', query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, event.stanza) q.expect('dbus-return', method='RequestAliases', value=([u'*****@*****.**'],)) # A second request should be satisfied from the cache. assert conn.Aliasing.RequestAliases([handle]) == ['*****@*****.**']
def test(q, bus, conn, stream): event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, event.stanza) # Force Gabble to process the vCard before calling any methods. sync_stream(q, stream) handle = conn.Properties.Get(cs.CONN, "SelfHandle") call_async(q, conn.Avatars, 'SetAvatar', 'william shatner', 'image/x-actor-name') event = q.expect('stream-iq', iq_type='get', to=None, query_ns='vcard-temp', query_name='vCard') reply = make_result_iq(stream, event.stanza) reply['type'] = 'error' reply.addChild( elem('error')(elem(ns.STANZA, 'forbidden')(), elem(ns.STANZA, 'text')(u'zomg whoops'))) stream.send(reply) event = q.expect('dbus-error', method='SetAvatar', name=cs.NOT_AVAILABLE)
def test_invisible(q, bus, conn, stream): assertContains("hidden", conn.Properties.Get(cs.CONN_IFACE_SIMPLE_PRESENCE, "Statuses")) conn.SimplePresence.SetPresence("hidden", "") # First we send an <invisible/> command. event = q.expect('stream-iq', query_name='invisible') acknowledge_iq(stream, event.stanza) # When that's returned successfully, we can signal the change on D-Bus. q.expect('dbus-signal', signal='PresencesChanged', interface=cs.CONN_IFACE_SIMPLE_PRESENCE, args=[{1: (5, 'hidden', '')}]) conn.SimplePresence.SetPresence("away", "gone") # First Gabble sends a <visible/> command. event = q.expect('stream-iq', query_name='visible') acknowledge_iq(stream, event.stanza) # Then: "It is the responsibility of the client to send an undirected # presence notification to the server". Plus, we should signal the change # on D-Bus. q.expect_many( EventPattern('stream-presence', to=None), EventPattern('dbus-signal', signal='PresencesChanged', interface=cs.CONN_IFACE_SIMPLE_PRESENCE, args=[{1: (3, 'away', 'gone')}]))
def test_with_xep0186(q, bus, conn, stream): statuses = conn.Properties.Get(cs.CONN_IFACE_SIMPLE_PRESENCE, 'Statuses') # testbusy and testaway are provided by test plugin assertContains('testbusy', statuses) assertContains('testaway', statuses) assertEquals(statuses['testbusy'][0], cs.PRESENCE_BUSY) assertEquals(statuses['testaway'][0], cs.PRESENCE_AWAY) conn.SimplePresence.SetPresence('testbusy', '') conn.Connect() # ... gabble asks for all the available lists on the server ... stream.handle_get_all_privacy_lists(q, bus, conn, lists=["foo-list", "test-busy-list", "bar-list"]) get_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set') list_node = xpath.queryForNodes('//active', get_list.query)[0] # ... and then activates the one linked with the requested status # Note: testbusy status is linked to test-busy-list by test plugin assertEquals('test-busy-list', list_node['name']) acknowledge_iq(stream, get_list.stanza) q.expect('dbus-signal', signal='PresencesChanged', args=[{1L: (cs.PRESENCE_BUSY, u'testbusy', '')}])
def test_invisible_on_connect_fail(q, bus, conn, stream): props = conn.Properties.GetAll(cs.CONN_IFACE_SIMPLE_PRESENCE) assertNotEquals({}, props['Statuses']) presence_event_pattern = EventPattern('stream-presence') q.forbid_events([presence_event_pattern]) conn.SimplePresence.SetPresence("hidden", "") conn.Connect() stream.handle_get_all_privacy_lists(q, bus, conn) create_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set') # Check its name assertNotEquals([], xpath.queryForNodes('/query/list/item/presence-out', create_list.query)) acknowledge_iq(stream, create_list.stanza) set_active = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set') active = xpath.queryForNodes('//active', set_active.query)[0] assertEquals('invisible', active['name']) send_error_reply(stream, set_active.stanza) q.unforbid_events([presence_event_pattern]) # Darn! At least we should have our presence set to DND. q.expect_many( EventPattern('dbus-signal', signal='PresencesChanged', interface=cs.CONN_IFACE_SIMPLE_PRESENCE, args=[{1: (6, 'dnd', '')}]), EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]))
def test_deny_unblock_remove(q, bus, conn, stream, stored, deny): """ Test unblocking a contact, and, while that request is pending, deleting them. """ self_handle = conn.GetSelfHandle() # This contact was on our roster, blocked and subscribed, when we started. contact = '*****@*****.**' handle = conn.RequestHandles(cs.HT_CONTACT, [contact])[0] # They're blocked, and we have a bidi subscription, so they should be on # deny and stored. (We already checked this earlier, but we've been messing # with the roster so let's be sure the preconditions are okay...) assertContains(handle, deny.Properties.Get(cs.CHANNEL_IFACE_GROUP, "Members")) assertContains(handle, stored.Properties.Get(cs.CHANNEL_IFACE_GROUP, "Members")) # Unblock them. call_async(q, deny.Group, 'RemoveMembers', [handle], "") roster_event = q.expect('stream-iq', query_ns=ns.ROSTER) item = roster_event.query.firstChildElement() assertEquals(contact, item['jid']) assertDoesNotContain((ns.GOOGLE_ROSTER, 't'), item.attributes) # If we now remove them from stored, the edit shouldn't be sent until the # unblock event has had a reply. q.forbid_events(remove_events) call_async(q, stored.Group, 'RemoveMembers', [handle], "") # Make sure if the remove is sent prematurely, we catch it. sync_stream(q, stream) q.unforbid_events(remove_events) # So now we send a roster push and reply for the unblock request. stream.send(make_set_roster_iq(stream, 'test@localhost/Resource', contact, 'both', False, attrs={})) acknowledge_iq(stream, roster_event.stanza) # And on receiving the push and reply, Gabble should show them being # removed from deny, and send a remove. _, roster_event = q.expect_many( EventPattern('dbus-signal', signal='MembersChanged', args=['', [], [handle], [], [], self_handle, cs.GC_REASON_NONE], predicate=is_deny), remove_events[0], ) item = roster_event.query.firstChildElement() assertEquals(contact, item['jid']) stream.send(make_set_roster_iq(stream, 'test@localhost/Resource', contact, 'remove', False, attrs={})) acknowledge_iq(stream, roster_event.stanza) q.expect('dbus-signal', signal='MembersChanged', args=['', [], [handle], [], [], 0, cs.GC_REASON_NONE], predicate=is_stored)
def test(q, bus, conn, stream): iq_event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, iq_event.stanza) t.check_conn_properties(q, conn) # Create new style tube channel and make sure that is indeed # returned. muc = '*****@*****.**' call_async( q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_DBUS_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: muc, cs.DBUS_TUBE_SERVICE_NAME: 'com.example.LolDongs' }) q.expect('stream-presence', to='%s/test' % muc) stream.send(make_muc_presence('owner', 'moderator', muc, 'bob')) stream.send(make_muc_presence('none', 'participant', muc, 'test')) ret, _ = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), EventPattern('dbus-signal', signal='NewChannels'), ) _, props = ret.value assertEquals(props[cs.CHANNEL_TYPE], cs.CHANNEL_TYPE_DBUS_TUBE) assertEquals(props[cs.TARGET_HANDLE_TYPE], cs.HT_ROOM) assertEquals(props[cs.TARGET_ID], muc) # Now try joining the text muc before asking for the tube channel. muc = '*****@*****.**' join_muc(q, bus, conn, stream, muc) call_async( q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_DBUS_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: muc, cs.DBUS_TUBE_SERVICE_NAME: 'com.example.LolDongs' }) ret, _ = q.expect_many( EventPattern('dbus-return', method='CreateChannel'), EventPattern('dbus-signal', signal='NewChannels'), ) _, props = ret.value assertEquals(props[cs.CHANNEL_TYPE], cs.CHANNEL_TYPE_DBUS_TUBE) assertEquals(props[cs.TARGET_HANDLE_TYPE], cs.HT_ROOM) assertEquals(props[cs.TARGET_ID], muc)
def test(q, bus, conn, stream, access_control): iq_event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, iq_event.stanza) # check if we can request muc D-Bus tube t.check_conn_properties(q, conn) self_handle = conn.Properties.Get(cs.CONN, "SelfHandle") self_name = conn.inspect_contact_sync(self_handle) # offer a D-Bus tube to another room using new API muc = '*****@*****.**' request = { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_DBUS_TUBE, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: '*****@*****.**', cs.DBUS_TUBE_SERVICE_NAME: 'com.example.TestCase', } join_muc(q, bus, conn, stream, muc, request=request) e = q.expect('dbus-signal', signal='NewChannels') channels = e.args[0] assert len(channels) == 1 path, prop = channels[0] assert prop[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_DBUS_TUBE assert prop[cs.INITIATOR_ID] == '[email protected]/test' assert prop[cs.REQUESTED] == True assert prop[cs.TARGET_HANDLE_TYPE] == cs.HT_ROOM assert prop[cs.TARGET_ID] == '*****@*****.**' assert prop[cs.DBUS_TUBE_SERVICE_NAME] == 'com.example.TestCase' assert prop[cs.DBUS_TUBE_SUPPORTED_ACCESS_CONTROLS] == [ cs.SOCKET_ACCESS_CONTROL_CREDENTIALS, cs.SOCKET_ACCESS_CONTROL_LOCALHOST ] # check that the tube channel is in the channels list all_channels = conn.Get(cs.CONN_IFACE_REQUESTS, 'Channels', dbus_interface=cs.PROPERTIES_IFACE, byte_arrays=True) assertContains((path, prop), all_channels) tube_chan = wrap_channel(bus.get_object(conn.bus_name, path), 'DBusTube') tube_props = tube_chan.Properties.GetAll(cs.CHANNEL_IFACE_TUBE, byte_arrays=True) assert tube_props['State'] == cs.TUBE_CHANNEL_STATE_NOT_OFFERED # try to offer using a wrong access control try: tube_chan.DBusTube.Offer(sample_parameters, cs.SOCKET_ACCESS_CONTROL_PORT) except dbus.DBusException, e: assertEquals(e.get_dbus_name(), cs.INVALID_ARGUMENT)
def test(q, bus, conn, stream): muc_handle = request_muc_handle(q, conn, stream, '*****@*****.**') call_async(q, conn, 'RequestChannel', cs.CHANNEL_TYPE_TEXT, cs.HT_ROOM, muc_handle, True) q.expect('stream-presence', to='[email protected]/test') # Send presence for own membership of room. stream.send( make_muc_presence('owner', 'moderator', '*****@*****.**', 'test')) iq, ret = q.expect_many( EventPattern('stream-iq', to='*****@*****.**', iq_type='get', query_ns=ns.MUC_OWNER), EventPattern('dbus-return', method='RequestChannel')) handle_muc_get_iq(stream, iq.stanza) text_chan = wrap_channel( bus.get_object(conn.bus_name, ret.value[0]), 'Text') props = dict([(name, id) for id, name, sig, flags in text_chan.TpProperties.ListProperties()]) call_async(q, text_chan.TpProperties, 'SetProperties', [(props['password'], 'foo'), (props['password-required'], True)]) event = q.expect('stream-iq', to='*****@*****.**', iq_type='get', query_ns=ns.MUC_OWNER) handle_muc_get_iq(stream, event.stanza) event = q.expect('stream-iq', to='*****@*****.**', iq_type='set', query_ns=ns.MUC_OWNER) fields = xpath.queryForNodes('/iq/query/x/field', event.stanza) form = {} for field in fields: values = xpath.queryForNodes('/field/value', field) form[field['var']] = [str(v) for v in values] assert form == {'password': ['foo'], 'password_protected': ['1'], 'muc#roomconfig_presencebroadcast' : ['moderator', 'participant', 'visitor']} acknowledge_iq(stream, event.stanza) event = q.expect('dbus-signal', signal='PropertiesChanged') assert event.args == [[(props['password'], 'foo'), (props['password-required'], True)]] q.expect('dbus-return', method='SetProperties', value=()) call_async(q, text_chan.TpProperties, 'SetProperties', [(31337, 'foo'), (props['password-required'], True)]) q.expect('dbus-error', name=cs.INVALID_ARGUMENT) call_async(q, text_chan.TpProperties, 'SetProperties', [(props['password'], True), (props['password-required'], 'foo')]) q.expect('dbus-error', name=cs.NOT_AVAILABLE) call_async(q, text_chan.TpProperties, 'SetProperties', [(props['subject-contact'], 42)]) q.expect('dbus-error', name=cs.PERMISSION_DENIED)
def handle_muc_owner_set_iq(stream, stanza, fields): form = parse_form(stanza) # Check that Gabble echoed back the fields it didn't understand (or want to # change) with their previous values. expected_form = get_default_form() expected_form.update(fields) assertEquals(expected_form, form) acknowledge_iq(stream, stanza)
def test(q, bus, conn, stream): event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, event.stanza) handle = conn.RequestHandles(1, ['*****@*****.**'])[0] call_async(q, conn.ContactInfo, 'RefreshContactInfo', [handle]) event = q.expect('stream-iq', to='*****@*****.**', query_ns='vcard-temp', query_name='vCard') result = make_result_iq(stream, event.stanza) result.firstChildElement().addElement('FN', content='Bob') n = result.firstChildElement().addElement('N') n.addElement('GIVEN', content='Bob') result.firstChildElement().addElement('NICKNAME', content=r'bob,bob1\,,bob2,bob3\,bob4') label = result.firstChildElement().addElement('LABEL') label.addElement('LINE', content='42 West Wallaby Street') label.addElement('LINE', content="Bishop's Stortford\n") label.addElement('LINE', content='Huntingdon') org = result.firstChildElement().addElement('ORG') # ORG is a sequence of decreasingly large org.units, starting # with the organisation name itself (but here we've moved the org name # to the end, to make sure that works.) org.addElement('ORGUNIT', content='Dept. of Examples') org.addElement('ORGUNIT', content='Exemplary Team') org.addElement('ORGNAME', content='Collabora Ltd.') stream.send(result) q.expect('dbus-signal', signal='ContactInfoChanged', args=[handle, [(u'fn', [], [u'Bob']), (u'n', [], [u'', u'Bob', u'', u'', u'']), (u'nickname', [], [r'bob,bob1\,,bob2,bob3\,bob4']), # LABEL comes out as a single blob of text (u'label', [], ['42 West Wallaby Street\n' "Bishop's Stortford\n" 'Huntingdon\n']), # ORG is a sequence of decreasingly large org.units, starting # with the organisation (u'org', [], [u'Collabora Ltd.', u'Dept. of Examples', u'Exemplary Team']), ]]) # ContactInfoChanged should not be signalled again forbidden = [EventPattern('dbus-signal', signal='ContactInfoChanged')] q.forbid_events(forbidden) # Refresh the contact info again; gabble should contact the server again call_async(q, conn.ContactInfo, 'RefreshContactInfo', [handle]) event = q.expect('stream-iq', to='*****@*****.**', query_ns='vcard-temp', query_name='vCard') sync_dbus(bus, q, conn) q.unforbid_events(forbidden)
def wait_bytestream_open(self): # Wait IBB open iq event = self.q.expect('stream-iq', iq_type='set') open = xpath.queryForNodes('/iq/open', event.stanza)[0] assert open.uri == ns.IBB assert open['sid'] == self.stream_id # open IBB bytestream acknowledge_iq(self.stream, event.stanza)
def test(q, bus, conn, stream): conn.Connect() _, event = q.expect_many( EventPattern('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]), EventPattern('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard')) acknowledge_iq(stream, event.stanza) handle = conn.RequestHandles(cs.HT_CONTACT, ['*****@*****.**'])[0] call_async(q, conn.Aliasing, 'RequestAliases', [handle]) event = q.expect('stream-iq', to='*****@*****.**', iq_type='get', query_ns=ns.PUBSUB, query_name='pubsub') items = event.query.firstChildElement() assertEquals('items', items.name) assertEquals(ns.NICK, items['node']) result = make_result_iq(stream, event.stanza) pubsub = result.firstChildElement() items = pubsub.addElement('items') items['node'] = ns.NICK item = items.addElement('item') item.addElement('nick', ns.NICK, content='Bobby') stream.send(result) q.expect('dbus-signal', signal='AliasesChanged', args=[[(handle, u'Bobby')]]) q.expect('dbus-return', method='RequestAliases', value=(['Bobby'],)) # A second request should be satisfied from the cache. assertEquals(['Bobby'], conn.Aliasing.RequestAliases([handle])) # Bobby grows up, decides he hates his nickname. # This is a regression test for # <https://bugs.freedesktop.org/show_bug.cgi?id=21817>, where this would # crash Gabble. message = elem('message', from_='*****@*****.**')( elem((ns.PUBSUB + "#event"), 'event')( elem('items', node=ns.NICK)( elem('item')( elem(ns.NICK, 'nick') ) ) ) ) stream.send(message.toXml()) event = q.expect('dbus-signal', signal='AliasesChanged') aliases = event.args[0] assertLength(1, aliases) h, a = aliases[0] assertEquals(handle, h) # The contact explicitly cleared their PEP nick; Gabble should fall back to # their JID. assertEquals(a, '*****@*****.**')
def test_deny_overlap_two(q, bus, conn, stream, subscribe, publish, stored, deny): """ Here's another tricky case: editing a contact (setting an alias, say), and then while that edit's in flight, blocking and remove the contact. """ # This contact was on our roster when we started. contact = '*****@*****.**' handle = conn.RequestHandles(cs.HT_CONTACT, [contact])[0] assertContains(handle, stored.Properties.Get(cs.CHANNEL_IFACE_GROUP, "Members")) assertContains(handle, subscribe.Properties.Get(cs.CHANNEL_IFACE_GROUP, "Members")) assertContains(handle, publish.Properties.Get(cs.CHANNEL_IFACE_GROUP, "Members")) # Once again, at no point in this test should anyone be removed outright. q.forbid_events(remove_events) # First up, we edit the contact's alias, triggering a roster update from # the client. conn.Aliasing.SetAliases({handle: 'oh! the huge manatee!'}) event = q.expect('stream-iq', query_ns=ns.ROSTER) item = event.query.firstChildElement() assertEquals(contact, item['jid']) assertEquals('oh! the huge manatee!', item['name']) # Before the server responds, we block and remove the contact. The edits # should be queued... patterns = [ EventPattern('stream-iq', query_ns=ns.ROSTER), EventPattern('stream-presence', presence_type='unsubscribed'), EventPattern('stream-presence', presence_type='unsubscribe'), ] q.forbid_events(patterns) call_async(q, deny.Group, 'AddMembers', [handle], "") call_async(q, stored.Group, 'RemoveMembers', [handle], "") # Make sure if the edits are sent prematurely, we've got them. sync_stream(q, stream) q.unforbid_events(patterns) # Okay, now we respond to the alias update. At this point we expect an # update to gr:t=B, leaving subscription=both intact, and subscription # cancellations. acknowledge_iq(stream, event.stanza) roster_event, _, _ = q.expect_many(*patterns) item = roster_event.query.firstChildElement() assertEquals(contact, item['jid']) assertEquals('B', item[(ns.GOOGLE_ROSTER, 't')]) # And we're done. Clean up. q.unforbid_events(remove_events)
def test(q, bus, conn, stream): iq_event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, iq_event.stanza) # send diso request m = domish.Element((None, 'iq')) m['from'] = '*****@*****.**' m['id'] = '1' m['type'] = 'get' query = m.addElement('query') query['xmlns'] = ns.DISCO_INFO stream.send(m) # wait for disco response event = q.expect('stream-iq', iq_type='result', query_ns=ns.DISCO_INFO, to='*****@*****.**') features = set([str(f['var']) for f in xpath.queryForNodes('/iq/query/feature', event.stanza)]) # OLPC NS aren't announced assert len(olpc_features.intersection(features)) == 0 # Use OLPC interface buddy_info_iface = dbus.Interface(conn, 'org.laptop.Telepathy.BuddyInfo') call_async(q, buddy_info_iface, 'SetProperties', {'color': '#ff0000,#0000ff'}) # wait for <presence> stanza event = q.expect('stream-presence') c_nodes = xpath.queryForNodes('/presence/c', event.stanza) assert c_nodes is not None assert len(c_nodes) == 1 # send diso request m = domish.Element((None, 'iq')) m['from'] = '*****@*****.**' m['id'] = '2' m['type'] = 'get' query = m.addElement('query') query['xmlns'] = ns.DISCO_INFO stream.send(m) # wait for disco response event = q.expect('stream-iq', iq_type='result', query_ns=ns.DISCO_INFO, to='*****@*****.**') assert event.stanza['id'] == '2' # OLPC NS are now announced features = set([str(f['var']) for f in xpath.queryForNodes('/iq/query/feature', event.stanza)]) assert olpc_features.issubset(features)
def test(q, bus, conn, stream): statuses = conn.Properties.Get(cs.CONN_IFACE_SIMPLE_PRESENCE, 'Statuses') # testbusy and testaway are provided by test plugin assertContains('testbusy', statuses) assertContains('testaway', statuses) assertEquals(statuses['testbusy'][0], cs.PRESENCE_BUSY) assertEquals(statuses['testaway'][0], cs.PRESENCE_AWAY) conn.SimplePresence.SetPresence('testbusy', '') conn.Connect() # ... gabble asks for all the available lists on the server ... stream.handle_get_all_privacy_lists( q, bus, conn, lists=["foo-list", "test-busy-list", "bar-list"]) # ... gabble checks whether there's usable invisible list on the server ... get_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='get') list_node = xpath.queryForNodes('//list', get_list.query)[0] assertEquals('invisible', list_node['name']) error = domish.Element((None, 'error')) error['type'] = 'cancel' error.addElement((ns.STANZA, 'item-not-found')) send_error_reply(stream, get_list.stanza, error) # ... since there is none, Gabble creates it ... create_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set') list_node = xpath.queryForNodes('//list', create_list.query)[0] assertEquals('invisible', list_node['name']) assertNotEquals([], xpath.queryForNodes('/query/list/item/presence-out', create_list.query)) acknowledge_iq(stream, create_list.stanza) get_list = q.expect('stream-iq', query_ns=ns.PRIVACY, iq_type='set') list_node = xpath.queryForNodes('//active', get_list.query)[0] # ... and then activates the one linked with the requested status # Note: testbusy status is linked to test-busy-list by test plugin assertEquals('test-busy-list', list_node['name']) acknowledge_iq(stream, get_list.stanza) q.expect('dbus-signal', signal='PresencesChanged', args=[{ 1: (cs.PRESENCE_BUSY, u'testbusy', '') }]) q.expect('dbus-signal', signal='StatusChanged', args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED]) # ... testaway is not supposed to be settable on us call_async(q, conn.SimplePresence, 'SetPresence', 'testaway', '') q.expect('dbus-error', method='SetPresence', name=cs.INVALID_ARGUMENT)
def test(q, bus, conn, stream, queued=False): event = q.expect('stream-iq', query_ns=ns.ROSTER) event.stanza['type'] = 'result' item = event.query.addElement('item') item['jid'] = '*****@*****.**' item['subscription'] = 'none' quux_handle = conn.get_contact_handle_sync('*****@*****.**') stream.send(event.stanza) # slight implementation detail: TpBaseContactList emits ContactsChanged # before it announces its channels q.expect('dbus-signal', signal='ContactsChangedWithID', interface=cs.CONN_IFACE_CONTACT_LIST, path=conn.object_path, args=[{quux_handle: (cs.SUBSCRIPTION_STATE_NO, cs.SUBSCRIPTION_STATE_NO, '')}, {quux_handle: '*****@*****.**'}, {}]) check_contact_roster(conn, '*****@*****.**', [], cs.SUBSCRIPTION_STATE_NO, cs.SUBSCRIPTION_STATE_NO) if queued: conn.Aliasing.SetAliases({quux_handle: 'Quux'}) set_aliases = q.expect('stream-iq', query_ns=ns.ROSTER) item = set_aliases.query.firstChildElement() assertEquals('*****@*****.**', item['jid']) assertEquals('Quux', item['name']) expectations = [ EventPattern('stream-iq', iq_type='set', query_ns=ns.ROSTER), ] call_async(q, conn.ContactList, 'RemoveContacts', [quux_handle]) if queued: # finish off the previous thing we were doing, so removal can proceed acknowledge_iq(stream, set_aliases.stanza) event = q.expect_many(*expectations)[0] item = event.query.firstChildElement() assertEquals('*****@*****.**', item['jid']) assertEquals('remove', item['subscription']) send_roster_push(stream, '*****@*****.**', 'remove') q.expect_many( EventPattern('dbus-signal', interface=cs.CONN_IFACE_CONTACT_LIST, path=conn.object_path, signal='ContactsChangedWithID', args=[{}, {}, {quux_handle: '*****@*****.**'}]), EventPattern('stream-iq', iq_id='push', iq_type='result'), ) acknowledge_iq(stream, event.stanza) q.expect('dbus-return', method='RemoveContacts')
def test(q, bus, conn, stream): event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, event.stanza) # returning an empty vcard will cause ContactInfoChanged to fire q.expect('dbus-signal', signal='ContactInfoChanged') handle = conn.RequestHandles(1, ['*****@*****.**'])[0] call_async(q, conn.ContactInfo, 'RefreshContactInfo', [handle]) event = q.expect('stream-iq', to='*****@*****.**', query_ns='vcard-temp', query_name='vCard') result = make_result_iq(stream, event.stanza) result.firstChildElement().addElement('FN', content='Bob') n = result.firstChildElement().addElement('N') n.addElement('GIVEN', content='Bob') result.firstChildElement().addElement('NICKNAME', content=r'bob,bob1\,,bob2,bob3\,bob4') label = result.firstChildElement().addElement('LABEL') label.addElement('LINE', content='42 West Wallaby Street') label.addElement('LINE', content="Bishop's Stortford\n") label.addElement('LINE', content='Huntingdon') org = result.firstChildElement().addElement('ORG') # ORG is a sequence of decreasingly large org.units, starting # with the organisation name itself (but here we've moved the org name # to the end, to make sure that works.) org.addElement('ORGUNIT', content='Dept. of Examples') org.addElement('ORGUNIT', content='Exemplary Team') org.addElement('ORGNAME', content='Collabora Ltd.') stream.send(result) q.expect('dbus-signal', signal='ContactInfoChanged') contact_info = [(u'fn', [], [u'Bob']), (u'n', [], [u'', u'Bob', u'', u'', u'']), (u'nickname', [], [r'bob,bob1\,,bob2,bob3\,bob4']), # LABEL comes out as a single blob of text (u'label', [], ['42 West Wallaby Street\n' "Bishop's Stortford\n" 'Huntingdon\n']), # ORG is a sequence of decreasingly large org.units, starting # with the organisation (u'org', [], [u'Collabora Ltd.', u'Dept. of Examples', u'Exemplary Team']), ] # The request should be satisfied from the cache. assertEquals( {handle: contact_info}, conn.ContactInfo.GetContactInfo([handle])) # check the ContactAttribute assertEquals( {handle: {cs.CONN_IFACE_CONTACT_INFO + '/info': contact_info, 'org.freedesktop.Telepathy.Connection/contact-id': '*****@*****.**'}}, conn.Contacts.GetContactAttributes([handle], [cs.CONN_IFACE_CONTACT_INFO], False))
def test(q, bus, conn, stream): path, _ = conn.Future.EnsureSidecar(CONSOLE_PLUGIN_IFACE) console = ProxyWrapper(bus.get_object(conn.bus_name, path), CONSOLE_PLUGIN_IFACE) assert not console.Properties.Get(CONSOLE_PLUGIN_IFACE, 'SpewStanzas') es = [ EventPattern('dbus-signal', signal='StanzaReceived'), EventPattern('dbus-signal', signal='StanzaSent'), ] q.forbid_events(es) call_async(q, console, 'SendIQ', 'get', STACY, '<coffee xmlns="urn:unimaginative"/>') e = q.expect('stream-iq', iq_type='get', query_ns='urn:unimaginative', query_name='coffee') acknowledge_iq(stream, e.stanza) e = q.expect('dbus-return', method='SendIQ') type_, body = e.value assertEquals('result', type_) # We just assume the body works. # Turn on signalling incoming and outgoing stanzas console.Properties.Set(CONSOLE_PLUGIN_IFACE, 'SpewStanzas', True) sync_dbus(bus, q, conn) q.unforbid_events(es) send_unrecognised_get(q, stream) e = q.expect('dbus-signal', signal='StanzaReceived') xml, = e.args assertContains('<iq', xml) assertContains('<dont-handle-me-bro', xml) signal = q.expect('dbus-signal', signal='StanzaSent') assertContains('service-unavailable', signal.args[0]) # Turn off spewing out stanzas; check it works. console.Properties.Set(CONSOLE_PLUGIN_IFACE, 'SpewStanzas', False) q.forbid_events(es) send_unrecognised_get(q, stream) sync_dbus(bus, q, conn) # Try sending just any old stanza console.SendStanza(''' <message to='%(stacy)s' type='headline'> <body> Hi sis. </body> </message>''' % { 'stacy': STACY }) e = q.expect('stream-message', to=STACY, message_type='headline') # Wocky fills in xmlns='' for us if we don't specify a namespace... great. # So this means <message/> gets sent as <message xmlns=''/> and the server # kicks us off. assertNotEquals('', e.stanza.uri)
def test_deny_unblock_remove(q, bus, conn, stream): """ Test unblocking a contact, and, while that request is pending, deleting them. """ # This contact was on our roster, blocked and subscribed, when we started. contact = '*****@*****.**' handle = conn.get_contact_handle_sync(contact) check_contact_roster(conn, contact, [], cs.SUBSCRIPTION_STATE_YES, cs.SUBSCRIPTION_STATE_YES) # They're blocked, and we have a bidi subscription, so they should be on # deny and stored. (We already checked this earlier, but we've been messing # with the roster so let's be sure the preconditions are okay...) assertContains(handle, conn.ContactBlocking.RequestBlockedContacts().keys()) # Unblock them. call_async(q, conn.ContactBlocking, 'UnblockContacts', [handle]) roster_event = q.expect('stream-iq', query_ns=ns.ROSTER) item = roster_event.query.firstChildElement() assertEquals(contact, item['jid']) assertDoesNotContain((ns.GOOGLE_ROSTER, 't'), item.attributes) # If we now remove them from stored, the edit shouldn't be sent until the # unblock event has had a reply. q.forbid_events(remove_events) call_async(q, conn.ContactList, 'RemoveContacts', [handle]) # Make sure if the remove is sent prematurely, we catch it. sync_stream(q, stream) q.unforbid_events(remove_events) # So now we send a roster push and reply for the unblock request. stream.send(make_set_roster_iq(stream, 'test@localhost/Resource', contact, 'both', False, attrs={})) acknowledge_iq(stream, roster_event.stanza) # And on receiving the push and reply, Gabble should show them being # removed from deny, and send a remove. _, roster_event = q.expect_many( EventPattern('dbus-signal', signal='BlockedContactsChanged', predicate=lambda e: blocked_contacts_changed_predicate(e, [], [contact])), remove_events[0], ) item = roster_event.query.firstChildElement() assertEquals(contact, item['jid']) stream.send(make_set_roster_iq(stream, 'test@localhost/Resource', contact, 'remove', False, attrs={})) acknowledge_iq(stream, roster_event.stanza)
def wait_bytestream_closed(self, expected=[]): events, close_event = wait_events( self.q, expected, EventPattern('stream-iq', iq_type='set', query_name='close', query_ns=ns.IBB)) # sender finish to send the file and so close the bytestream acknowledge_iq(self.stream, close_event.stanza) return events
def test_pep(q, bus, conn, stream): call_async(q, conn.Location, 'SetLocation', {'lat': 0.0, 'lon': 0.0}) geoloc_iq_set_event = EventPattern( 'stream-iq', predicate=lambda x: xpath.queryForNodes( "/iq/pubsub/publish/item/geoloc", x.stanza)) event = q.expect_many(geoloc_iq_set_event)[0] acknowledge_iq(stream, event.stanza) q.expect('dbus-return', method='SetLocation')
def test(q, bus, conn, stream): event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, event.stanza) handle = conn.get_contact_handle_sync('*****@*****.**') call_async(q, conn.Aliasing, 'RequestAliases', [handle]) event = q.expect('stream-iq', to='*****@*****.**', iq_type='get', query_ns=ns.PUBSUB, query_name='pubsub') items = event.query.firstChildElement() assertEquals('items', items.name) assertEquals(ns.NICK, items['node']) result = make_result_iq(stream, event.stanza) pubsub = result.firstChildElement() items = pubsub.addElement('items') items['node'] = ns.NICK item = items.addElement('item') item.addElement('nick', ns.NICK, content='Bobby') stream.send(result) q.expect('dbus-signal', signal='AliasesChanged', args=[[(handle, u'Bobby')]]) q.expect('dbus-return', method='RequestAliases', value=(['Bobby'],)) # A second request should be satisfied from the cache. assertEquals(['Bobby'], conn.Aliasing.RequestAliases([handle])) # Bobby grows up, decides he hates his nickname. # This is a regression test for # <https://bugs.freedesktop.org/show_bug.cgi?id=21817>, where this would # crash Gabble. message = elem('message', from_='*****@*****.**')( elem((ns.PUBSUB_EVENT), 'event')( elem('items', node=ns.NICK)( elem('item')( elem(ns.NICK, 'nick') ) ) ) ) stream.send(message.toXml()) event = q.expect('dbus-signal', signal='AliasesChanged') aliases = event.args[0] assertLength(1, aliases) h, a = aliases[0] assertEquals(handle, h) # The contact explicitly cleared their PEP nick; Gabble should fall back to # their JID. assertEquals(a, '*****@*****.**')
def test_pep(q, bus, conn, stream): call_async(q, conn.Location, 'SetLocation', { 'lat': 0.0, 'lon': 0.0}) geoloc_iq_set_event = EventPattern('stream-iq', predicate=lambda x: xpath.queryForNodes("/iq/pubsub/publish/item/geoloc", x.stanza)) event = q.expect_many(geoloc_iq_set_event)[0] acknowledge_iq(stream, event.stanza) q.expect('dbus-return', method='SetLocation')
def check_roster_write(stream, event, jid, name): item = event.query.firstChildElement() assertEquals(jid, item['jid']) # This copes with name=None assertEquals(name, item.getAttribute('name')) acknowledge_iq(stream, event.stanza) # RFC 3921 requires the server to send a roster push to all connected # resources whenever a resource updates the roster. Gabble depends on this # and pays no attention to its own nick update until the server sends a # push. send_roster_push(stream, jid, 'none', name=name)
def replying_to_requests(q, bus, conn, stream): jid = '*****@*****.**' # We shouldn't send receipts to people who aren't on our roster. q.forbid_events([EventPattern('stream-message', to=jid)]) stream.send( elem('message', from_=jid, type='chat', id='alpha')(elem('body')(u"You didn't kill me, you moron!"), elem(ns.RECEIPTS, 'request'))) q.expect('dbus-signal', signal='MessageReceived') sync_stream(q, stream) q.unforbid_all() # We should send receipts to people on our roster, seeing as we're not # invisible. rostertest.send_roster_push(stream, jid, subscription='from') stream.send( elem('message', from_=jid, type='chat', id='beta')( elem('body')(u"You've just destroyed my spiritual essences."), elem(ns.RECEIPTS, 'request'))) q.expect('dbus-signal', signal='MessageReceived') e = q.expect('stream-message', to=jid) receipt = next(e.stanza.elements(uri=ns.RECEIPTS, name='received')) assertEquals('beta', receipt['id']) # We would like requests in messages without id=''s not to crash Gabble, # and also for it not to send a reply. q.forbid_events([EventPattern('stream-message', to=jid)]) stream.send( elem('message', from_=jid, type='chat')( # NB. no id='' attribute elem('body')(u"A favor that I shall now return!"), elem(ns.RECEIPTS, 'request'))) q.expect('dbus-signal', signal='MessageReceived') sync_stream(q, stream) q.unforbid_all() # If we're invisible, LeChuck shouldn't get receipts. conn.SimplePresence.SetPresence("hidden", "") event = q.expect('stream-iq', query_name='invisible') acknowledge_iq(stream, event.stanza) q.forbid_events([EventPattern('stream-message', to=jid)]) stream.send( elem('message', from_=jid, type='chat', id='epsilon')(elem('body')( u"… but where am I going to find a duck wearing burlap chaps?"), elem( ns.RECEIPTS, 'request'))) q.expect('dbus-signal', signal='MessageReceived') sync_stream(q, stream) q.unforbid_all()
def test_deny_overlap_two(q, bus, conn, stream): """ Here's another tricky case: editing a contact (setting an alias, say), and then while that edit's in flight, blocking and remove the contact. """ # This contact was on our roster when we started. contact = '*****@*****.**' handle = conn.get_contact_handle_sync(contact) check_contact_roster(conn, contact, [], cs.SUBSCRIPTION_STATE_YES, cs.SUBSCRIPTION_STATE_YES) # Once again, at no point in this test should anyone be removed outright. q.forbid_events(remove_events) # First up, we edit the contact's alias, triggering a roster update from # the client. conn.Aliasing.SetAliases({handle: 'oh! the huge manatee!'}) event = q.expect('stream-iq', query_ns=ns.ROSTER) item = event.query.firstChildElement() assertEquals(contact, item['jid']) assertEquals('oh! the huge manatee!', item['name']) # Before the server responds, we block and remove the contact. The edits # should be queued... patterns = [ EventPattern('stream-iq', query_ns=ns.ROSTER), EventPattern('stream-presence', presence_type='unsubscribed'), EventPattern('stream-presence', presence_type='unsubscribe'), ] q.forbid_events(patterns) call_async(q, conn.ContactBlocking, 'BlockContacts', [handle], "") call_async(q, conn.ContactList, 'RemoveContacts', [handle]) # Make sure if the edits are sent prematurely, we've got them. sync_stream(q, stream) q.unforbid_events(patterns) # Okay, now we respond to the alias update. At this point we expect an # update to gr:t=B, leaving subscription=both intact, and subscription # cancellations. acknowledge_iq(stream, event.stanza) roster_event, _, _ = q.expect_many(*patterns) item = roster_event.query.firstChildElement() assertEquals(contact, item['jid']) assertEquals('B', item[(ns.GOOGLE_ROSTER, 't')]) # And we're done. Clean up. q.unforbid_events(remove_events)
def test(q, bus, conn, stream): iq_event, disco_event = q.expect_many( EventPattern('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard'), EventPattern('stream-iq', to='localhost', query_ns=ns.DISCO_ITEMS)) acknowledge_iq(stream, iq_event.stanza) buddy_info_iface = dbus.Interface(conn, 'org.laptop.Telepathy.BuddyInfo') handles = {} # Alice is one of our friend so we receive her PEP notifications handles['alice'] = conn.get_contact_handle_sync('alice@localhost') # Try to get Alice's currrent-activity call_async(q, buddy_info_iface, "GetCurrentActivity", handles['alice']) # Alice's current-activity is not in the cache so Gabble sends a PEP query event = q.expect('stream-iq', iq_type='get', query_name='pubsub') answer_to_current_act_pubsub_request(stream, event.stanza, 'activity1', '*****@*****.**') event = q.expect('dbus-return', method='GetCurrentActivity') id, handles['room1'] = event.value assert id == 'activity1' assert conn.InspectHandles(2, [handles['room1']]) == \ ['*****@*****.**'] # Retry to get Alice's current-activity # Alice's current-activity is now in the cache so Gabble doesn't # send PEP query assert buddy_info_iface.GetCurrentActivity(handles['alice']) == \ ('activity1', handles['room1']) # Alice changed her current-activity send_buddy_changed_current_act_msg(stream, 'alice@localhost', 'activity2', '*****@*****.**') event = q.expect('dbus-signal', signal='CurrentActivityChanged') contact, id, handles['room2'] = event.args assert contact == handles['alice'] assert id == 'activity2' assert conn.InspectHandles(2, [handles['room2']]) == \ ['*****@*****.**'] # Get Alice's current-activity as the cache have to be updated assert buddy_info_iface.GetCurrentActivity(handles['alice']) == \ ('activity2', handles['room2'])
def test(q, bus, conn, stream): event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, event.stanza) # returning an empty vcard will cause ContactInfoChanged to fire q.expect('dbus-signal', signal='ContactInfoChanged') handle = conn.get_contact_handle_sync('*****@*****.**') call_async(q, conn.ContactInfo, 'RefreshContactInfo', [handle]) event = q.expect('stream-iq', to='*****@*****.**', query_ns='vcard-temp', query_name='vCard') result = make_result_iq(stream, event.stanza) result.firstChildElement().addElement('FN', content='Bob') n = result.firstChildElement().addElement('N') n.addElement('GIVEN', content='Bob') result.firstChildElement().addElement('NICKNAME', content=r'bob,bob1\,,bob2,bob3\,bob4') label = result.firstChildElement().addElement('LABEL') label.addElement('LINE', content='42 West Wallaby Street') label.addElement('LINE', content="Bishop's Stortford\n") label.addElement('LINE', content='Huntingdon') org = result.firstChildElement().addElement('ORG') # ORG is a sequence of decreasingly large org.units, starting # with the organisation name itself (but here we've moved the org name # to the end, to make sure that works.) org.addElement('ORGUNIT', content='Dept. of Examples') org.addElement('ORGUNIT', content='Exemplary Team') org.addElement('ORGNAME', content='Collabora Ltd.') stream.send(result) q.expect('dbus-signal', signal='ContactInfoChanged') contact_info = [(u'fn', [], [u'Bob']), (u'n', [], [u'', u'Bob', u'', u'', u'']), (u'nickname', [], [r'bob,bob1\,,bob2,bob3\,bob4']), # LABEL comes out as a single blob of text (u'label', [], ['42 West Wallaby Street\n' "Bishop's Stortford\n" 'Huntingdon\n']), # ORG is a sequence of decreasingly large org.units, starting # with the organisation (u'org', [], [u'Collabora Ltd.', u'Dept. of Examples', u'Exemplary Team']), ] # The request should be satisfied from the cache. h2asv = conn.Contacts.GetContactAttributes([handle], [cs.CONN_IFACE_CONTACT_INFO], False) assertEquals(contact_info, h2asv[handle][cs.ATTR_CONTACT_INFO])
def test(q, bus, conn, stream): event = q.expect('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard') acknowledge_iq(stream, event.stanza) sync_stream(q, stream) sync_dbus(bus, q, conn) # A presence from a contact stream.send( make_presence('contact1@localhost/client', 'SHA1SUM-FOR-CONTACT1')) event = q.expect('dbus-signal', signal='AvatarUpdated') assert event.args[0] == 2, event.args assert event.args[1] == "SHA1SUM-FOR-CONTACT1", event.args AvatarRetrieved_event = EventPattern('dbus-signal', signal='AvatarRetrieved') AvatarUpdated_event = EventPattern('dbus-signal', signal='AvatarUpdated') StreamPresence_event = EventPattern('stream-presence') StreamIqVcard_event = EventPattern('stream-iq', query_ns='vcard-temp') # A presence from myself on another resource stream.send( make_presence('test@localhost/resource1', 'SHA1SUM-FOR-MYSELF-RES1')) q.forbid_events([AvatarRetrieved_event, AvatarUpdated_event]) stream_presence, stream_iq = q.expect_many( EventPattern('stream-presence'), EventPattern('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard')) sync_dbus(bus, q, conn) q.unforbid_events([AvatarRetrieved_event, AvatarUpdated_event]) # If the server wrongly send a presence stanza with our resource, # AvatarUpdated must not be emitted q.forbid_events([ StreamPresence_event, StreamIqVcard_event, AvatarRetrieved_event, AvatarUpdated_event ]) stream.send(make_presence('test@localhost/Resource', 'SHA1SUM-FOR-MYSELF')) sync_dbus(bus, q, conn) sync_stream(q, stream) q.unforbid_events([ StreamPresence_event, StreamIqVcard_event, AvatarRetrieved_event, AvatarUpdated_event ])
def test_success(q, gateways_iface, stream): call_async(q, gateways_iface, 'Register', 'talkd.example.com', '1970', 's3kr1t') e = q.expect('stream-iq', iq_type='set', query_name='query', query_ns=ns.REGISTER, to='talkd.example.com') assertEquals('1970', xpath.queryForString('/query/username', e.query)) assertEquals('s3kr1t', xpath.queryForString('/query/password', e.query)) acknowledge_iq(stream, e.stanza) q.expect_many( EventPattern('dbus-return', method='Register'), EventPattern('stream-presence', presence_type='subscribe', to='talkd.example.com'), ) stream.send(make_presence('talkd.example.com', type='subscribed'))
def server_discovered(q, bus, conn, stream, server=None): iq_event, disco_event = q.expect_many( EventPattern('stream-iq', to=None, query_ns='vcard-temp', query_name='vCard'), EventPattern('stream-iq', to='localhost', query_ns=ns.DISCO_ITEMS)) acknowledge_iq(stream, iq_event.stanza) # no search server has been discovered yet. The CreateChannel operation # will be completed once the disco process is finished. call_create(q, conn, server=server) # reply to IQ query reply = make_result_iq(stream, disco_event.stanza) query = xpath.queryForNodes('/iq/query', reply)[0] item = query.addElement((None, 'item')) item['jid'] = JUD_SERVER stream.send(reply) # wait for the disco#info query event = q.expect('stream-iq', to=JUD_SERVER, query_ns=ns.DISCO_INFO) reply = elem_iq(stream, 'result', id=event.stanza['id'], from_=JUD_SERVER)( elem(ns.DISCO_INFO, 'query')(elem('identity', category='directory', type='user', name='vCard User Search')(), elem('feature', var=ns.SEARCH)())) stream.send(reply) # JUD_SERVER is used as default, and shows up as the Server property on the # resulting channel. ret, _ = answer_field_query(q, stream, JUD_SERVER) _, properties = ret.value assertEquals(JUD_SERVER, properties[cs.CONTACT_SEARCH_SERVER]) # Now that the search server has been discovered, it is used right away. call_create(q, conn, server=server) ret, _ = answer_field_query(q, stream, JUD_SERVER) _, properties = ret.value assertEquals(JUD_SERVER, properties[cs.CONTACT_SEARCH_SERVER])
def test(q, bus, conn, stream): # Gabble asks for the roster; the server sends back an empty roster. event = q.expect('stream-iq', query_ns=ns.ROSTER) acknowledge_iq(stream, event.stanza) q.expect('dbus-signal', signal='ContactListStateChanged', args=[cs.CONTACT_LIST_STATE_SUCCESS]) # The server sends us a roster push without an id=''. WTF! iq = make_roster_push(stream, jid, 'both') del iq['id'] stream.send(iq) h = conn.get_contact_handle_sync(jid) q.expect_many( EventPattern( 'dbus-signal', signal='ContactsChangedWithID', args=[{ h: (cs.SUBSCRIPTION_STATE_YES, cs.SUBSCRIPTION_STATE_YES, ''), }, { h: jid }, {}], ), ) # Verify that Gabble didn't crash while trying to ack the push. sync_stream(q, stream) # Just for completeness, let's repeat this test with a malicious roster # push from a contact (rather than from our server). Our server's *really* # broken if it allows this. Nonetheless... iq = make_roster_push(stream, '*****@*****.**', 'both') del iq['id'] iq['from'] = '*****@*****.**' stream.send(iq) q.forbid_events([ EventPattern('dbus-signal', signal='ContactsChangedWithID'), ]) # Make sure Gabble's got the evil push... sync_stream(q, stream) # ...and make sure it's not emitted anything. sync_dbus(bus, q, conn)