def test(q, bus, conn, stream, image_data, mime_type): call_async(q, conn.Avatars, 'SetAvatar', image_data, mime_type) expect_and_handle_get_vcard(q, stream) def check(vcard): assertEquals(mime_type, xpath.queryForString('/vCard/PHOTO/TYPE', vcard)) binval = xpath.queryForString('/vCard/PHOTO/BINVAL', vcard) # <http://xmpp.org/extensions/xep-0153.html#bizrules-image> says: # # 5. The image data MUST conform to the base64Binary datatype and thus # be encoded in accordance with Section 6.8 of RFC 2045, which # recommends that base64 data should have lines limited to at most # 76 characters in length. lines = binval.split('\n') for line in lines: assert len(line) <= 76, line assertEquals(image_data, base64.decodestring(binval)) expect_and_handle_set_vcard(q, stream, check=check) q.expect('dbus-return', method='SetAvatar')
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(q, bus, conn, stream): expect_and_handle_get_vcard(q, stream) self_handle = conn.Properties.Get(cs.CONN, "SelfHandle") conn.Aliasing.SetAliases({self_handle: 'lala'}) expect_and_handle_set_vcard(q, stream) event = q.expect('dbus-signal', signal='AliasesChanged', args=[[(self_handle, u'lala')]]) room_jid = '*****@*****.**' # muc stream tube call_async( q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: room_jid }) gfc, _, _ = q.expect_many( EventPattern('dbus-signal', signal='GroupFlagsChanged'), EventPattern( 'dbus-signal', signal='MembersChangedDetailed', predicate=lambda e: e.args[0] == [] and # added e.args[1] == [] and # removed e.args[2] == [] and # local pending len(e.args[3]) == 1 and # remote pending e.args[4].get('actor', 0) == 0 and e.args[4].get( 'change-reason', 0) == 0 and e.args[4]['contact-ids'][e.args[ 3][0]] == '[email protected]/lala'), EventPattern('stream-presence', to='%s/lala' % room_jid)) assert gfc.args[1] == 0 # Send presence for other member of room. stream.send(make_muc_presence('owner', 'moderator', room_jid, 'bob')) # Send presence for own membership of room. stream.send(make_muc_presence('none', 'participant', room_jid, 'lala')) event = q.expect( 'dbus-signal', signal='MembersChangedDetailed', predicate=lambda e: len(e.args[0]) == 2 and # added e.args[1] == [] and # removed e.args[2] == [] and # local pending e.args[3] == [] and # remote pending e.args[4].get('actor', 0) == 0 and e.args[4].get('change-reason', 0) == 0 and set([e.args[4]['contact-ids'][h] for h in e.args[0]]) == set( ['[email protected]/lala', '[email protected]/bob'])) event = q.expect('dbus-return', method='CreateChannel')
def test(q, bus, conn, stream): expect_and_handle_get_vcard(q, stream) def check_vcard(vcard): for e in vcard.elements(): if e.name == 'NICKNAME': assert str(e) == 'Some Guy', e.toXml() return assert False, vcard.toXml() expect_and_handle_set_vcard(q, stream, check_vcard)
def test(q, bus, conn, stream): expect_and_handle_get_vcard(q, stream) # Ensure that Gabble's actually got the initial vCard reply; if it hasn't # processed it by the time we call SetAliases, the latter will wait for it # to reply and then set immediately. sync_stream(q, stream) handle = conn.Properties.Get(cs.CONN, "SelfHandle") call_async(q, conn.Aliasing, 'SetAliases', {handle: 'Some Guy'}) # SetAliases requests vCard v1 get_vcard_event = q.expect('stream-iq', query_ns=ns.VCARD_TEMP, query_name='vCard', iq_type='get') iq = get_vcard_event.stanza vcard = iq.firstChildElement() assert vcard.name == 'vCard', vcard.toXml() call_async(q, conn.Avatars, 'SetAvatar', 'hello', 'image/png') # We don't expect Gabble to send a second vCard request, since there's one # outstanding. But we want to ensure that SetAvatar reaches Gabble before # the empty vCard does. sync_dbus(bus, q, conn) # Send back current empty vCard result = make_result_iq(stream, iq) # result already includes the <vCard/> from the query, which is all we need stream.send(result) def has_nickname_and_photo(vcard): nicknames = xpath.queryForNodes('/vCard/NICKNAME', vcard) assert nicknames is not None assert len(nicknames) == 1 assert str(nicknames[0]) == 'Some Guy' photos = xpath.queryForNodes('/vCard/PHOTO', vcard) assert photos is not None and len(photos) == 1, repr(photos) types = xpath.queryForNodes('/PHOTO/TYPE', photos[0]) binvals = xpath.queryForNodes('/PHOTO/BINVAL', photos[0]) assert types is not None and len(types) == 1, repr(types) assert binvals is not None and len(binvals) == 1, repr(binvals) assert str(types[0]) == 'image/png' got = str(binvals[0]).strip() exp = base64.b64encode('hello') assertEquals(exp, got) # Now Gabble should set a new vCard with both of the above changes. expect_and_handle_set_vcard(q, stream, has_nickname_and_photo)
def test(q, bus, conn, stream): conn.Connect() expect_and_handle_get_vcard(q, stream) # Ensure that Gabble's actually got the initial vCard reply; if it hasn't # processed it by the time we call SetAliases, the latter will wait for it # to reply and then set immediately. sync_stream(q, stream) handle = conn.GetSelfHandle() call_async(q, conn.Aliasing, 'SetAliases', {handle: 'Some Guy'}) # SetAliases requests vCard v1 get_vcard_event = q.expect('stream-iq', query_ns=ns.VCARD_TEMP, query_name='vCard', iq_type='get') iq = get_vcard_event.stanza vcard = iq.firstChildElement() assert vcard.name == 'vCard', vcard.toXml() call_async(q, conn.Avatars, 'SetAvatar', 'hello', 'image/png') # We don't expect Gabble to send a second vCard request, since there's one # outstanding. But we want to ensure that SetAvatar reaches Gabble before # the empty vCard does. sync_dbus(bus, q, conn) # Send back current empty vCard result = make_result_iq(stream, iq) # result already includes the <vCard/> from the query, which is all we need stream.send(result) def has_nickname_and_photo(vcard): nicknames = xpath.queryForNodes('/vCard/NICKNAME', vcard) assert nicknames is not None assert len(nicknames) == 1 assert str(nicknames[0]) == 'Some Guy' photos = xpath.queryForNodes('/vCard/PHOTO', vcard) assert photos is not None and len(photos) == 1, repr(photos) types = xpath.queryForNodes('/PHOTO/TYPE', photos[0]) binvals = xpath.queryForNodes('/PHOTO/BINVAL', photos[0]) assert types is not None and len(types) == 1, repr(types) assert binvals is not None and len(binvals) == 1, repr(binvals) assert str(types[0]) == 'image/png' got = str(binvals[0]) exp = base64.b64encode('hello') assert got == exp, (got, exp) # Now Gabble should set a new vCard with both of the above changes. expect_and_handle_set_vcard(q, stream, has_nickname_and_photo)
def test(q, bus, conn, stream): expect_and_handle_get_vcard(q, stream) self_handle = conn.Properties.Get(cs.CONN, "SelfHandle") conn.Aliasing.SetAliases({self_handle: 'lala'}) expect_and_handle_set_vcard(q, stream) event = q.expect('dbus-signal', signal='AliasesChanged', args=[[(self_handle, u'lala')]]) room_jid = '*****@*****.**' # muc stream tube call_async(q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: room_jid}) gfc, _, _ = q.expect_many( EventPattern('dbus-signal', signal='GroupFlagsChanged'), EventPattern('dbus-signal', signal='MembersChangedDetailed', predicate=lambda e: e.args[0] == [] and # added e.args[1] == [] and # removed e.args[2] == [] and # local pending len(e.args[3]) == 1 and # remote pending e.args[4].get('actor', 0) == 0 and e.args[4].get('change-reason', 0) == 0 and e.args[4]['contact-ids'][e.args[3][0]] == '[email protected]/lala'), EventPattern('stream-presence', to='%s/lala' % room_jid)) assert gfc.args[1] == 0 # Send presence for other member of room. stream.send(make_muc_presence('owner', 'moderator', room_jid, 'bob')) # Send presence for own membership of room. stream.send(make_muc_presence('none', 'participant', room_jid, 'lala')) event = q.expect('dbus-signal', signal='MembersChangedDetailed', predicate=lambda e: len(e.args[0]) == 2 and # added e.args[1] == [] and # removed e.args[2] == [] and # local pending e.args[3] == [] and # remote pending e.args[4].get('actor', 0) == 0 and e.args[4].get('change-reason', 0) == 0 and set([e.args[4]['contact-ids'][h] for h in e.args[0]]) == set(['[email protected]/lala', '[email protected]/bob'])) event = q.expect('dbus-return', method='CreateChannel')
def test(q, bus, conn, stream): expect_get_and_send_item_not_found(q, stream) sync_stream(q, stream) call_async( q, conn.Avatars, 'SetAvatar', 'Guy.brush', 'image/x-mighty-pirate') # Gabble checks again, but we still don't have a vCard expect_get_and_send_item_not_found(q, stream) # Never mind! It creates a new one. expect_and_handle_set_vcard(q, stream) q.expect('dbus-return', method='SetAvatar')
def test(q, bus, conn, stream): photo = current_vcard.addElement((None, 'PHOTO')) photo.addElement((None, 'TYPE')).addContent('image/fake') photo.addElement((None, 'BINVAL')).addContent('NYANYANYANYANYAN') call_async(q, conn.Avatars, 'ClearAvatar') expect_and_handle_get_vcard(q, stream) def check(vcard): assert len(vcard.children) == 0, vcard.toXml() expect_and_handle_set_vcard(q, stream, check=check) q.expect('dbus-return', method='ClearAvatar')
def test(q, bus, conn, stream): self_handle = conn.Properties.Get(cs.CONN, "SelfHandle") 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 = next(vCard.elements(uri=ns.VCARD_TEMP, name='NICKNAME')) 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(q, bus, conn, stream): conn.Connect() expect_and_handle_get_vcard(q, stream) self_handle = conn.GetSelfHandle() conn.Aliasing.SetAliases({self_handle: 'lala'}) expect_and_handle_set_vcard(q, stream) event = q.expect('dbus-signal', signal='AliasesChanged', args=[[(self_handle, u'lala')]]) room_jid = '*****@*****.**' room_handle = request_muc_handle(q, conn, stream, room_jid) call_async(q, conn, 'RequestChannel', cs.CHANNEL_TYPE_TEXT, cs.HT_ROOM, room_handle, True) gfc, _, _ = q.expect_many( EventPattern('dbus-signal', signal='GroupFlagsChanged'), EventPattern('dbus-signal', signal='MembersChanged', args=[u'', [], [], [], [2], 0, 0]), EventPattern('stream-presence', to='%s/lala' % room_jid)) assert gfc.args[1] == 0 # Send presence for other member of room. stream.send(make_muc_presence('owner', 'moderator', room_jid, 'bob')) # Send presence for own membership of room. stream.send(make_muc_presence('none', 'participant', room_jid, 'lala')) event = q.expect('dbus-signal', signal='MembersChanged', args=[u'', [2, 3], [], [], [], 0, 0]) assert conn.InspectHandles(1, [2]) == ['[email protected]/lala'] assert conn.InspectHandles(1, [3]) == ['[email protected]/bob'] event = q.expect('dbus-return', method='RequestChannel')
def test(q, bus, conn, stream): self_handle = conn.Properties.Get(cs.CONN, "SelfHandle") # When Gabble initially requests its avatar from the server, it discovers # it has none. expect_and_handle_get_vcard(q, stream) handle, signalled_token = q.expect('dbus-signal', signal='AvatarUpdated').args assertEquals(self_handle, handle) assertEquals('', signalled_token) # The user sets an avatar. call_async(q, conn.Avatars, 'SetAvatar', AVATAR_1_DATA, AVATAR_1_MIME_TYPE) expect_and_handle_get_vcard(q, stream) expect_and_handle_set_vcard(q, stream) # It's signalled on D-Bus … set_ret, avatar_updated = q.expect_many( EventPattern('dbus-return', method='SetAvatar'), EventPattern('dbus-signal', signal='AvatarUpdated'), ) returned_token, = set_ret.value handle, signalled_token = avatar_updated.args assertEquals(self_handle, handle) assertEquals(returned_token, signalled_token) # … and also on XMPP. broadcast = q.expect('stream-presence', to=None) broadcast_hash = extract_hash_from_presence(broadcast.stanza) assertEquals(AVATAR_1_SHA1, broadcast_hash) # If applications ask Gabble for information about the user's own avatar, # it should be able to answer. (Strictly speaking, expecting Gabble to know # the avatar data is risky because Gabble discards cached vCards after a # while, but we happen to know it takes 20 seconds or so for that to # happen.) known = conn.Avatars.GetKnownAvatarTokens([self_handle]) assertEquals({self_handle: signalled_token}, known) conn.Avatars.RequestAvatars([self_handle]) retrieved = q.expect('dbus-signal', signal='AvatarRetrieved') handle, token, data, mime_type = retrieved.args assertEquals(self_handle, handle) assertEquals(signalled_token, token) assertEquals(AVATAR_1_DATA, data) assertEquals(AVATAR_1_MIME_TYPE, mime_type) # Well, that was quite easy. How about we join a MUC? XEP-0153 §4.1 says: # If a client supports the protocol defined herein, it […] SHOULD # also include the update child in directed presence stanzas (e.g., # directed presence sent when joining Multi-User Chat [5] rooms). # — http://xmpp.org/extensions/xep-0153.html#bizrules-presence join_event = try_to_join_muc(q, bus, conn, stream, MUC) directed_hash = extract_hash_from_presence(join_event.stanza) assertEquals(AVATAR_1_SHA1, directed_hash) # There are two others in the MUC: fredrik has no avatar, wendy has an # avatar. We, of course, have our own avatar. stream.send(make_muc_presence('none', 'participant', MUC, 'fredrik')) stream.send(make_muc_presence('none', 'participant', MUC, 'wendy', photo=AVATAR_2_SHA1)) stream.send(make_muc_presence('owner', 'moderator', MUC, 'test', photo=AVATAR_1_SHA1)) path, _ = q.expect('dbus-return', method='CreateChannel').value chan = wrap_channel(bus.get_object(conn.bus_name, path), 'Text') members = chan.Properties.Get(cs.CHANNEL_IFACE_GROUP, 'Members') assertLength(3, members) fredrik, wendy, muc_self_handle = conn.get_contact_handles_sync( ['%s/%s' % (MUC, x) for x in ["fredrik", "wendy", "test"]]) known = conn.Avatars.GetKnownAvatarTokens(members) # <https://bugs.freedesktop.org/show_bug.cgi?id=32017>: this assertion # failed, the MUC self handle's token was the empty string. assertEquals(AVATAR_1_SHA1, known[muc_self_handle]) assertEquals(AVATAR_2_SHA1, known[wendy]) assertEquals('', known[fredrik]) # 'k, cool. Wendy loves our avatar and switches to it. stream.send(make_muc_presence('none', 'participant', MUC, 'wendy', photo=AVATAR_1_SHA1)) # Okay this is technically assuming that we just expose the SHA1 sums # directly which is not guaranteed … but we do. q.expect('dbus-signal', signal='AvatarUpdated', args=[wendy, AVATAR_1_SHA1]) # Fredrik switches too. stream.send(make_muc_presence('none', 'participant', MUC, 'fredrik', photo=AVATAR_1_SHA1)) q.expect('dbus-signal', signal='AvatarUpdated', args=[fredrik, AVATAR_1_SHA1]) # And we switch to some other avatar. Gabble should update its vCard, and # then update its MUC presence (which the test, acting as the MUC server, # must echo). call_async(q, conn.Avatars, 'SetAvatar', AVATAR_2_DATA, AVATAR_2_MIME_TYPE) expect_and_handle_get_vcard(q, stream) expect_and_handle_set_vcard(q, stream) muc_presence = q.expect('stream-presence', to=('%s/test' % MUC)) directed_hash = extract_hash_from_presence(muc_presence.stanza) stream.send(make_muc_presence('owner', 'moderator', MUC, 'test', photo=directed_hash)) # Gabble should signal an avatar update for both our global self-handle and # our MUC self-handle. (The first of these of course does not need to wait # for the MUC server to echo our presence.) q.expect_many( EventPattern('dbus-signal', signal='AvatarUpdated', args=[self_handle, AVATAR_2_SHA1]), EventPattern('dbus-signal', signal='AvatarUpdated', args=[muc_self_handle, AVATAR_2_SHA1]), )
def test(q, bus, conn, stream): self_handle = conn.Properties.Get(cs.CONN, "SelfHandle") # When Gabble initially requests its avatar from the server, it discovers # it has none. expect_and_handle_get_vcard(q, stream) handle, signalled_token = q.expect('dbus-signal', signal='AvatarUpdated').args assertEquals(self_handle, handle) assertEquals('', signalled_token) # The user sets an avatar. call_async(q, conn.Avatars, 'SetAvatar', AVATAR_1_DATA, AVATAR_1_MIME_TYPE) expect_and_handle_get_vcard(q, stream) expect_and_handle_set_vcard(q, stream) # It's signalled on D-Bus … set_ret, avatar_updated = q.expect_many( EventPattern('dbus-return', method='SetAvatar'), EventPattern('dbus-signal', signal='AvatarUpdated'), ) returned_token, = set_ret.value handle, signalled_token = avatar_updated.args assertEquals(self_handle, handle) assertEquals(returned_token, signalled_token) # … and also on XMPP. broadcast = q.expect('stream-presence', to=None) broadcast_hash = extract_hash_from_presence(broadcast.stanza) assertEquals(AVATAR_1_SHA1, broadcast_hash) # If applications ask Gabble for information about the user's own avatar, # it should be able to answer. (Strictly speaking, expecting Gabble to know # the avatar data is risky because Gabble discards cached vCards after a # while, but we happen to know it takes 20 seconds or so for that to # happen.) known = conn.Avatars.GetKnownAvatarTokens([self_handle]) assertEquals({self_handle: signalled_token}, known) conn.Avatars.RequestAvatars([self_handle]) retrieved = q.expect('dbus-signal', signal='AvatarRetrieved') handle, token, data, mime_type = retrieved.args assertEquals(self_handle, handle) assertEquals(signalled_token, token) assertEquals(AVATAR_1_DATA, data) assertEquals(AVATAR_1_MIME_TYPE, mime_type) # Well, that was quite easy. How about we join a MUC? XEP-0153 §4.1 says: # If a client supports the protocol defined herein, it […] SHOULD # also include the update child in directed presence stanzas (e.g., # directed presence sent when joining Multi-User Chat [5] rooms). # — http://xmpp.org/extensions/xep-0153.html#bizrules-presence join_event = try_to_join_muc(q, bus, conn, stream, MUC) directed_hash = extract_hash_from_presence(join_event.stanza) assertEquals(AVATAR_1_SHA1, directed_hash) # There are two others in the MUC: fredrik has no avatar, wendy has an # avatar. We, of course, have our own avatar. stream.send(make_muc_presence('none', 'participant', MUC, 'fredrik')) stream.send( make_muc_presence('none', 'participant', MUC, 'wendy', photo=AVATAR_2_SHA1)) stream.send( make_muc_presence('owner', 'moderator', MUC, 'test', photo=AVATAR_1_SHA1)) path, _ = q.expect('dbus-return', method='CreateChannel').value chan = wrap_channel(bus.get_object(conn.bus_name, path), 'Text') members = chan.Properties.Get(cs.CHANNEL_IFACE_GROUP, 'Members') assertLength(3, members) fredrik, wendy, muc_self_handle = conn.get_contact_handles_sync( ['%s/%s' % (MUC, x) for x in ["fredrik", "wendy", "test"]]) known = conn.Avatars.GetKnownAvatarTokens(members) # <https://bugs.freedesktop.org/show_bug.cgi?id=32017>: this assertion # failed, the MUC self handle's token was the empty string. assertEquals(AVATAR_1_SHA1, known[muc_self_handle]) assertEquals(AVATAR_2_SHA1, known[wendy]) assertEquals('', known[fredrik]) # 'k, cool. Wendy loves our avatar and switches to it. stream.send( make_muc_presence('none', 'participant', MUC, 'wendy', photo=AVATAR_1_SHA1)) # Okay this is technically assuming that we just expose the SHA1 sums # directly which is not guaranteed … but we do. q.expect('dbus-signal', signal='AvatarUpdated', args=[wendy, AVATAR_1_SHA1]) # Fredrik switches too. stream.send( make_muc_presence('none', 'participant', MUC, 'fredrik', photo=AVATAR_1_SHA1)) q.expect('dbus-signal', signal='AvatarUpdated', args=[fredrik, AVATAR_1_SHA1]) # And we switch to some other avatar. Gabble should update its vCard, and # then update its MUC presence (which the test, acting as the MUC server, # must echo). call_async(q, conn.Avatars, 'SetAvatar', AVATAR_2_DATA, AVATAR_2_MIME_TYPE) expect_and_handle_get_vcard(q, stream) expect_and_handle_set_vcard(q, stream) muc_presence = q.expect('stream-presence', to=('%s/test' % MUC)) directed_hash = extract_hash_from_presence(muc_presence.stanza) stream.send( make_muc_presence('owner', 'moderator', MUC, 'test', photo=directed_hash)) # Gabble should signal an avatar update for both our global self-handle and # our MUC self-handle. (The first of these of course does not need to wait # for the MUC server to echo our presence.) q.expect_many( EventPattern('dbus-signal', signal='AvatarUpdated', args=[self_handle, AVATAR_2_SHA1]), EventPattern('dbus-signal', signal='AvatarUpdated', args=[muc_self_handle, AVATAR_2_SHA1]), )