diff options
Diffstat (limited to 'tests/twisted/roster/test-google-roster.py')
-rw-r--r-- | tests/twisted/roster/test-google-roster.py | 240 |
1 files changed, 90 insertions, 150 deletions
diff --git a/tests/twisted/roster/test-google-roster.py b/tests/twisted/roster/test-google-roster.py index 257661b6e..cff985dc1 100644 --- a/tests/twisted/roster/test-google-roster.py +++ b/tests/twisted/roster/test-google-roster.py @@ -7,7 +7,7 @@ from gabbletest import ( acknowledge_iq, exec_test, sync_stream, make_result_iq, GoogleXmlStream, ) from rostertest import ( - expect_contact_list_signals, check_contact_list_signals, + check_contact_roster, contacts_changed_predicate, blocked_contacts_changed_predicate, ) from servicetest import ( call_async, sync_dbus, EventPattern, @@ -43,18 +43,6 @@ def add_roster_item(query, contact, state, ask, attrs={}): return item -def is_stored(event): - return event.path.endswith('/stored') - -def is_subscribe(event): - return event.path.endswith('/subscribe') - -def is_publish(event): - return event.path.endswith('/publish') - -def is_deny(event): - return event.path.endswith('/deny') - def test_inital_roster(q, bus, conn, stream): """ This part of the test checks that Gabble correctly alters on which lists @@ -104,44 +92,36 @@ def test_inital_roster(q, bus, conn, stream): # <https://bugs.launchpad.net/ubuntu/+source/telepathy-gabble/+bug/398293>, # where Gabble was incorrectly hiding valid contacts. - mutually_subscribed_contacts = ['lp-bug-398293@gmail.com', - 'blocked-but-subscribed@boards.ca', - 'music-is-math@boards.ca'] - rp_contacts = ['this-is-a-jid@badger.com'] + contacts = [ + ('lp-bug-398293@gmail.com', cs.SUBSCRIPTION_STATE_YES, cs.SUBSCRIPTION_STATE_YES, ''), + ('blocked-but-subscribed@boards.ca', cs.SUBSCRIPTION_STATE_YES, cs.SUBSCRIPTION_STATE_YES, ''), + ('music-is-math@boards.ca', cs.SUBSCRIPTION_STATE_YES, cs.SUBSCRIPTION_STATE_YES, ''), + ('this-is-a-jid@badger.com', cs.SUBSCRIPTION_STATE_ASK, cs.SUBSCRIPTION_STATE_NO, '') + ] + blocked_contacts = ['blocked-but-subscribed@boards.ca', 'blocked-and-no-sub@boards.ca', 'music-is-math@boards.ca'] - pairs = expect_contact_list_signals(q, bus, conn, - ['publish', 'subscribe', 'stored', 'deny']) - - publish = check_contact_list_signals(q, bus, conn, pairs.pop(0), - cs.HT_LIST, 'publish', mutually_subscribed_contacts) - subscribe = check_contact_list_signals(q, bus, conn, pairs.pop(0), - cs.HT_LIST, 'subscribe', mutually_subscribed_contacts, - rp_contacts=rp_contacts) - stored = check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_LIST, - 'stored', mutually_subscribed_contacts + rp_contacts) - deny = check_contact_list_signals(q, bus, conn, pairs.pop(0), cs.HT_LIST, - 'deny', blocked_contacts) - - assertLength(0, pairs) # i.e. we've checked all of them - - return (publish, subscribe, stored, deny) + q.expect_many( + EventPattern('dbus-signal', signal='ContactsChangedWithID', + predicate=lambda e: contacts_changed_predicate(e, conn, contacts)), + EventPattern('dbus-signal', signal='BlockedContactsChanged', + predicate=lambda e: blocked_contacts_changed_predicate(e, blocked_contacts, [])), + ) -def test_flickering(q, bus, conn, stream, subscribe): +def test_flickering(q, bus, conn, stream): """ Google's server is buggy; when asking to subscribe to somebody, the subscription state transitions "flicker" sometimes. Here, we test that Gabble is suppressing the flickers. """ - self_handle = conn.GetSelfHandle() contact = 'bob@foo.com' - handle = conn.RequestHandles(cs.HT_CONTACT, ['bob@foo.com'])[0] + handle = conn.get_contact_handle_sync('bob@foo.com') # request subscription - call_async(q, subscribe.Group, 'AddMembers', [handle], "") + call_async(q, conn.ContactList, 'RequestSubscription', [handle], '') event = q.expect('stream-iq', iq_type='set', query_ns=ns.ROSTER) item = event.query.firstChildElement() @@ -177,26 +157,16 @@ def test_flickering(q, bus, conn, stream, subscribe): # Gabble should report this update to the UI. q.expect_many( - EventPattern('dbus-signal', signal='MembersChanged', - args=['', [handle], [], [], [], 0, cs.GC_REASON_NONE], - predicate=is_stored), - EventPattern('dbus-signal', signal='MembersChanged', - args=['', [], [], [], [handle], self_handle, cs.GC_REASON_NONE], - predicate=is_subscribe), - EventPattern('dbus-signal', signal='ContactsChanged', + EventPattern('dbus-signal', signal='ContactsChangedWithID', args=[{handle: (cs.SUBSCRIPTION_STATE_ASK, cs.SUBSCRIPTION_STATE_NO, ''), - }, []]), + }, {handle: contact}, {}]), ) # Gabble shouldn't report any changes to subscribe or stored's members in # response to the next two roster updates. change_events = [ - EventPattern('dbus-signal', signal='MembersChanged', - predicate=is_subscribe), - EventPattern('dbus-signal', signal='MembersChanged', - predicate=is_stored), - EventPattern('dbus-signal', signal='ContactsChanged'), + EventPattern('dbus-signal', signal='ContactsChangedWithID'), ] q.forbid_events(change_events) @@ -235,15 +205,10 @@ def test_flickering(q, bus, conn, stream, subscribe): stream.send(presence) # Gabble should report this update to the UI. - q.expect_many( - EventPattern('dbus-signal', signal='MembersChanged', - args=['', [handle], [], [], [], handle, cs.GC_REASON_NONE], - predicate=is_subscribe), - EventPattern('dbus-signal', signal='ContactsChanged', + q.expect('dbus-signal', signal='ContactsChangedWithID', args=[{handle: (cs.SUBSCRIPTION_STATE_YES, cs.SUBSCRIPTION_STATE_NO, ''), - }, []]), - ) + }, {handle: contact}, {}]) # Gabble shouldn't report any changes to subscribe or stored's members in # response to the next two roster updates. @@ -265,7 +230,7 @@ def test_flickering(q, bus, conn, stream, subscribe): sync_dbus(bus, q, conn) q.unforbid_events(change_events) -def test_local_pending(q, bus, conn, stream, subscribe): +def test_local_pending(q, bus, conn, stream): """ When somebody asks to subscribe to us, Google sends the subscription request and then a roster update saying there is no subscription. @@ -274,7 +239,7 @@ def test_local_pending(q, bus, conn, stream, subscribe): """ contact = 'alice@foo.com' - handle = conn.RequestHandles(cs.HT_CONTACT, [contact])[0] + handle = conn.get_contact_handle_sync(contact) # Alice asks to subscribes to us presence = domish.Element(('jabber:client', 'presence')) @@ -282,19 +247,25 @@ def test_local_pending(q, bus, conn, stream, subscribe): presence['type'] = 'subscribe' stream.send(presence) - q.expect_many( - EventPattern('dbus-signal', signal='MembersChanged', - args=['', [], [], [handle], [], handle, cs.GC_REASON_NONE], - predicate=is_publish), - EventPattern('dbus-signal', signal='ContactsChanged', + q.expect('dbus-signal', signal='ContactsChangedWithID', args=[{handle: (cs.SUBSCRIPTION_STATE_NO, - cs.SUBSCRIPTION_STATE_ASK, '')}, []]), - ) + cs.SUBSCRIPTION_STATE_ASK, '')}, {handle: contact}, {}]) + + def alice_state_changed(e): + # check that Alice's publish and subscribe state isn't changed + changes, ids, removal = e.args + + subscription = changes.get(handle) + if subscription is None: + return False + + subscribe, publish, request = subscription + return subscribe != cs.SUBSCRIPTION_STATE_NO and publish != cs.SUBSCRIPTION_STATE_ASK # Now we send the spurious roster update with subscribe="none" and verify # that nothing happens to her publish state in reaction to that - change_event = EventPattern('dbus-signal', signal='MembersChanged', - predicate=is_publish) + change_event = EventPattern('dbus-signal', signal='ContactsChangedWithID', + predicate=alice_state_changed) q.forbid_events([change_event]) iq = make_set_roster_iq(stream, 'test@localhost/Resource', contact, @@ -312,14 +283,9 @@ def test_local_pending(q, bus, conn, stream, subscribe): presence['type'] = 'unsubscribe' stream.send(presence) - q.expect_many( - EventPattern('dbus-signal', signal='MembersChanged', - args=['', [], [handle], [], [], handle, cs.GC_REASON_NONE], - predicate=is_publish), - EventPattern('dbus-signal', signal='ContactsChanged', + q.expect('dbus-signal', signal='ContactsChangedWithID', args=[{handle: (cs.SUBSCRIPTION_STATE_NO, - cs.SUBSCRIPTION_STATE_REMOVED_REMOTELY, '')}, []]), - ) + cs.SUBSCRIPTION_STATE_REMOVED_REMOTELY, '')}, {handle: contact}, {}]) # Now we send a roster roster update with subscribe="none" again (which # doesn't change anything, it just confirms what we already knew) and @@ -342,7 +308,7 @@ remove_events = [ ) ] -def test_deny_simple(q, bus, conn, stream, stored, deny): +def test_deny_simple(q, bus, conn, stream): """ If we remove a blocked contact from 'stored', they shouldn't actually be removed from the roster: rather, we should cancel both subscription @@ -350,10 +316,12 @@ def test_deny_simple(q, bus, conn, stream, stored, deny): remaining on 'deny'. """ contact = 'blocked-but-subscribed@boards.ca' - handle = conn.RequestHandles(cs.HT_CONTACT, [contact])[0] - assertContains(handle, - stored.Properties.Get(cs.CHANNEL_IFACE_GROUP, "Members")) - call_async(q, stored.Group, 'RemoveMembers', [handle], "") + handle = conn.get_contact_handle_sync(contact) + + check_contact_roster(conn, contact, [], + cs.SUBSCRIPTION_STATE_YES, cs.SUBSCRIPTION_STATE_YES) + + call_async(q, conn.ContactList, 'RemoveContacts', [handle]) q.forbid_events(remove_events) @@ -362,7 +330,7 @@ def test_deny_simple(q, bus, conn, stream, stored, deny): presence_type='unsubscribe'), EventPattern('stream-presence', to=contact, presence_type='unsubscribed'), - EventPattern('dbus-return', method='RemoveMembers'), + EventPattern('dbus-return', method='RemoveContacts'), ) # Our server sends roster pushes in response to our unsubscribe and @@ -374,48 +342,39 @@ def test_deny_simple(q, bus, conn, stream, stored, deny): # As a result they should drop off all three non-deny lists, but not fall # off deny: - q.expect_many( - EventPattern('dbus-signal', signal='ContactsChanged', - args=[{}, [handle]]), - *[ EventPattern('dbus-signal', signal='MembersChanged', - args=['', [], [handle], [], [], 0, cs.GC_REASON_NONE], - predicate=p) - for p in [is_stored, is_subscribe, is_publish] - ]) + q.expect('dbus-signal', signal='ContactsChangedWithID', args=[{}, {}, {handle: contact}]) assertContains(handle, - deny.Properties.Get(cs.CHANNEL_IFACE_GROUP, "Members")) + conn.ContactBlocking.RequestBlockedContacts().keys()) q.unforbid_events(remove_events) -def test_deny_overlap_one(q, bus, conn, stream, subscribe, stored, deny): +def test_deny_overlap_one(q, bus, conn, stream): """ Here's a tricker case: blocking a contact, and then removing them before the server's responded to the block request. """ - self_handle = conn.GetSelfHandle() # As we saw in test_flickering(), we have a subscription to Bob, # everything's peachy. contact = 'bob@foo.com' - handle = conn.RequestHandles(cs.HT_CONTACT, ['bob@foo.com'])[0] + handle = conn.get_contact_handle_sync(contact) - assertContains(handle, - stored.Properties.Get(cs.CHANNEL_IFACE_GROUP, "Members")) - assertContains(handle, - subscribe.Properties.Get(cs.CHANNEL_IFACE_GROUP, "Members")) + check_contact_roster(conn, contact, [], + cs.SUBSCRIPTION_STATE_YES, cs.SUBSCRIPTION_STATE_NO) q.forbid_events(remove_events) # But then we have a falling out. In a blind rage, I block Bob: - call_async(q, deny.Group, 'AddMembers', [handle], "") + call_async(q, conn.ContactBlocking, 'BlockContacts', [handle], "") event = q.expect('stream-iq', query_ns=ns.ROSTER) item = event.query.firstChildElement() assertEquals(contact, item['jid']) assertEquals('B', item[(ns.GOOGLE_ROSTER, 't')]) - # Then — *before the server has replied* — I remove him from stored. - call_async(q, stored.Group, 'RemoveMembers', [handle], "") + # Then — *before the server has replied* — I remove him from the contact + # list. + call_async(q, conn.ContactList, 'RemoveContacts', [handle]) # subscription='remove' is still forbidden from above. So we sync to ensure # that Gabble's received RemoveMembers, and if it's going to send us a @@ -437,8 +396,8 @@ def test_deny_overlap_one(q, bus, conn, stream, subscribe, stored, deny): q.forbid_events(unsubscribed_events) q.expect_many( - EventPattern('dbus-signal', signal='MembersChanged', predicate=is_deny, - args=["", [handle], [], [], [], self_handle, 0]), + EventPattern('dbus-signal', signal='BlockedContactsChanged', + predicate=lambda e: blocked_contacts_changed_predicate(e, [contact], [])), EventPattern('stream-presence', to=contact, presence_type='unsubscribe'), ) @@ -448,26 +407,17 @@ def test_deny_overlap_one(q, bus, conn, stream, subscribe, stored, deny): "none", False, attrs={'gr:t': 'B'})) # As a result, Gabble makes Bob fall off subscribe and stored. - q.expect_many( - EventPattern('dbus-signal', signal='MembersChanged', - predicate=is_subscribe, - args=["", [], [handle], [], [], 0, 0]), - EventPattern('dbus-signal', signal='MembersChanged', - predicate=is_stored, - args=["", [], [handle], [], [], 0, 0]), - EventPattern('dbus-signal', signal='ContactsChanged', - args=[{}, [handle]]), - ) + q.expect('dbus-signal', signal='ContactsChangedWithID', + args=[{}, {}, {handle: contact}]) # And he should definitely still be on deny. That rascal. assertContains(handle, - deny.Properties.Get(cs.CHANNEL_IFACE_GROUP, "Members")) + conn.ContactBlocking.RequestBlockedContacts().keys()) q.unforbid_events(unsubscribed_events) q.unforbid_events(remove_events) -def test_deny_overlap_two(q, bus, conn, stream, - subscribe, publish, stored, deny): +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. @@ -475,14 +425,10 @@ def test_deny_overlap_two(q, bus, conn, stream, # This contact was on our roster when we started. contact = 'lp-bug-398293@gmail.com' - handle = conn.RequestHandles(cs.HT_CONTACT, [contact])[0] + handle = conn.get_contact_handle_sync(contact) - 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")) + 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) @@ -504,8 +450,8 @@ def test_deny_overlap_two(q, bus, conn, stream, ] q.forbid_events(patterns) - call_async(q, deny.Group, 'AddMembers', [handle], "") - call_async(q, stored.Group, 'RemoveMembers', [handle], "") + 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) @@ -524,27 +470,27 @@ def test_deny_overlap_two(q, bus, conn, stream, # And we're done. Clean up. q.unforbid_events(remove_events) -def test_deny_unblock_remove(q, bus, conn, stream, stored, deny): +def test_deny_unblock_remove(q, bus, conn, stream): """ 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 = 'music-is-math@boards.ca' - handle = conn.RequestHandles(cs.HT_CONTACT, [contact])[0] + 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, - deny.Properties.Get(cs.CHANNEL_IFACE_GROUP, "Members")) - assertContains(handle, - stored.Properties.Get(cs.CHANNEL_IFACE_GROUP, "Members")) + conn.ContactBlocking.RequestBlockedContacts().keys()) # Unblock them. - call_async(q, deny.Group, 'RemoveMembers', [handle], "") + call_async(q, conn.ContactBlocking, 'UnblockContacts', [handle]) roster_event = q.expect('stream-iq', query_ns=ns.ROSTER) item = roster_event.query.firstChildElement() @@ -554,7 +500,7 @@ def test_deny_unblock_remove(q, bus, conn, stream, stored, deny): # 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], "") + call_async(q, conn.ContactList, 'RemoveContacts', [handle]) # Make sure if the remove is sent prematurely, we catch it. sync_stream(q, stream) @@ -569,9 +515,8 @@ def test_deny_unblock_remove(q, bus, conn, stream, stored, deny): # 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), + EventPattern('dbus-signal', signal='BlockedContactsChanged', + predicate=lambda e: blocked_contacts_changed_predicate(e, [], [contact])), remove_events[0], ) item = roster_event.query.firstChildElement() @@ -581,11 +526,7 @@ def test_deny_unblock_remove(q, bus, conn, stream, stored, deny): '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_contact_blocking(q, bus, conn, stream, stored, deny): +def test_contact_blocking(q, bus, conn, stream): """test ContactBlocking API""" assertContains(cs.CONN_IFACE_CONTACT_BLOCKING, conn.Properties.Get(cs.CONN, "Interfaces")) @@ -596,16 +537,15 @@ def test_contact_blocking(q, bus, conn, stream, stored, deny): assertLength(3, blocked) def test(q, bus, conn, stream): - publish, subscribe, stored, deny = test_inital_roster(q, bus, conn, stream) - - test_flickering(q, bus, conn, stream, subscribe) - test_local_pending(q, bus, conn, stream, subscribe) - test_deny_simple(q, bus, conn, stream, stored, deny) - test_deny_overlap_one(q, bus, conn, stream, subscribe, stored, deny) - test_deny_overlap_two(q, bus, conn, stream, - subscribe, publish, stored, deny) - test_deny_unblock_remove(q, bus, conn, stream, stored, deny) - test_contact_blocking(q, bus, conn, stream, stored, deny) + test_inital_roster(q, bus, conn, stream) + + test_flickering(q, bus, conn, stream) + test_local_pending(q, bus, conn, stream) + test_deny_simple(q, bus, conn, stream) + test_deny_overlap_one(q, bus, conn, stream) + test_deny_overlap_two(q, bus, conn, stream) + test_deny_unblock_remove(q, bus, conn, stream) + test_contact_blocking(q, bus, conn, stream) if __name__ == '__main__': exec_test(test, protocol=GoogleXmlStream) |