def test(q, bus, conn, stream): room = '*****@*****.**' chan, path, props, disco = join_muc(q, bus, conn, stream, room, also_capture=[ EventPattern( 'stream-iq', iq_type='get', query_name='query', query_ns=ns.DISCO_INFO, to=room) ]) sync_dbus(bus, q, conn) # we call Close... call_async(q, chan, 'Close') q.expect('dbus-return', method='Close') # ...so gabble announces our unavailable presence to the MUC. event = q.expect('stream-presence', to=room + '/test') elem = event.stanza assertEquals('unavailable', elem['type']) # while we wait for the conference server to echo our unavailable # presence, we try and create the same channel again... call_async( q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: room }) # ...which should fail because the channel hasn't closed yet. q.expect('dbus-error', method='CreateChannel', name=cs.NOT_AVAILABLE) # the conference server finally gets around to echoing our # unavailable presence... echo_muc_presence(q, stream, elem, 'none', 'participant') # ...and only now is the channel closed. q.expect_many(EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='ChannelClosed')) # now that the channel has finally closed, let's try and request # it again which should succeed! chan, _, _ = join_muc(q, bus, conn, stream, room) # let's clear up though. chan.Close() event = q.expect('stream-presence', to=room + '/test') echo_muc_presence(q, stream, event.stanza, 'none', 'participant') q.expect_many(EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='ChannelClosed'))
def test(q, bus, conn, stream): room = '*****@*****.**' chan, path, props, disco = join_muc(q, bus, conn, stream, room, also_capture=[EventPattern('stream-iq', iq_type='get', query_name='query', query_ns=ns.DISCO_INFO, to=room)]) sync_dbus(bus, q, conn) # we call Close... call_async(q, chan, 'Close') q.expect('dbus-return', method='Close') # ...so gabble announces our unavailable presence to the MUC. event = q.expect('stream-presence', to=room + '/test') elem = event.stanza assertEquals('unavailable', elem['type']) # while we wait for the conference server to echo our unavailable # presence, we try and create the same channel again... call_async(q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: room }) # ...which should fail because the channel hasn't closed yet. q.expect('dbus-error', method='CreateChannel', name=cs.NOT_AVAILABLE) # the conference server finally gets around to echoing our # unavailable presence... echo_muc_presence(q, stream, elem, 'none', 'participant') # ...and only now is the channel closed. q.expect_many(EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='ChannelClosed')) # now that the channel has finally closed, let's try and request # it again which should succeed! chan, _, _ = join_muc(q, bus, conn, stream, room) # let's clear up though. chan.Close() event = q.expect('stream-presence', to=room + '/test') echo_muc_presence(q, stream, event.stanza, 'none', 'participant') q.expect_many(EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='ChannelClosed'))
def create_muji_channel (q, conn, stream, muc, in_muc = False): call_async (q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CALL, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: muc, cs.CALL_INITIAL_AUDIO: True, cs.CALL_INITIAL_AUDIO_NAME: "Audio", }, byte_arrays = True) if not in_muc: e = q.expect('stream-presence', to = muc + "/test") echo_muc_presence (q, stream, e.stanza, 'none', 'participant') e = q.expect ('dbus-return', method='CreateChannel') return e.value
def test_then_disconnect(q, bus, conn, stream): room = '*****@*****.**' chan, path, props, disco = join_muc(q, bus, conn, stream, room, also_capture=[ EventPattern( 'stream-iq', iq_type='get', query_name='query', query_ns=ns.DISCO_INFO, to=room) ]) sync_dbus(bus, q, conn) # we call Close... call_async(q, chan, 'Close') q.expect('dbus-return', method='Close') # ...so gabble announces our unavailable presence to the MUC. event = q.expect('stream-presence', to=room + '/test') elem = event.stanza assertEquals('unavailable', elem['type']) # oh no, but now we want to disconnect. call_async(q, conn, 'Disconnect') # the muc factory is told to close everything, so it does so # without announcing it to the channel because it does it # forcibly, so the channels disappear. q.expect_many(EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='ChannelClosed')) # now echo the unavailable presence; this shouldn't be handled # because the channel has already closed. echo_muc_presence(q, stream, elem, 'none', 'participant') # send the stream footer so that the connection thinks it's # property disconnected now. stream.sendFooter() # finally, Disconnect returns q.expect('dbus-return', method='Disconnect')
def expect_close(q, path, stream=None, jid=None): forbid_unavailable = [EventPattern('stream-presence', presence_type='unavailable', to='%s/test' % jid)] if jid is not None: e = q.expect_many(*forbid_unavailable)[0] echo_muc_presence(q, stream, e.stanza, 'none', 'participant') else: q.forbid_events(forbid_unavailable) q.expect_many(EventPattern('dbus-signal', signal='ChannelClosed', args=[path]), EventPattern('dbus-signal', signal='Closed', path=path)) if jid is not None: q.unforbid_events(forbid_unavailable)
def expect_close(q, path, stream=None, jid=None): forbid_unavailable = [ EventPattern('stream-presence', presence_type='unavailable', to='%s/test' % jid) ] if jid is not None: e = q.expect_many(*forbid_unavailable)[0] echo_muc_presence(q, stream, e.stanza, 'none', 'participant') else: q.forbid_events(forbid_unavailable) q.expect_many( EventPattern('dbus-signal', signal='ChannelClosed', args=[path]), EventPattern('dbus-signal', signal='Closed', path=path)) if jid is not None: q.unforbid_events(forbid_unavailable)
def create_muji_channel(q, conn, stream, muc, in_muc=False): call_async(q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_CALL, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: muc, cs.CALL_INITIAL_AUDIO: True, cs.CALL_INITIAL_AUDIO_NAME: "Audio", }, byte_arrays=True) if not in_muc: e = q.expect('stream-presence', to=muc + "/test") echo_muc_presence(q, stream, e.stanza, 'none', 'participant') e = q.expect('dbus-return', method='CreateChannel') return e.value
def test_then_disconnect(q, bus, conn, stream): room = '*****@*****.**' chan, path, props, disco = join_muc(q, bus, conn, stream, room, also_capture=[EventPattern('stream-iq', iq_type='get', query_name='query', query_ns=ns.DISCO_INFO, to=room)]) sync_dbus(bus, q, conn) # we call Close... call_async(q, chan, 'Close') q.expect('dbus-return', method='Close') # ...so gabble announces our unavailable presence to the MUC. event = q.expect('stream-presence', to=room + '/test') elem = event.stanza assertEquals('unavailable', elem['type']) # oh no, but now we want to disconnect. call_async(q, conn, 'Disconnect') # the muc factory is told to close everything, so it does so # without announcing it to the channel because it does it # forcibly, so the channels disappear. q.expect_many(EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='ChannelClosed')) # now echo the unavailable presence; this shouldn't be handled # because the channel has already closed. echo_muc_presence(q, stream, elem, 'none', 'participant') # send the stream footer so that the connection thinks it's # property disconnected now. stream.sendFooter() # finally, Disconnect returns q.expect('dbus-return', method='Disconnect')
assert removed == [bob_handle] names = tube_chan.Get(cs.CHANNEL_TYPE_DBUS_TUBE, 'DBusNames', dbus_interface=cs.PROPERTIES_IFACE) assert names == {tube_self_handle: my_bus_name} tube_chan.Channel.Close() _, _, event = q.expect_many( EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='ChannelClosed'), EventPattern('stream-presence', to='[email protected]/test', presence_type='unavailable')) # we must echo the MUC presence so the room will actually close # and we should wait to make sure gabble has actually parsed our # echo before trying to rejoin echo_muc_presence(q, stream, event.stanza, 'none', 'participant') sync_stream(q, stream) # rejoin the room call_async(q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: '*****@*****.**' }) q.expect('stream-presence', to='[email protected]/test') # Bob is in the room and in the tube bob_in_tube() # Send presence for own membership of room. stream.send(make_muc_presence('none', 'participant', muc, 'test'))
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) buddy_iface = dbus.Interface(conn, 'org.laptop.Telepathy.BuddyInfo') act_prop_iface = dbus.Interface(conn, 'org.laptop.Telepathy.ActivityProperties') bob_handle = conn.get_contact_handle_sync('bob@localhost') # Bob invites us to a chatroom, pre-seeding properties message = domish.Element(('jabber:client', 'message')) message['from'] = 'bob@localhost' message['to'] = 'test@localhost' properties = message.addElement((ns.OLPC_ACTIVITY_PROPS, 'properties')) properties['room'] = '*****@*****.**' properties['activity'] = 'foo_id' property = properties.addElement((None, 'property')) property['type'] = 'str' property['name'] = 'title' property.addContent('From the invitation') property = properties.addElement((None, 'property')) property['type'] = 'bool' property['name'] = 'private' property.addContent('1') stream.send(message) message = domish.Element((None, 'message')) message['from'] = '*****@*****.**' message['to'] = 'test@localhost' x = message.addElement((ns.MUC_USER, 'x')) invite = x.addElement((None, 'invite')) invite['from'] = 'bob@localhost' reason = invite.addElement((None, 'reason')) reason.addContent('No good reason') stream.send(message) event = q.expect('dbus-signal', signal='NewChannel') assert event.args[1] == cs.CHANNEL_TYPE_TEXT assert event.args[2] == 2 # handle type assert event.args[3] == 1 # handle room_handle = 1 text_chan = wrap_channel(bus.get_object(conn.bus_name, event.args[0]), 'Text') group_iface = text_chan.Group members = group_iface.GetAllMembers()[0] local_pending = group_iface.GetAllMembers()[1] remote_pending = group_iface.GetAllMembers()[2] assert len(members) == 1 assert conn.inspect_contact_sync(members[0]) == 'bob@localhost' bob_handle = members[0] assert len(local_pending) == 1 # FIXME: the username-part-is-nickname assumption assert conn.inspect_contact_sync(local_pending[0]) == \ '[email protected]/test' assert len(remote_pending) == 0 room_self_handle = text_chan.Properties.Get(cs.CHANNEL_IFACE_GROUP, "SelfHandle") assert room_self_handle == local_pending[0] # by now, we should have picked up the extra activity properties buddy_iface = dbus.Interface(conn, 'org.laptop.Telepathy.BuddyInfo') call_async(q, buddy_iface, 'GetActivities', bob_handle) event = q.expect('stream-iq', iq_type='get', to='bob@localhost') # Bob still has no (public) activities event.stanza['type'] = 'result' event.stanza['to'] = 'test@localhost' event.stanza['from'] = 'bob@localhost' stream.send(event.stanza) event = q.expect('dbus-return', method='GetActivities') assert event.value == ([('foo_id', room_handle)], ) props = act_prop_iface.GetProperties(room_handle) assert len(props) == 2 assert props['title'] == 'From the invitation' assert props['private'] == True # Now Bob changes the properties message = domish.Element(('jabber:client', 'message')) message['from'] = 'bob@localhost' message['to'] = 'test@localhost' properties = message.addElement((ns.OLPC_ACTIVITY_PROPS, 'properties')) properties['room'] = '*****@*****.**' properties['activity'] = 'foo_id' property = properties.addElement((None, 'property')) property['type'] = 'str' property['name'] = 'title' property.addContent('Mushroom, mushroom') property = properties.addElement((None, 'property')) property['type'] = 'bool' property['name'] = 'private' property.addContent('0') stream.send(message) event = q.expect('dbus-signal', signal='ActivityPropertiesChanged') assert event.args == [ room_handle, { 'title': 'Mushroom, mushroom', 'private': False } ] assert act_prop_iface.GetProperties(room_handle) == \ event.args[1] # OK, now accept the invitation call_async(q, group_iface, 'AddMembers', [room_self_handle], 'Oh, OK then') q.expect_many( EventPattern('stream-presence', to='[email protected]/test'), EventPattern('dbus-signal', signal='MembersChanged', args=[ '', [], [bob_handle], [], [room_self_handle], 0, cs.GC_REASON_INVITED ]), EventPattern('dbus-return', method='AddMembers'), ) # Send presence for own membership of room. stream.send( make_muc_presence('owner', 'moderator', '*****@*****.**', 'test')) event = q.expect('dbus-signal', signal='MembersChanged') assert event.args == ['', [room_self_handle], [], [], [], 0, 0] call_async(q, buddy_iface, 'SetActivities', [('foo_id', room_handle)]) event = q.expect('stream-iq', iq_type='set') # Now that it's not private, it'll go in my PEP event.stanza['type'] = 'result' event.stanza['to'] = 'test@localhost' event.stanza['from'] = 'test@localhost' stream.send(event.stanza) q.expect('dbus-return', method='SetActivities') # Bob changes the properties and tells the room he's done so message = domish.Element(('jabber:client', 'message')) message['from'] = '[email protected]/bob' message['to'] = '*****@*****.**' properties = message.addElement((ns.OLPC_ACTIVITY_PROPS, 'properties')) properties['activity'] = 'foo_id' property = properties.addElement((None, 'property')) property['type'] = 'str' property['name'] = 'title' property.addContent('Badger badger badger') property = properties.addElement((None, 'property')) property['type'] = 'bool' property['name'] = 'private' property.addContent('0') stream.send(message) event = q.expect('stream-iq', iq_type='set') message = event.stanza activities = xpath.queryForNodes('/iq/pubsub/publish/item/activities', message) assert (activities is not None and len(activities) == 1), repr(activities) assert activities[0].uri == ns.OLPC_ACTIVITY_PROPS properties = xpath.queryForNodes('/activities/properties', activities[0]) assert (properties is not None and len(properties) == 1), repr(properties) assert properties[0].uri == ns.OLPC_ACTIVITY_PROPS assert properties[0]['room'] == '*****@*****.**' assert properties[0]['activity'] == 'foo_id' property = xpath.queryForNodes('/properties/property', properties[0]) assert (property is not None and len(property) == 2), repr(property) seen = set() for p in property: seen.add(p['name']) if p['name'] == 'title': assert p['type'] == 'str' assert str(p) == 'Badger badger badger' elif p['name'] == 'private': assert p['type'] == 'bool' assert str(p) == '0' else: assert False, 'Unexpected property %s' % p['name'] assert 'title' in seen, seen assert 'private' in seen, seen event.stanza['type'] = 'result' event.stanza['to'] = 'test@localhost' event.stanza['from'] = 'test@localhost' stream.send(event.stanza) act_prop_iface = dbus.Interface(conn, 'org.laptop.Telepathy.ActivityProperties') # test sets the title and sets private back to True call_async(q, act_prop_iface, 'SetProperties', room_handle, { 'title': 'I can set the properties too', 'private': True }) event = q.expect('stream-message', to='*****@*****.**') message = event.stanza properties = xpath.queryForNodes('/message/properties', message) assert (properties is not None and len(properties) == 1), repr(properties) assert properties[0].uri == ns.OLPC_ACTIVITY_PROPS assert properties[0]['room'] == '*****@*****.**' assert properties[0]['activity'] == 'foo_id' property = xpath.queryForNodes('/properties/property', properties[0]) assert (property is not None and len(property) == 2), repr(property) seen = set() for p in property: seen.add(p['name']) if p['name'] == 'title': assert p['type'] == 'str' assert str(p) == 'I can set the properties too' elif p['name'] == 'private': assert p['type'] == 'bool' assert str(p) == '1' else: assert False, 'Unexpected property %s' % p['name'] assert 'title' in seen, seen assert 'private' in seen, seen event = q.expect('stream-iq', iq_type='set') event.stanza['type'] = 'result' event.stanza['to'] = 'test@localhost' event.stanza['from'] = 'test@localhost' stream.send(event.stanza) message = event.stanza activities = xpath.queryForNodes('/iq/pubsub/publish/item/activities', message) assert (activities is not None and len(activities) == 1), repr(activities) assert activities[0].uri == ns.OLPC_ACTIVITY_PROPS properties = xpath.queryForNodes('/activities/properties', activities[0]) assert properties is None, repr(properties) event = q.expect('stream-iq', iq_type='set') event.stanza['type'] = 'result' event.stanza['to'] = 'test@localhost' event.stanza['from'] = 'test@localhost' stream.send(event.stanza) message = event.stanza activities = xpath.queryForNodes('/iq/pubsub/publish/item/activities', message) assert (activities is not None and len(activities) == 1), repr(activities) assert activities[0].uri == ns.OLPC_ACTIVITIES activity = xpath.queryForNodes('/activities/activity', activities[0]) assert activity is None, repr(activity) q.expect('dbus-return', method='SetProperties') # test sets the title and sets private back to True call_async(q, act_prop_iface, 'SetProperties', room_handle, { 'title': 'I can set the properties too', 'private': False }) event = q.expect('stream-message', to='*****@*****.**') message = event.stanza properties = xpath.queryForNodes('/message/properties', message) assert (properties is not None and len(properties) == 1), repr(properties) assert properties[0].uri == ns.OLPC_ACTIVITY_PROPS assert properties[0]['room'] == '*****@*****.**' assert properties[0]['activity'] == 'foo_id' property = xpath.queryForNodes('/properties/property', properties[0]) assert (property is not None and len(property) == 2), repr(property) seen = set() for p in property: seen.add(p['name']) if p['name'] == 'title': assert p['type'] == 'str' assert str(p) == 'I can set the properties too' elif p['name'] == 'private': assert p['type'] == 'bool' assert str(p) == '0' else: assert False, 'Unexpected property %s' % p['name'] assert 'title' in seen, seen assert 'private' in seen, seen event = q.expect('stream-iq', iq_type='set') event.stanza['type'] = 'result' event.stanza['to'] = 'test@localhost' event.stanza['from'] = 'test@localhost' stream.send(event.stanza) message = event.stanza activities = xpath.queryForNodes('/iq/pubsub/publish/item/activities', message) assert (activities is not None and len(activities) == 1), repr(activities) assert activities[0].uri == ns.OLPC_ACTIVITY_PROPS properties = xpath.queryForNodes('/activities/properties', activities[0]) assert (properties is not None and len(properties) == 1), repr(properties) assert properties[0].uri == ns.OLPC_ACTIVITY_PROPS assert properties[0]['room'] == '*****@*****.**' assert properties[0]['activity'] == 'foo_id' property = xpath.queryForNodes('/properties/property', properties[0]) assert (property is not None and len(property) == 2), repr(property) seen = set() for p in property: seen.add(p['name']) if p['name'] == 'title': assert p['type'] == 'str' assert str(p) == 'I can set the properties too' elif p['name'] == 'private': assert p['type'] == 'bool' assert str(p) == '0' else: assert False, 'Unexpected property %s' % p['name'] assert 'title' in seen, seen assert 'private' in seen, seen event = q.expect('stream-iq', iq_type='set') event.stanza['type'] = 'result' event.stanza['to'] = 'test@localhost' event.stanza['from'] = 'test@localhost' stream.send(event.stanza) message = event.stanza activities = xpath.queryForNodes('/iq/pubsub/publish/item/activities', message) assert (activities is not None and len(activities) == 1), repr(activities) assert activities[0].uri == ns.OLPC_ACTIVITIES activity = xpath.queryForNodes('/activities/activity', activities[0]) assert (activity is not None and len(activity) == 1), repr(activity) assert activity[0]['room'] == '*****@*****.**' assert activity[0]['type'] == 'foo_id' # sic q.expect('dbus-return', method='SetProperties') text_chan.Close() # we must echo the MUC presence so the room will actually close event = q.expect('stream-presence', to='[email protected]/test', presence_type='unavailable') echo_muc_presence(q, stream, event.stanza, 'none', 'participant') event = q.expect('stream-iq', iq_type='set') event.stanza['type'] = 'result' event.stanza['to'] = 'test@localhost' event.stanza['from'] = 'test@localhost' stream.send(event.stanza) message = event.stanza activities = xpath.queryForNodes('/iq/pubsub/publish/item/activities', message) assert (activities is not None and len(activities) == 1), repr(activities) assert activities[0].uri == ns.OLPC_ACTIVITIES activity = xpath.queryForNodes('/activities/activity', activities[0]) assert activity is None, repr(activity) event = q.expect('stream-iq', iq_type='set') event.stanza['type'] = 'result' event.stanza['to'] = 'test@localhost' event.stanza['from'] = 'test@localhost' stream.send(event.stanza) message = event.stanza activities = xpath.queryForNodes('/iq/pubsub/publish/item/activities', message) assert (activities is not None and len(activities) == 1), repr(activities) assert activities[0].uri == ns.OLPC_ACTIVITY_PROPS properties = xpath.queryForNodes('/activities/properties', activities[0]) assert properties is None, repr(properties)
'DBusNames', dbus_interface=cs.PROPERTIES_IFACE) assert names == {tube_self_handle: my_bus_name} tube_chan.Channel.Close() _, _, event = q.expect_many( EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='ChannelClosed'), EventPattern('stream-presence', to='[email protected]/test', presence_type='unavailable')) # we must echo the MUC presence so the room will actually close # and we should wait to make sure gabble has actually parsed our # echo before trying to rejoin echo_muc_presence(q, stream, event.stanza, 'none', 'participant') sync_stream(q, stream) # rejoin the room call_async( q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: '*****@*****.**' }) q.expect('stream-presence', to='[email protected]/test') # Bob is in the room and in the tube bob_in_tube()
assert removed == [bob_handle] names = tube_chan.Get(cs.CHANNEL_TYPE_DBUS_TUBE, "DBusNames", dbus_interface=cs.PROPERTIES_IFACE) assert names == {tube_self_handle: my_bus_name} chan_iface.Close() q.expect_many(EventPattern("dbus-signal", signal="Closed"), EventPattern("dbus-signal", signal="ChannelClosed")) # leave the room text_chan.Close() # we must echo the MUC presence so the room will actually close # and we should wait to make sure gabble has actually parsed our # echo before trying to rejoin event = q.expect("stream-presence", to="[email protected]/test", presence_type="unavailable") echo_muc_presence(q, stream, event.stanza, "none", "participant") sync_stream(q, stream) q.expect_many(EventPattern("dbus-signal", signal="Closed"), EventPattern("dbus-signal", signal="ChannelClosed")) # rejoin the room call_async( q, conn.Requests, "CreateChannel", { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: "*****@*****.**", }, )
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) exv = q.expect('dbus-signal', signal='NewChannels') channels = exv.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 as e: assertEquals(e.get_dbus_name(), cs.INVALID_ARGUMENT) else: assert False # offer the tube call_async(q, tube_chan.DBusTube, 'Offer', sample_parameters, access_control) presence_event, return_event, status_event, dbus_changed_event = q.expect_many( EventPattern('stream-presence', to='[email protected]/test', predicate=lambda e: t.presence_contains_tube(e)), EventPattern('dbus-return', method='Offer'), EventPattern('dbus-signal', signal='TubeChannelStateChanged', args=[cs.TUBE_CHANNEL_STATE_OPEN]), EventPattern('dbus-signal', signal='DBusNamesChanged', interface=cs.CHANNEL_TYPE_DBUS_TUBE)) tube_self_handle = tube_chan.Properties.Get(cs.CHANNEL_IFACE_GROUP, 'SelfHandle') assert tube_self_handle != 0 # handle presence_event # We announce our newly created tube in our muc presence presence = presence_event.stanza dbus_stream_id, my_bus_name, dbus_tube_id = check_tube_in_presence( presence, '[email protected]/test') # handle dbus_changed_event added, removed = dbus_changed_event.args assert added == {tube_self_handle: my_bus_name} assert removed == [] dbus_tube_adr = return_event.value[0] bob_bus_name = ':2.Ym9i' bob_handle = conn.get_contact_handle_sync('[email protected]/bob') def bob_in_tube(): presence = elem('presence', from_='[email protected]/bob', to='*****@*****.**')( elem('x', xmlns=ns.MUC_USER), elem('tubes', xmlns=ns.TUBES)( elem('tube', type='dbus', initiator='[email protected]/test', service='com.example.TestCase', id=str(dbus_tube_id))(elem('parameters')( elem('parameter', name='ay', type='bytes')(u'aGVsbG8='), elem('parameter', name='s', type='str')(u'hello'), elem('parameter', name='i', type='int')(u'-123'), elem('parameter', name='u', type='uint')(u'123'))))) # have to add stream-id and dbus-name attributes manually as we can't use # keyword with '-'... tube_node = xpath.queryForNodes('/presence/tubes/tube', presence)[0] tube_node['stream-id'] = dbus_stream_id tube_node['dbus-name'] = bob_bus_name stream.send(presence) # Bob joins the tube bob_in_tube() dbus_changed_event = q.expect('dbus-signal', signal='DBusNamesChanged', interface=cs.CHANNEL_TYPE_DBUS_TUBE) added, removed = dbus_changed_event.args assert added == {bob_handle: bob_bus_name} assert removed == [] tube = Connection(dbus_tube_adr) fire_signal_on_tube(q, tube, '*****@*****.**', dbus_stream_id, my_bus_name) names = tube_chan.Get(cs.CHANNEL_TYPE_DBUS_TUBE, 'DBusNames', dbus_interface=cs.PROPERTIES_IFACE) assert names == {tube_self_handle: my_bus_name, bob_handle: bob_bus_name} # Bob leave the tube presence = elem('presence', from_='[email protected]/bob', to='*****@*****.**')(elem('x', xmlns=ns.MUC_USER), elem('tubes', xmlns=ns.TUBES)) stream.send(presence) dbus_changed_event = q.expect('dbus-signal', signal='DBusNamesChanged', interface=cs.CHANNEL_TYPE_DBUS_TUBE) added, removed = dbus_changed_event.args assert added == {} assert removed == [bob_handle] names = tube_chan.Get(cs.CHANNEL_TYPE_DBUS_TUBE, 'DBusNames', dbus_interface=cs.PROPERTIES_IFACE) assert names == {tube_self_handle: my_bus_name} tube_chan.Channel.Close() _, _, event = q.expect_many( EventPattern('dbus-signal', signal='Closed'), EventPattern('dbus-signal', signal='ChannelClosed'), EventPattern('stream-presence', to='[email protected]/test', presence_type='unavailable')) # we must echo the MUC presence so the room will actually close # and we should wait to make sure gabble has actually parsed our # echo before trying to rejoin echo_muc_presence(q, stream, event.stanza, 'none', 'participant') sync_stream(q, stream) # rejoin the room call_async( q, conn.Requests, 'CreateChannel', { cs.CHANNEL_TYPE: cs.CHANNEL_TYPE_TEXT, cs.TARGET_HANDLE_TYPE: cs.HT_ROOM, cs.TARGET_ID: '*****@*****.**' }) q.expect('stream-presence', to='[email protected]/test') # Bob is in the room and in the tube bob_in_tube() # Send presence for own membership of room. stream.send(make_muc_presence('none', 'participant', muc, 'test')) def new_tube(e): path, props = e.args[0][0] return props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_DBUS_TUBE def new_text(e): path, props = e.args[0][0] return props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT # tube and text is created text_event, tube_event = q.expect_many( EventPattern('dbus-signal', signal='NewChannels', predicate=new_text), EventPattern('dbus-signal', signal='NewChannels', predicate=new_tube)) channels = exv.args[0] tube_path, props = tube_event.args[0][0] assertEquals(cs.CHANNEL_TYPE_DBUS_TUBE, props[cs.CHANNEL_TYPE]) assertEquals('[email protected]/test', props[cs.INITIATOR_ID]) assertEquals(False, props[cs.REQUESTED]) assertEquals(cs.HT_ROOM, props[cs.TARGET_HANDLE_TYPE]) assertEquals('com.example.TestCase', props[cs.DBUS_TUBE_SERVICE_NAME]) _, props = text_event.args[0][0] assertEquals(cs.CHANNEL_TYPE_TEXT, props[cs.CHANNEL_TYPE]) assertEquals(True, props[cs.REQUESTED]) # tube is local-pending tube_chan = bus.get_object(conn.bus_name, tube_path) state = tube_chan.Get(cs.CHANNEL_IFACE_TUBE, 'State', dbus_interface=dbus.PROPERTIES_IFACE) assertEquals(cs.TUBE_STATE_LOCAL_PENDING, state)
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) buddy_iface = dbus.Interface(conn, 'org.laptop.Telepathy.BuddyInfo') act_prop_iface = dbus.Interface(conn, 'org.laptop.Telepathy.ActivityProperties') bob_handle = conn.RequestHandles(1, ['bob@localhost'])[0] # Bob invites us to a chatroom, pre-seeding properties message = domish.Element(('jabber:client', 'message')) message['from'] = 'bob@localhost' message['to'] = 'test@localhost' properties = message.addElement( (ns.OLPC_ACTIVITY_PROPS, 'properties')) properties['room'] = '*****@*****.**' properties['activity'] = 'foo_id' property = properties.addElement((None, 'property')) property['type'] = 'str' property['name'] = 'title' property.addContent('From the invitation') property = properties.addElement((None, 'property')) property['type'] = 'bool' property['name'] = 'private' property.addContent('1') stream.send(message) message = domish.Element((None, 'message')) message['from'] = '*****@*****.**' message['to'] = 'test@localhost' x = message.addElement((ns.MUC_USER, 'x')) invite = x.addElement((None, 'invite')) invite['from'] = 'bob@localhost' reason = invite.addElement((None, 'reason')) reason.addContent('No good reason') stream.send(message) event = q.expect('dbus-signal', signal='NewChannel') assert event.args[1] == cs.CHANNEL_TYPE_TEXT assert event.args[2] == 2 # handle type assert event.args[3] == 1 # handle room_handle = 1 text_chan = bus.get_object(conn.bus_name, event.args[0]) chan_iface = dbus.Interface(text_chan, cs.CHANNEL) group_iface = dbus.Interface(text_chan, cs.CHANNEL_IFACE_GROUP) members = group_iface.GetAllMembers()[0] local_pending = group_iface.GetAllMembers()[1] remote_pending = group_iface.GetAllMembers()[2] assert len(members) == 1 assert conn.InspectHandles(1, members)[0] == 'bob@localhost' bob_handle = members[0] assert len(local_pending) == 1 # FIXME: the username-part-is-nickname assumption assert conn.InspectHandles(1, local_pending)[0] == \ '[email protected]/test' assert len(remote_pending) == 0 room_self_handle = group_iface.GetSelfHandle() assert room_self_handle == local_pending[0] # by now, we should have picked up the extra activity properties buddy_iface = dbus.Interface(conn, 'org.laptop.Telepathy.BuddyInfo') call_async(q, buddy_iface, 'GetActivities', bob_handle) event = q.expect('stream-iq', iq_type='get', to='bob@localhost') # Bob still has no (public) activities event.stanza['type'] = 'result' event.stanza['to'] = 'test@localhost' event.stanza['from'] = 'bob@localhost' stream.send(event.stanza) event = q.expect('dbus-return', method='GetActivities') assert event.value == ([('foo_id', room_handle)],) props = act_prop_iface.GetProperties(room_handle) assert len(props) == 2 assert props['title'] == 'From the invitation' assert props['private'] == True # Now Bob changes the properties message = domish.Element(('jabber:client', 'message')) message['from'] = 'bob@localhost' message['to'] = 'test@localhost' properties = message.addElement( (ns.OLPC_ACTIVITY_PROPS, 'properties')) properties['room'] = '*****@*****.**' properties['activity'] = 'foo_id' property = properties.addElement((None, 'property')) property['type'] = 'str' property['name'] = 'title' property.addContent('Mushroom, mushroom') property = properties.addElement((None, 'property')) property['type'] = 'bool' property['name'] = 'private' property.addContent('0') stream.send(message) event = q.expect('dbus-signal', signal='ActivityPropertiesChanged') assert event.args == [room_handle, {'title': 'Mushroom, mushroom', 'private': False }] assert act_prop_iface.GetProperties(room_handle) == \ event.args[1] # OK, now accept the invitation call_async(q, group_iface, 'AddMembers', [room_self_handle], 'Oh, OK then') q.expect_many( EventPattern('stream-presence', to='[email protected]/test'), EventPattern('dbus-signal', signal='MembersChanged', args=['', [], [bob_handle], [], [room_self_handle], 0, cs.GC_REASON_INVITED]), EventPattern('dbus-return', method='AddMembers'), ) # Send presence for own membership of room. stream.send(make_muc_presence('owner', 'moderator', '*****@*****.**', 'test')) event = q.expect('dbus-signal', signal='MembersChanged') assert event.args == ['', [room_self_handle], [], [], [], 0, 0] call_async(q, buddy_iface, 'SetActivities', [('foo_id', room_handle)]) event = q.expect('stream-iq', iq_type='set') # Now that it's not private, it'll go in my PEP event.stanza['type'] = 'result' event.stanza['to'] = 'test@localhost' event.stanza['from'] = 'test@localhost' stream.send(event.stanza) q.expect('dbus-return', method='SetActivities') # Bob changes the properties and tells the room he's done so message = domish.Element(('jabber:client', 'message')) message['from'] = '[email protected]/bob' message['to'] = '*****@*****.**' properties = message.addElement( (ns.OLPC_ACTIVITY_PROPS, 'properties')) properties['activity'] = 'foo_id' property = properties.addElement((None, 'property')) property['type'] = 'str' property['name'] = 'title' property.addContent('Badger badger badger') property = properties.addElement((None, 'property')) property['type'] = 'bool' property['name'] = 'private' property.addContent('0') stream.send(message) event = q.expect('stream-iq', iq_type='set') message = event.stanza activities = xpath.queryForNodes('/iq/pubsub/publish/item/activities', message) assert (activities is not None and len(activities) == 1), repr(activities) assert activities[0].uri == ns.OLPC_ACTIVITY_PROPS properties = xpath.queryForNodes('/activities/properties', activities[0]) assert (properties is not None and len(properties) == 1), repr(properties) assert properties[0].uri == ns.OLPC_ACTIVITY_PROPS assert properties[0]['room'] == '*****@*****.**' assert properties[0]['activity'] == 'foo_id' property = xpath.queryForNodes('/properties/property', properties[0]) assert (property is not None and len(property) == 2), repr(property) seen = set() for p in property: seen.add(p['name']) if p['name'] == 'title': assert p['type'] == 'str' assert str(p) == 'Badger badger badger' elif p['name'] == 'private': assert p['type'] == 'bool' assert str(p) == '0' else: assert False, 'Unexpected property %s' % p['name'] assert 'title' in seen, seen assert 'private' in seen, seen event.stanza['type'] = 'result' event.stanza['to'] = 'test@localhost' event.stanza['from'] = 'test@localhost' stream.send(event.stanza) act_prop_iface = dbus.Interface(conn, 'org.laptop.Telepathy.ActivityProperties') # test sets the title and sets private back to True call_async(q, act_prop_iface, 'SetProperties', room_handle, {'title': 'I can set the properties too', 'private': True}) event = q.expect('stream-message', to='*****@*****.**') message = event.stanza properties = xpath.queryForNodes('/message/properties', message) assert (properties is not None and len(properties) == 1), repr(properties) assert properties[0].uri == ns.OLPC_ACTIVITY_PROPS assert properties[0]['room'] == '*****@*****.**' assert properties[0]['activity'] == 'foo_id' property = xpath.queryForNodes('/properties/property', properties[0]) assert (property is not None and len(property) == 2), repr(property) seen = set() for p in property: seen.add(p['name']) if p['name'] == 'title': assert p['type'] == 'str' assert str(p) == 'I can set the properties too' elif p['name'] == 'private': assert p['type'] == 'bool' assert str(p) == '1' else: assert False, 'Unexpected property %s' % p['name'] assert 'title' in seen, seen assert 'private' in seen, seen event = q.expect('stream-iq', iq_type='set') event.stanza['type'] = 'result' event.stanza['to'] = 'test@localhost' event.stanza['from'] = 'test@localhost' stream.send(event.stanza) message = event.stanza activities = xpath.queryForNodes('/iq/pubsub/publish/item/activities', message) assert (activities is not None and len(activities) == 1), repr(activities) assert activities[0].uri == ns.OLPC_ACTIVITY_PROPS properties = xpath.queryForNodes('/activities/properties', activities[0]) assert properties is None, repr(properties) event = q.expect('stream-iq', iq_type='set') event.stanza['type'] = 'result' event.stanza['to'] = 'test@localhost' event.stanza['from'] = 'test@localhost' stream.send(event.stanza) message = event.stanza activities = xpath.queryForNodes('/iq/pubsub/publish/item/activities', message) assert (activities is not None and len(activities) == 1), repr(activities) assert activities[0].uri == ns.OLPC_ACTIVITIES activity = xpath.queryForNodes('/activities/activity', activities[0]) assert activity is None, repr(activity) q.expect('dbus-return', method='SetProperties') # test sets the title and sets private back to True call_async(q, act_prop_iface, 'SetProperties', room_handle, {'title': 'I can set the properties too', 'private': False}) event = q.expect('stream-message', to='*****@*****.**') message = event.stanza properties = xpath.queryForNodes('/message/properties', message) assert (properties is not None and len(properties) == 1), repr(properties) assert properties[0].uri == ns.OLPC_ACTIVITY_PROPS assert properties[0]['room'] == '*****@*****.**' assert properties[0]['activity'] == 'foo_id' property = xpath.queryForNodes('/properties/property', properties[0]) assert (property is not None and len(property) == 2), repr(property) seen = set() for p in property: seen.add(p['name']) if p['name'] == 'title': assert p['type'] == 'str' assert str(p) == 'I can set the properties too' elif p['name'] == 'private': assert p['type'] == 'bool' assert str(p) == '0' else: assert False, 'Unexpected property %s' % p['name'] assert 'title' in seen, seen assert 'private' in seen, seen event = q.expect('stream-iq', iq_type='set') event.stanza['type'] = 'result' event.stanza['to'] = 'test@localhost' event.stanza['from'] = 'test@localhost' stream.send(event.stanza) message = event.stanza activities = xpath.queryForNodes('/iq/pubsub/publish/item/activities', message) assert (activities is not None and len(activities) == 1), repr(activities) assert activities[0].uri == ns.OLPC_ACTIVITY_PROPS properties = xpath.queryForNodes('/activities/properties', activities[0]) assert (properties is not None and len(properties) == 1), repr(properties) assert properties[0].uri == ns.OLPC_ACTIVITY_PROPS assert properties[0]['room'] == '*****@*****.**' assert properties[0]['activity'] == 'foo_id' property = xpath.queryForNodes('/properties/property', properties[0]) assert (property is not None and len(property) == 2), repr(property) seen = set() for p in property: seen.add(p['name']) if p['name'] == 'title': assert p['type'] == 'str' assert str(p) == 'I can set the properties too' elif p['name'] == 'private': assert p['type'] == 'bool' assert str(p) == '0' else: assert False, 'Unexpected property %s' % p['name'] assert 'title' in seen, seen assert 'private' in seen, seen event = q.expect('stream-iq', iq_type='set') event.stanza['type'] = 'result' event.stanza['to'] = 'test@localhost' event.stanza['from'] = 'test@localhost' stream.send(event.stanza) message = event.stanza activities = xpath.queryForNodes('/iq/pubsub/publish/item/activities', message) assert (activities is not None and len(activities) == 1), repr(activities) assert activities[0].uri == ns.OLPC_ACTIVITIES activity = xpath.queryForNodes('/activities/activity', activities[0]) assert (activity is not None and len(activity) == 1), repr(activity) assert activity[0]['room'] == '*****@*****.**' assert activity[0]['type'] == 'foo_id' # sic q.expect('dbus-return', method='SetProperties') chan_iface.Close() # we must echo the MUC presence so the room will actually close event = q.expect('stream-presence', to='[email protected]/test', presence_type='unavailable') echo_muc_presence(q, stream, event.stanza, 'none', 'participant') event = q.expect('stream-iq', iq_type='set') event.stanza['type'] = 'result' event.stanza['to'] = 'test@localhost' event.stanza['from'] = 'test@localhost' stream.send(event.stanza) message = event.stanza activities = xpath.queryForNodes('/iq/pubsub/publish/item/activities', message) assert (activities is not None and len(activities) == 1), repr(activities) assert activities[0].uri == ns.OLPC_ACTIVITIES activity = xpath.queryForNodes('/activities/activity', activities[0]) assert activity is None, repr(activity) event = q.expect('stream-iq', iq_type='set') event.stanza['type'] = 'result' event.stanza['to'] = 'test@localhost' event.stanza['from'] = 'test@localhost' stream.send(event.stanza) message = event.stanza activities = xpath.queryForNodes('/iq/pubsub/publish/item/activities', message) assert (activities is not None and len(activities) == 1), repr(activities) assert activities[0].uri == ns.OLPC_ACTIVITY_PROPS properties = xpath.queryForNodes('/activities/properties', activities[0]) assert properties is None, repr(properties)