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(q, bus, conn, stream): conn.Connect() event = q.expect('stream-iq', query_ns=ns.ROSTER) event.stanza['type'] = 'result' item = event.query.addElement('item') item['jid'] = '*****@*****.**' item['subscription'] = 'both' item = event.query.addElement('item') item['jid'] = '*****@*****.**' item['subscription'] = 'from' item = event.query.addElement('item') item['jid'] = '*****@*****.**' item['subscription'] = 'to' 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 expect_list_channel(q, bus, conn, 'publish', ['*****@*****.**', '*****@*****.**']) expect_list_channel(q, bus, conn, 'subscribe', ['*****@*****.**', '*****@*****.**']) expect_list_channel(q, bus, conn, 'stored', ['*****@*****.**', '*****@*****.**', '*****@*****.**'])
def test(q, bus, conn, stream): conn.Connect() event = q.expect('stream-iq', query_ns=ns.ROSTER) event.stanza['type'] = 'result' item = event.query.addElement('item') item['jid'] = '*****@*****.**' item['subscription'] = 'both' group = item.addElement('group', content='women') group = item.addElement('group', content='affected-by-fdo-12791') # This is a broken roster - Amy appears twice. This should only happen # if the server is somehow buggy. This was my initial attempt at # reproducing fd.o #12791 - I doubt it's very realistic, but we shouldn't # assert, regardless of what input we get! item = event.query.addElement('item') item['jid'] = '*****@*****.**' item['subscription'] = 'both' group = item.addElement('group', content='women') item = event.query.addElement('item') item['jid'] = '*****@*****.**' item['subscription'] = 'from' group = item.addElement('group', content='men') # This is what was *actually* strange about the #12791 submitter's roster - # Bob appears, fully subscribed, but also there's an attempt to subscribe # to one of Bob's resources. We now ignore such items item = event.query.addElement('item') item['jid'] = '[email protected]/Resource' item['subscription'] = 'none' item['ask'] = 'subscribe' item = event.query.addElement('item') item['jid'] = '*****@*****.**' item['subscription'] = 'to' group = item.addElement('group', content='men') 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 expect_list_channel(q, bus, conn, 'publish', ['*****@*****.**', '*****@*****.**']) expect_list_channel(q, bus, conn, 'subscribe', ['*****@*****.**', '*****@*****.**']) expect_list_channel(q, bus, conn, 'stored', ['*****@*****.**', '*****@*****.**', '*****@*****.**']) _expect_group_channel(q, bus, conn, 'women', ['*****@*****.**']) _expect_group_channel(q, bus, conn, 'affected-by-fdo-12791', []) _expect_group_channel(q, bus, conn, 'men', ['*****@*****.**', '*****@*****.**'])
def test(q, bus, conn, stream, remove, local): conn.Connect() # Gabble asks for the roster; the server sends back an empty roster. event = q.expect('stream-iq', query_ns=ns.ROSTER) event.stanza['type'] = 'result' stream.send(event.stanza) publish = expect_list_channel(q, bus, conn, 'publish', []) subscribe = expect_list_channel(q, bus, conn, 'subscribe', []) stored = expect_list_channel(q, bus, conn, 'stored', []) h = conn.RequestHandles(cs.HT_CONTACT, [jid])[0] # Another client logged into our account (Gajim, say) wants to subscribe to # Marco's presence. First, per RFC 3921 it 'SHOULD perform a "roster set" # for the new roster item': # # <iq type='set'> # <query xmlns='jabber:iq:roster'> # <item jid='*****@*****.**'/> # </query> # </iq> # # 'As a result, the user's server (1) MUST initiate a roster push for the # new roster item to all available resources associated with this user that # have requested the roster, setting the 'subscription' attribute to a # value of "none"': iq = IQ(stream, "set") item = iq.addElement((ns.ROSTER, 'query')).addElement('item') item['jid'] = jid item['subscription'] = 'none' stream.send(iq) # In response, Gabble should add Marco to stored: q.expect('dbus-signal', signal='MembersChanged', args=['', [h], [], [], [], 0, 0], path=stored.object_path) # Gajim sends a <presence type='subscribe'/> to Marco. 'As a result, the # user's server MUST initiate a second roster push to all of the user's # available resources that have requested the roster, setting [...] # ask='subscribe' attribute in the roster item [for Marco]: iq = IQ(stream, "set") item = iq.addElement((ns.ROSTER, 'query')).addElement('item') item['jid'] = jid item['subscription'] = 'none' item['ask'] = 'subscribe' stream.send(iq) # In response, Gabble should add Marco to subscribe:remote-pending: q.expect('dbus-signal', signal='MembersChanged', args=['', [], [], [], [h], 0, 0], path=subscribe.object_path) # The user decides that they don't care what Marco's baking after all # (maybe they read his blog instead?) and: if remove: # ...removes him from the roster... if local: # ...by telling Gabble to remove him from stored. stored.Group.RemoveMembers([h], '') event = q.expect('stream-iq', iq_type='set', query_ns=ns.ROSTER) item = event.query.firstChildElement() assertEquals(jid, item['jid']) assertEquals('remove', item['subscription']) else: # ...using the other client. pass # The server must 'inform all of the user's available resources that # have requested the roster of the roster item removal': iq = IQ(stream, "set") item = iq.addElement((ns.ROSTER, 'query')).addElement('item') item['jid'] = jid item['subscription'] = 'remove' # When Marco found this bug, this roster update included: item['ask'] = 'subscribe' # which is a bit weird: I don't think the server should send that when # the contact's being removed. I think Gabble should ignore it, so I'm # including it in the test. stream.send(iq) # In response, Gabble should announce that Marco has been removed from # subscribe:remote-pending and stored:members: q.expect_many( EventPattern('dbus-signal', signal='MembersChanged', args=['', [], [h], [], [], 0, 0], path=subscribe.object_path), EventPattern('dbus-signal', signal='MembersChanged', args=['', [], [h], [], [], 0, 0], path=stored.object_path), ) else: # ...rescinds the subscription request... if local: # ...by telling Gabble to remove him from 'subscribe'. subscribe.Group.RemoveMembers([h], '') q.expect('stream-presence', to=jid, presence_type='unsubscribe') else: # ...in the other client. pass # In response, the server sends a roster update: iq = IQ(stream, "set") item = iq.addElement((ns.ROSTER, 'query')).addElement('item') item['jid'] = jid item['subscription'] = 'none' # no ask='subscribe' any more. stream.send(iq) # In response, Gabble should announce that Marco has been removed from # subscribe:remote-pending. It shouldn't wait for the <presence # type='unsubscribed'/> ack before doing so: empirical tests reveal # that it's never delivered. q.expect('dbus-signal', signal='MembersChanged', args=['', [], [h], [], [], 0, 0], path=subscribe.object_path)